import { runDocsScript } from "@snapotter/ai";

/** Page count via the docs-profile Python dispatcher (pikepdf). */
export async function pdfPageCountPy(absPath: string): Promise<number> {
  const stdout = await runDocsScript("doc_pagecount", { path: absPath });
  const parsed = JSON.parse(stdout.trim()) as { pages?: number; error?: string };
  if (parsed.error || typeof parsed.pages !== "number") {
    throw new Error(`doc_pagecount failed: ${parsed.error ?? stdout.slice(0, 200)}`);
  }
  return parsed.pages;
}

/** Flatten forms/annotations into page content (PyMuPDF bake). */
export async function pdfFlattenPy(inPath: string, outPath: string): Promise<void> {
  const stdout = await runDocsScript("doc_flatten", { path: inPath, out: outPath });
  const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
  if (parsed.error) {
    throw new Error(`doc_flatten failed: ${parsed.error}`);
  }
}

/** True redaction with verification pass (PyMuPDF search + apply_redactions). */
export async function pdfRedactPy(
  inPath: string,
  outPath: string,
  terms: string[],
  caseSensitive: boolean,
): Promise<{ found: number }> {
  const stdout = await runDocsScript("doc_redact", {
    path: inPath,
    out: outPath,
    terms,
    caseSensitive,
  });
  const parsed = JSON.parse(stdout.trim()) as {
    found?: number;
    verified?: boolean;
    error?: string;
  };
  if (parsed.error) {
    throw new Error(`doc_redact failed: ${parsed.error}`);
  }
  if (typeof parsed.found !== "number") {
    throw new Error(`doc_redact failed: ${stdout.slice(0, 200)}`);
  }
  return { found: parsed.found };
}

/** Extract plain text from a PDF (PyMuPDF get_text). */
export async function pdfTextPy(inPath: string, outTxtPath: string): Promise<{ chars: number }> {
  const stdout = await runDocsScript("doc_text", { path: inPath, out: outTxtPath });
  const parsed = JSON.parse(stdout.trim()) as { chars?: number; error?: string };
  if (parsed.error) {
    throw new Error(`doc_text failed: ${parsed.error}`);
  }
  if (typeof parsed.chars !== "number") {
    throw new Error(`doc_text failed: ${stdout.slice(0, 200)}`);
  }
  return { chars: parsed.chars };
}

/** PDF to DOCX conversion (pdf2docx). Long-running: 5 min timeout. */
export async function pdfToWordPy(inPath: string, outPath: string): Promise<void> {
  const stdout = await runDocsScript(
    "doc_to_word",
    { path: inPath, out: outPath },
    { timeoutMs: 300_000 },
  );
  const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
  if (parsed.error) {
    throw new Error(`doc_to_word failed: ${parsed.error}`);
  }
}

/** Read PDF document metadata (pikepdf docinfo). */
export async function pdfMetadataGetPy(inPath: string): Promise<Record<string, string>> {
  const stdout = await runDocsScript("doc_metadata", { path: inPath, mode: "get" });
  const parsed = JSON.parse(stdout.trim()) as { metadata?: Record<string, string>; error?: string };
  if (parsed.error) {
    throw new Error(`doc_metadata get failed: ${parsed.error}`);
  }
  if (!parsed.metadata || typeof parsed.metadata !== "object") {
    throw new Error(`doc_metadata get failed: ${stdout.slice(0, 200)}`);
  }
  return parsed.metadata;
}

/** Write PDF document metadata (pikepdf docinfo). */
export async function pdfMetadataSetPy(
  inPath: string,
  outPath: string,
  metadata: Record<string, string>,
): Promise<void> {
  const stdout = await runDocsScript("doc_metadata", {
    path: inPath,
    out: outPath,
    mode: "set",
    metadata,
  });
  const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
  if (parsed.error) {
    throw new Error(`doc_metadata set failed: ${parsed.error}`);
  }
}

/** HTML or Markdown to PDF (WeasyPrint, SSRF-hardened). 2 min timeout. */
export async function htmlToPdfPy(
  inPath: string,
  outPath: string,
  mode: "html" | "markdown",
): Promise<void> {
  const stdout = await runDocsScript(
    "doc_html_pdf",
    { path: inPath, out: outPath, mode },
    { timeoutMs: 120_000 },
  );
  const parsed = JSON.parse(stdout.trim()) as { ok?: boolean; error?: string };
  if (parsed.error) {
    throw new Error(`doc_html_pdf failed: ${parsed.error}`);
  }
}
