import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";

const read = (path) => readFileSync(path, "utf8").replace(/\r\n/g, "\n");
const compact = (value) => String(value || "").replace(/\s+/g, " ").trim();

const parseTomlString = (toml, key) => {
  const match = toml.match(new RegExp(`^${key}\\s*=\\s*"([^"]*)"`, "m"));
  return match ? match[1] : "";
};

const parseTomlArray = (toml, key) => {
  const match = toml.match(new RegExp(`^${key}\\s*=\\s*\\[([^\\]]*)\\]`, "m"));
  if (!match) return [];
  return match[1]
    .split(",")
    .map((item) => item.trim().replace(/^"|"$/g, ""))
    .filter(Boolean);
};

const parseBuildchain = () => {
  const toml = read(".buildchain/buildchain.toml");
  return {
    title: parseTomlString(toml, "title"),
    abstract: parseTomlString(toml, "abstract"),
    kind: parseTomlString(toml, "kind"),
    primaryArtifact: parseTomlString(toml, "primary_artifact"),
    artifactPaths: parseTomlArray(toml, "artifact_paths"),
    metadataPaths: parseTomlArray(toml, "metadata_paths"),
    sourcePaths: parseTomlArray(toml, "source_paths"),
    siteConsumers: parseTomlArray(toml, "site_consumers"),
  };
};

const packageInfo = () => JSON.parse(read("package.json"));

const normalizeLatex = (latex) => latex
  .replace(/%.*$/gm, "")
  .replace(/\\begin\{agentguidebox\}/g, "")
  .replace(/\\end\{agentguidebox\}/g, "")
  .replace(/\\begin\{evidenceframe\}/g, "")
  .replace(/\\end\{evidenceframe\}/g, "")
  .replace(/\\begin\{foundationtable\}/g, "")
  .replace(/\\end\{foundationtable\}/g, "")
  .replace(/\\begin\{machinebridgebox\}/g, "")
  .replace(/\\end\{machinebridgebox\}/g, "")
  .replace(/\\begin\{evidenceladder\}/g, "")
  .replace(/\\end\{evidenceladder\}/g, "")
  .replace(/\\agentguidetitle\{([^{}]*)\}/g, "\n**$1**\n")
  .replace(/\\bridgeclaim\{([^{}]*)\}\{([^{}]*)\}/g, "\n**$1 — $2**\n")
  .replace(/\\begin\{agentprompt\}/g, "\n@@AGENT_PROMPT_START@@\n")
  .replace(/\\end\{agentprompt\}/g, "\n@@AGENT_PROMPT_END@@\n")
  .replace(/\\href\{([^{}]*)\}\{([^{}]*)\}/g, "[$2]($1)")
  .replace(/\\calloutbox\{([^{}]*)\}\{([^{}]*)\}/g, "\n**$1**\n\n$2\n")
  .replace(/\\flowbox\{([^{}]*)\}/g, "\n**$1**\n")
  .replace(/\\layerbox\{([^{}]*)\}\{([^{}]*)\}/g, "\n**$1**\n\n$2\n")
  .replace(/\\begin\{figure\}(?:\[[^\]]*\])?/g, "")
  .replace(/\\end\{figure\}/g, "")
  .replace(/\\includegraphics(?:\[[^\]]*\])?\{[^{}]*\}/g, "")
  .replace(/\\caption\{([^{}]*)\}/g, "\n*$1*\n")
  .replace(/\\label\{[^{}]*\}/g, "")
  .replace(/\\begin\{tabularx\}\{[^{}]*\}\{[^{}]*\}/g, "")
  .replace(/\\begin\{tabularx\}\{[^{}]*\}\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g, "")
  .replace(/\\end\{tabularx\}/g, "")
  .replace(/\\begin\{tabular\}\{[^{}]*\}/g, "")
  .replace(/\\end\{tabular\}/g, "")
  .replace(/\\begin\{center\}/g, "")
  .replace(/\\end\{center\}/g, "")
  .replace(/\\toprule|\\midrule|\\bottomrule/g, "")
  .replace(/\\begin\{itemize\}\[leftmargin=\*\]/g, "")
  .replace(/\\begin\{itemize\}/g, "")
  .replace(/\\end\{itemize\}/g, "")
  .replace(/\\begin\{enumerate\}\[leftmargin=\*\]/g, "")
  .replace(/\\begin\{enumerate\}/g, "")
  .replace(/\\end\{enumerate\}/g, "")
  .replace(/\\item\s+/g, "- ")
  .replace(/\\subsection\{([^}]*)\}/g, "\n## $1\n")
  .replace(/\\section\{([^}]*)\}/g, "# $1\n")
  .replace(/\\textit\{([^}]*)\}/g, "$1")
  .replace(/\\textbf\{([^}]*)\}/g, "$1")
  .replace(/\s*&\s*/g, " | ")
  .replace(/\s*\\\\\s*/g, "\n")
  .replace(/``/g, "\"")
  .replace(/''/g, "\"")
  .replace(/~/g, " ")
  .replace(/\\&/g, "&")
  .replace(/\\_/g, "_")
  .replace(/\\-/g, "-")
  .replace(/\\[a-zA-Z]+\*?(?:\[[^\]]*\])?(?:\{([^{}]*)\})?/g, (_, inner) => inner || "")
  .replace(/[{}]/g, "")
  .replace(/@@AGENT_PROMPT_START@@/g, "```text")
  .replace(/@@AGENT_PROMPT_END@@/g, "```")
  .replace(/[ \t]+\n/g, "\n")
  .replace(/\n{3,}/g, "\n\n")
  .trim();

