import { forceArgs } from "../cli/forceArgs.ts";
import { cliAlert, cliLog } from "../cli/prompts.ts";
import { colorize } from "../cli/style.ts";
import type { TerminalBlock } from "../cli/TerminalLayout.ts";
import type { ITool } from "../types.ts";
import { loadPdfForm } from "../util/saveLoadPdf.ts";

function getCaseSyntaxPatternByFileExtension(
  extenstion: string,
  field: string,
) {
  switch (extenstion.trim().toLowerCase().replace(".", "")) {
    case "cs":
    case "js":
    case "ts":
    default:
      return `(?<!//\s?)case ?"${field.replace(/\[\d\]/, `\\[\\?|\\d+\\]`)}"`;
  }
}

class CheckCode implements ITool {
  name = "checkcode";
  description = "Checks if form fields are present in a given code file";
  private block?: TerminalBlock;
  setBlock(block: TerminalBlock) {
    this.block = block;
    this.block.setPreserveHistory(true);
  }
  async help() {
    cliLog("Usage: checkcode <pdfPath> <csPath>", this.block);
    await cliAlert("", this.block);
  }
  async run(pdfPath: string, codePaths: string) {
    [pdfPath, codePaths] = await forceArgs([pdfPath, codePaths], [
      "Please provide path to PDF file:",
      "Please provide path(s) to code file(s) (comma separated for multiple):",
    ], this.block);

    const form = await loadPdfForm(pdfPath);

    const fields = form.getFields();
    const codeFiles: [string, string][] = codePaths.split(",").map((
      c,
    ) => [c, Deno.readTextFileSync(c.trim())]);

    const fieldNames: string[] = fields.map((f) => f.getName())
      .filter((f) => !f.toLowerCase().includes("signature"));
    let unfound = fieldNames.slice();

    for (const [path, content] of codeFiles) {
      unfound = unfound.filter((f) => {
        const rx = new RegExp(
          getCaseSyntaxPatternByFileExtension(path.split(".").at(-1) ?? "", f),
        );
        return rx.test(content);
      });
    }

    if (unfound.length) {
      cliLog(
        colorize(
          "The following field names are not present in the CS code",
          "red",
        ),
        this.block,
      );
      cliLog(unfound, this.block);
      await cliAlert("Your princess is in another castle...", this.block);
    } else {
      cliLog(colorize("All form fields present", "green"), this.block);
      await cliAlert("Ok!", this.block);
    }
  }
}

export default new CheckCode();
