// Command: Discover Builtin Candidates in TXT Folder
// Scans all TXT files in a folder, extracts function calls not recognized as builtins/known, and exports a report.

import * as vscode from "vscode";
import * as path from "path";
import { getAllKnownFunctions } from "../../../core/src/builtins/functionsRegistry.js";
import { parseFunctionCalls } from "../../../core/src/parser.js";

const MAX_SCAN_TIME_MS = 60_000; // bail out after 60 s regardless of file count

async function chooseTargetFolder() {
  const folders = vscode.workspace.workspaceFolders;
  if (!folders || folders.length === 0) {
    vscode.window.showErrorMessage('No workspace folder open.');
    return undefined;
  }
  if (folders.length === 1) return folders[0].uri;
  const pick = await vscode.window.showWorkspaceFolderPick();
  return pick ? pick.uri : undefined;
}

async function chooseOutputFile(defaultName) {
  const uri = await vscode.window.showSaveDialog({
    saveLabel: 'Export Discovery Report',
    defaultUri: vscode.Uri.file(path.join(
      vscode.workspace.workspaceFolders?.[0]?.uri.fsPath ?? "",
      defaultName
    )),
    filters: { 'JSON': ['json'], 'CSV': ['csv'] }
  });
  return uri;
}

async function runDiscoveryReport() {
  const folderUri = await chooseTargetFolder();
  if (!folderUri) return;
  const txtFiles = await vscode.workspace.findFiles(
    new vscode.RelativePattern(folderUri, '**/*.{txt,TXT}'),
    '**/node_modules/**'
  );
  if (txtFiles.length === 0) {
    vscode.window.showInformationMessage('No TXT files found in selected folder.');
    return;
  }
  const known = new Set(getAllKnownFunctions().map(f => f.toLowerCase()));
  const discovered = new Map(); // name -> { files: Set, count }

  let cancelled = false;
  let timedOut = false;
  await vscode.window.withProgress(
    {
      location: vscode.ProgressLocation.Notification,
      title: `Acurity: Scanning ${txtFiles.length} files for unknown symbols`,
      cancellable: true
    },
    async (progress, token) => {
      const startMs = Date.now();
      for (let i = 0; i < txtFiles.length; i++) {
        if (token.isCancellationRequested) {
          cancelled = true;
          break;
        }
        if (Date.now() - startMs > MAX_SCAN_TIME_MS) {
          timedOut = true;
          break;
        }
        const file = txtFiles[i];
        progress.report({
          message: `${i + 1}/${txtFiles.length} ${path.basename(file.fsPath)}`,
          increment: 100 / txtFiles.length
        });
        const doc = await vscode.workspace.openTextDocument(file);
        const calls = parseFunctionCalls(doc.getText());
        for (const fn of calls) {
          const name = fn.toLowerCase();
          if (!known.has(name)) {
            if (!discovered.has(name)) discovered.set(name, { files: new Set(), count: 0 });
            discovered.get(name).files.add(path.relative(folderUri.fsPath, file.fsPath));
            discovered.get(name).count++;
          }
        }
      }
    }
  );

  if (cancelled) return;
  if (timedOut) {
    vscode.window.showWarningMessage(
      `Acurity: Discovery scan timed out after ${MAX_SCAN_TIME_MS / 1000}s. Results may be incomplete.`
    );
  }

  if (discovered.size === 0) {
    vscode.window.showInformationMessage('No unknown function calls discovered.');
    return;
  }

  // Prepare report
  const reportArr = Array.from(discovered.entries()).map(([name, info]) => ({
    function: name,
    count: info.count,
    files: Array.from(info.files)
  }));

  // Ask user for output file
  const outUri = await chooseOutputFile('builtin-discovery-report.json');
  if (!outUri) return;
  let outData;
  if (outUri.fsPath.endsWith('.csv')) {
    // CSV
    outData = 'function,count,files\n' + reportArr.map(r => `${r.function},${r.count},"${r.files.join(';')}"`).join('\n');
  } else {
    // JSON
    outData = JSON.stringify(reportArr, null, 2);
  }
  try {
    await vscode.workspace.fs.writeFile(outUri, Buffer.from(outData, 'utf8'));
    vscode.window.showInformationMessage(`Discovery report exported: ${outUri.fsPath}`);
  } catch (err) {
    vscode.window.showErrorMessage(`Discovery report: failed to write ${outUri.fsPath}: ${err.message}`);
  }
}

export {
  runDiscoveryReport
};
