// the docs as markdown, for agents: every page's own markdown next to it (/configuration/index.md),
// llms.txt listing them all (llmstxt.org), and llms-full.txt with every page in one file. the
// markdown is docs/ as written, with links between docs turned into links to these copies.

import fs from "node:fs";
import path from "node:path";
import { DOCS_DIR, frontmatter, type Doc } from "./docs";
import { SECTIONS } from "./nav";
import { cardFor } from "./og";
import { HOME_DESCRIPTION } from "./site";

/** where a page's markdown is served */
export const markdownPath = (doc: Doc) => `${doc.url}index.md`;

/** the specs: long internal design notes, which llms.txt puts under "Optional" */
const OPTIONAL = new Set(["internals"]);

export function markdownFor(doc: Doc, docs: Map<string, Doc>, site: URL): string {
  const { body } = frontmatter(fs.readFileSync(path.join(DOCS_DIR, `${doc.id}.md`), "utf8"));
  const dir = path.posix.dirname(doc.id);
  // relative links to another doc, inline or as a reference definition
  const linked = body.replace(/(\]\(|^\[[^\]]+\]:\s*)([^)\s:]+\.md)(#[^)\s]*)?/gm, (whole, lead, target, hash = "") => {
    const id = path.posix.normalize(path.posix.join(dir === "." ? "" : dir, target)).slice(0, -3);
    const to = docs.get(id);
    return to ? `${lead}${new URL(markdownPath(to), site)}${hash}` : whole;
  });
  const text = linked.trim();
  return `${text.startsWith("# ") ? text : `# ${doc.title}\n\n${text}`}\n`;
}

/** every doc in the order the site lists them, each section's index first */
function inOrder(docs: Map<string, Doc>) {
  return SECTIONS.map((s) => ({
    section: s,
    docs: [s.index, ...s.pages.map((p) => p.doc)].filter((id): id is string => !!id).map((id) => docs.get(id)!),
  }));
}

export function llmsTxt(docs: Map<string, Doc>, site: URL): string {
  const entry = (d: Doc) => {
    const { title, description } = cardFor(d, docs);
    return `- [${title}](${new URL(markdownPath(d), site)})${description ? `: ${description}` : ""}`;
  };
  const sections = inOrder(docs);
  const listed = sections.filter(({ section }) => !OPTIONAL.has(section.id));
  const optional = sections.filter(({ section }) => OPTIONAL.has(section.id)).flatMap((s) => s.docs);
  return [
    "# hydrant",
    `> ${HOME_DESCRIPTION}`,
    `every link below is a page of these docs as markdown. the site itself is ${site}, and ${new URL("/llms-full.txt", site)} has every page in one file.`,
    ...listed.map(({ section, docs: ds }) => `## ${section.title}\n\n${ds.map(entry).join("\n")}`),
    ...(optional.length ? [`## Optional\n\n${optional.map(entry).join("\n")}`] : []),
  ].join("\n\n") + "\n";
}

export function llmsFullTxt(docs: Map<string, Doc>, site: URL): string {
  return inOrder(docs)
    .flatMap((s) => s.docs)
    .map((d) => `<!-- ${new URL(d.url, site)} -->\n\n${markdownFor(d, docs, site)}`)
    .join("\n---\n\n");
}

