#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";

export const PAGE_TYPES = new Set(["cover", "agenda", "chapter", "statement", "text-visual", "comparison", "flow", "timeline", "matrix", "architecture", "swimlane", "cycle", "ipo", "table", "case", "exercise", "summary", "qa"]);
const PAGE_KEYS = new Set(["id", "type", "title", "eyebrow", "body", "source", "visual", "items", "prompt", "duration"]);

export function validateManifest(manifest) {
  const errors = [];
  if (!manifest || typeof manifest !== "object" || Array.isArray(manifest)) return ["manifest must be an object"];
  if (manifest.version !== 1) errors.push("version must be 1");
  if (!manifest.course?.title?.trim()) errors.push("course.title is required");
  if (!Array.isArray(manifest.pages) || manifest.pages.length < 2) return [...errors, "pages must contain at least two pages"];
  const ids = new Set();
  manifest.pages.forEach((page, index) => {
    const at = `pages[${index}]`;
    if (!page.id || !/^[a-z][a-z0-9-]*$/.test(page.id)) errors.push(`${at}.id must be kebab-case`);
    if (ids.has(page.id)) errors.push(`${at}.id duplicates ${page.id}`);
    ids.add(page.id);
    if (!PAGE_TYPES.has(page.type)) errors.push(`${at}.type is unsupported: ${page.type}`);
    if (!page.title?.trim()) errors.push(`${at}.title is required`);
    if (!page.source?.trim()) errors.push(`${at}.source is required`);
    for (const key of Object.keys(page)) if (!PAGE_KEYS.has(key)) errors.push(`${at}.${key} is unknown`);
    if (page.type === "exercise" && (!page.prompt?.trim() || !page.duration?.trim())) errors.push(`${at} exercise requires prompt and duration`);
  });
  if (manifest.pages[0].type !== "cover") errors.push("first page must use type cover");
  if (manifest.pages.at(-1).type !== "qa") errors.push("last page must use type qa");
  return errors;
}

function run(file) {
  const resolved = path.resolve(file || "course-manifest.json");
  let manifest;
  try { manifest = JSON.parse(fs.readFileSync(resolved, "utf8")); }
  catch (error) { console.log(`FAIL cannot read manifest: ${error.message}`); return 2; }
  const errors = validateManifest(manifest);
  const report = {file: resolved, ok: errors.length === 0, pageCount: manifest.pages?.length || 0, errors};
  console.log(JSON.stringify(report, null, 2));
  return errors.length ? 1 : 0;
}

if (process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1])) process.exitCode = run(process.argv[2]);
