import fs from "node:fs/promises";
import path from "node:path";
import YAML from "yaml";

const CWD = process.cwd();
const ANNO_DIR = path.join(CWD, "src", "annotations");
const PUBLIC_DIR = path.join(CWD, "public");

async function exists(p) {
  try { await fs.access(p); return true; } catch { return false; }
}

async function walk(dir) {
  const out = [];
  const ents = await fs.readdir(dir, { withFileTypes: true });
  for (const e of ents) {
    const p = path.join(dir, e.name);
    if (e.isDirectory()) out.push(...(await walk(p)));
    else out.push(p);
  }
  return out;
}

function parseDoc(raw, fileAbs) {
  if (/\.json$/i.test(fileAbs)) return JSON.parse(raw);
  return YAML.parse(raw);
}

function isPlainObject(x) {
  return !!x && typeof x === "object" && !Array.isArray(x);
}

function toPublicPathFromUrl(urlPath) {
  // "/media/..." -> "public/media/..."
  const clean = String(urlPath || "").split("?")[0].split("#")[0];
  if (!clean.startsWith("/media/")) return null;
  return path.join(PUBLIC_DIR, clean.replace(/^\/+/, ""));
}

async function main() {
  if (!(await exists(ANNO_DIR))) {
    console.log("✅ annotations-media: aucun src/annotations — rien à vérifier.");
    process.exit(0);
  }

  const files = (await walk(ANNO_DIR)).filter((p) => /\.(ya?ml|json)$/i.test(p));
  let checked = 0;
  let missing = 0;
  const notes = [];

  // Optim: éviter de vérifier 100 fois le même fichier media
  const seenMedia = new Set(); // src string

  for (const f of files) {
    const rel = path.relative(CWD, f).replace(/\\/g, "/");
    const raw = await fs.readFile(f, "utf8");

    let doc;
    try { doc = parseDoc(raw, f); }
    catch (e) {
      missing++;
      notes.push(`- PARSE FAIL: ${rel} (${String(e?.message ?? e)})`);
      continue;
    }

    if (!isPlainObject(doc) || doc.schema !== 1 || !isPlainObject(doc.paras)) continue;

    for (const [paraId, entry] of Object.entries(doc.paras)) {
      const media = entry?.media;
      if (!Array.isArray(media)) continue;

      for (const m of media) {
        const src = String(m?.src || "");
        if (!src.startsWith("/media/")) continue; // externes ok, ou autres conventions futures

        // dédupe
        if (seenMedia.has(src)) continue;
        seenMedia.add(src);

        checked++;
        const p = toPublicPathFromUrl(src);
        if (!p) continue;

        if (!(await exists(p))) {
          missing++;
          notes.push(`- MISSING MEDIA: ${src} (from ${rel} para ${paraId})`);
        }
      }
    }
  }

  if (missing > 0) {
    console.error(`FAIL: annotations media missing (checked=${checked} missing=${missing})`);
    for (const n of notes) console.error(n);
    process.exit(1);
  }

  console.log(`✅ annotations-media OK: checked=${checked}`);
}

main().catch((e) => {
  console.error("FAIL: check-annotations-media crashed:", e);
  process.exit(1);
});