/**
 * Document writers for the wiki generation pipeline.
 *
 * Handles final document assembly, appendix management, and
 * post-generation Mermaid validation of markdown files.
 */

import { join } from "node:path";
import {
  existsSync,
  readFileSync,
  writeFileSync,
  readdirSync,
  statSync,
} from "node:fs";
import { downgradeInvalidMermaidBlocksInMarkdown } from "../mermaid-validation";
import {
  MANAGED_APPENDIX_START,
  MANAGED_APPENDIX_END,
} from "../constants";
import { stripManagedAppendix, sanitizeMermaidSource, toRelativePath } from "../utils";

export function buildAppendixSection(
  heading: string,
  body: string,
  language?: string,
): string {
  if (!body.trim()) return "";
  if (language) {
    const content = language === "mermaid" ? sanitizeMermaidSource(body) : body;
    return `## ${heading}\n\n\`\`\`${language}\n${content}\n\`\`\``;
  }
  return `## ${heading}\n\n${body}`;
}

export async function writeFinalDocument(
  docFullPath: string,
  fallbackBody: string,
  appendixSections: string[],
): Promise<void> {
  let existing = "";
  try {
    existing = stripManagedAppendix(readFileSync(docFullPath, "utf-8"));
  } catch {
    existing = "";
  }

  const bodyResult = await downgradeInvalidMermaidBlocksInMarkdown(
    existing || fallbackBody.trim(),
  );
  const appendix = appendixSections.filter(Boolean).join("\n\n");
  const finalContent =
    [bodyResult.markdown, MANAGED_APPENDIX_START, appendix, MANAGED_APPENDIX_END]
      .filter(Boolean)
      .join("\n\n")
      .trim() + "\n";

  writeFileSync(docFullPath, finalContent);
}

export async function validateWikiMarkdownFiles(
  wikiDir: string,
): Promise<string[]> {
  const errors: string[] = [];
  const stack = [wikiDir];

  while (stack.length > 0) {
    const current = stack.pop();
    if (!current || !existsSync(current)) {
      continue;
    }

    for (const entry of readdirSync(current)) {
      const fullPath = join(current, entry);
      const stats = statSync(fullPath);
      if (stats.isDirectory()) {
        stack.push(fullPath);
        continue;
      }

      if (!stats.isFile() || !fullPath.endsWith(".md")) {
        continue;
      }

      const original = readFileSync(fullPath, "utf-8");
      const validated = await downgradeInvalidMermaidBlocksInMarkdown(original);
      if (validated.diagramErrors.length > 0) {
        errors.push(
          ...validated.diagramErrors.map(
            (error) => `${toRelativePath(wikiDir, fullPath)}: ${error}`,
          ),
        );
        writeFileSync(fullPath, validated.markdown);
      }
    }
  }

  return errors;
}