const parseSection = (path) => {
  const latex = read(path);
  const sectionMatch = latex.match(/\\section\{([^}]*)\}/);
  const title = sectionMatch ? sectionMatch[1] : path;
  const bodyLatex = sectionMatch ? latex.slice(sectionMatch.index + sectionMatch[0].length) : latex;
  const subsections = [...latex.matchAll(/\\subsection\{([^}]*)\}/g)].map((match) => match[1]);
  const markdown = normalizeLatex(latex);
  const paragraphs = normalizeLatex(bodyLatex)
    .split(/\n{2,}/)
    .map((block) => compact(block.replace(/^##\s+.*$/gm, "")))
    .filter(Boolean);
  return {
    id: path.split("/").pop().replace(/\.tex$/, ""),
    title,
    sourcePath: path,
    subsections,
    summary: paragraphs[0] || "",
    markdown,
  };
};

const sectionPaths = () => {
  const main = read("paper/main.tex");
  return [...main.matchAll(/\\input\{sections\/([^}]*)\}/g)].map((match) => `paper/sections/${match[1]}.tex`);
};

const parseReferences = () => {
  const bib = read("paper/references.bib");
  return [...bib.matchAll(/@misc\{([^,]+),([\s\S]*?)\n\}/g)].map((match) => {
    const body = match[2];
    const field = (name) => {
      const fieldMatch = body.match(new RegExp(`${name}\\s*=\\s*\\{([^}]*)\\}`, "m"));
      return fieldMatch ? fieldMatch[1] : "";
    };
    return {
      key: match[1],
      title: field("title"),
      author: field("author"),
      year: field("year"),
      note: field("note"),
    };
  });
};

const buildPrinciples = (sections) => {
  const principles = sections.find((section) => section.title === "Principles");
  if (!principles) return [];
  const latex = read(principles.sourcePath);
  return [...latex.matchAll(/(KFD-[0-9]+)\s*&\s*([^\\]+)\\\\/g)].map((match) => ({
    id: match[1],
    text: match[2].trim(),
  }));
};

const siteSection = (section, role, presentation, priority) => ({
  id: section.id,
  sourcePath: section.sourcePath,
  title: section.title,
  role,
  presentation,
  priority,
  summary: section.summary,
  markdown: section.markdown,
});

export const buildSiteBundles = () => {
  const buildchain = parseBuildchain();
  const pkg = packageInfo();
  const sections = sectionPaths().map(parseSection);
  const references = parseReferences();
  const principles = buildPrinciples(sections);
  const source = {
    package: pkg.name,
    packageVersion: pkg.version,
    repository: pkg.repository?.url || "",
    titleSource: ".buildchain/buildchain.toml",
    paperEntrypoint: "paper/main.tex",
    sectionSources: sections.map((section) => section.sourcePath),
    bibliography: "paper/references.bib",
    buildchainConfig: ".buildchain/buildchain.toml",
  };

  const brand = {
    schemaVersion: 1,
    contract: "kungfu-white-paper-brand-site-bundle",
    consumer: "kungfu.tech",
    source,
    routes: {
      canonicalHost: "kungfu.tech",
      canonicalPath: "/whitepaper/kungfu-real-world-agent-work",
      canonicalUrl: "https://kungfu.tech/whitepaper/kungfu-real-world-agent-work",
      indexPath: "/whitepaper",
      indexUrl: "https://kungfu.tech/whitepaper",
      pdfPath: "/whitepaper/kungfu-white-paper.pdf",
      pdfUrl: "https://kungfu.tech/whitepaper/kungfu-white-paper.pdf",
      pdfAliases: ["/whitepaper/kungfu-real-world-agent-work.pdf"],
      evidenceUrl: "https://papers.libkungfu.dev/kungfu-product-white-paper",
    },
    hero: {
      title: buildchain.title,
      eyebrow: "Kungfu White Paper",
      lead: buildchain.abstract,
      stance: "Work should not disappear when a chat ends, restart when an Agent changes, or become complete merely because a process exits.",
      primaryCta: {
        label: "Read the white paper",
        href: "https://kungfu.tech/whitepaper/kungfu-real-world-agent-work",
      },
      secondaryCta: {
        label: "Inspect evidence",
        href: "https://papers.libkungfu.dev/kungfu-product-white-paper",
      },
    },
    positioning: {
      audience: ["agent users", "developers", "operators", "researchers", "early product evaluators"],
      productClaim: "Kungfu is a local-first product and runtime that preserves governed Work across replaceable Agent processes.",
      philosophicalClaim: "Facts must not drift, trust must start from facts, and cooperation must start from trusted value.",
      proofPath: "Agent Work Lab, exact artifact evidence, real Project continuity, and explicit public claim boundaries.",
    },
    principles,
    homepageSections: [
      siteSection(sections.find((section) => section.title === "Executive Summary"), "first-screen", "executive-summary", 10),
      siteSection(sections.find((section) => section.title === "The Problem"), "primary", "problem-statement", 20),
      siteSection(sections.find((section) => section.title === "Product Thesis"), "primary", "product-thesis", 30),
      siteSection(sections.find((section) => section.title === "Principles"), "primary", "kfd-principles", 40),
      siteSection(sections.find((section) => section.title === "Roadmap"), "support", "roadmap", 50),
      siteSection(sections.find((section) => section.title === "Conclusion"), "support", "closing-thesis", 60),
    ].filter(Boolean),
    displayPlan: {
      firstScreen: ["hero", "Executive Summary"],
      primary: ["The Problem", "Product Thesis", "Principles"],
      support: ["Roadmap", "Conclusion"],
      hideFromBrandPage: ["full bibliography", "source bundle internals", "raw Buildchain passport fields"],
    },
  };

  const evidence = {
    schemaVersion: 1,
    contract: "kungfu-white-paper-evidence-site-bundle",
    consumer: "papers.libkungfu.dev",
    source,
    publication: {
      kind: buildchain.kind,
      title: buildchain.title,
      abstract: buildchain.abstract,
      primaryArtifact: buildchain.primaryArtifact,
      artifactPaths: buildchain.artifactPaths,
      metadataPaths: buildchain.metadataPaths,
      sourcePaths: buildchain.sourcePaths,
      siteConsumers: buildchain.siteConsumers,
    },
    routes: {
      canonicalHost: "papers.libkungfu.dev",
      canonicalPath: "/kungfu-product-white-paper",
      canonicalUrl: "https://papers.libkungfu.dev/kungfu-product-white-paper",
      pdfPath: "/kungfu-product-white-paper/main.pdf",
      pdfUrl: "https://papers.libkungfu.dev/kungfu-product-white-paper/main.pdf",
      sourcePath: "/kungfu-product-white-paper/source.tar.gz",
      sourceUrl: "https://papers.libkungfu.dev/kungfu-product-white-paper/source.tar.gz",
      brandUrl: "https://kungfu.tech/whitepaper/kungfu-real-world-agent-work",
      repositoryUrl: "https://github.com/kungfu-systems/paper-kungfu-product-white-paper",
    },
    sectionMap: sections.map((section, index) => ({
      order: index + 1,
      id: section.id,
      title: section.title,
      sourcePath: section.sourcePath,
      subsections: section.subsections,
      summary: section.summary,
    })),
    references,
    verification: {
      commands: ["make check", "make pdf", "npx -y @kungfu-tech/buildchain@3.0.0 validate --cwd . --json", "npm pack --dry-run --json"],
      buildchainManifestPath: ".buildchain/publication/publication-artifact.json",
      sourceBundlePath: ".buildchain/publication/source.tar.gz",
      residualRisk: "The paper is a draft product white paper; philosophical and product-positioning claims still require human review before launch use.",
    },
  };

  return {
    "site/brand-site.json": brand,
    "site/evidence-site.json": evidence,
    "site/site-bundles.json": {
      schemaVersion: 1,
      contract: "kungfu-white-paper-site-bundles-index",
      source,
      bundles: [
        {
          id: "brand",
          consumer: "kungfu.tech",
          path: "site/brand-site.json",
          contract: brand.contract,
          purpose: "Product and philosophy presentation for the Kungfu main site.",
        },
        {
          id: "evidence",
          consumer: "papers.libkungfu.dev",
          path: "site/evidence-site.json",
          contract: evidence.contract,
          purpose: "Artifact, citation, source, and verification presentation for the paper registry.",
        },
      ],
    },
  };
};

const writeJson = (path, value) => {
  mkdirSync(dirname(path), { recursive: true });
  writeFileSync(path, `${JSON.stringify(value, null, 2)}\n`);
};

if (import.meta.url === `file://${process.argv[1]}`) {
  for (const [path, value] of Object.entries(buildSiteBundles())) {
    writeJson(path, value);
  }
  if (!existsSync("site")) mkdirSync("site", { recursive: true });
  console.log("updated site bundles:");
  for (const path of Object.keys(buildSiteBundles())) {
    console.log(`- ${join(process.cwd(), path)}`);
  }
}
