/**
 * Content QA for the original question packs.
 *
 *   npx tsx scripts/check-content.ts [--dir <packsDir>]
 *
 * Prints per-category counts, the difficulty and type mix, the answer-letter distribution players
 * will see (after the seeded option shuffle) and the True/False balance, then every warning and
 * error. Exits 1 when any error is found.
 */
import { PACKS_DIR, formatIssue, validatePacks, type ContentPack } from '../src/content/index';

function argValue(flag: string): string | undefined {
  const i = process.argv.indexOf(flag);
  return i >= 0 ? process.argv[i + 1] : undefined;
}

function pct(n: number, total: number): string {
  return total === 0 ? '  -' : `${Math.round((n / total) * 100)}%`.padStart(4);
}

function tally<T extends string>(values: T[]): Map<T, number> {
  const out = new Map<T, number>();
  for (const v of values) out.set(v, (out.get(v) ?? 0) + 1);
  return out;
}

function printPack(pack: ContentPack): void {
  const qs = pack.questions;
  console.log(`\n${pack.name} (${pack.key}, ${pack.kind}) — ${qs.length} questions`);
  console.log('  category              total   std  diff    MC    TF  wild');
  for (const cat of pack.categories) {
    const inCat = qs.filter((q) => q.category === cat.key);
    const std = inCat.filter((q) => q.difficulty === 'STANDARD').length;
    const mc = inCat.filter((q) => q.type === 'MULTIPLE_CHOICE').length;
    const wild = inCat.filter((q) => q.wildcardEligible).length;
    const missing = pack.missingCategories.includes(cat.key) ? '  (no file)' : '';
    console.log(
      `  ${cat.key.padEnd(20)} ${String(inCat.length).padStart(6)} ${String(std).padStart(5)} ${String(inCat.length - std).padStart(5)}` +
        ` ${String(mc).padStart(5)} ${String(inCat.length - mc).padStart(5)} ${String(wild).padStart(5)}${missing}`,
    );
  }
  const difficult = qs.filter((q) => q.difficulty === 'DIFFICULT').length;
  console.log(`  difficulty mix: STANDARD ${pct(qs.length - difficult, qs.length)}  DIFFICULT ${pct(difficult, qs.length)}`);

  const mc = qs.filter((q) => q.type === 'MULTIPLE_CHOICE');
  const shown = tally(mc.map((q) => q.correctOptionId));
  console.log(
    `  MC answer letters (as shown): ${['a', 'b', 'c', 'd'].map((l) => `${l} ${String(shown.get(l) ?? 0).padStart(3)} ${pct(shown.get(l) ?? 0, mc.length)}`).join('  ')}`,
  );
  // True/False is not shuffled, so its balance depends on the writers alone.
  const tf =qs.filter((q) => q.type === 'TRUE_FALSE');
  const trueCount = tf.filter((q) => q.correctOptionId === 'a').length;
  console.log(`  TF answers: True ${trueCount} ${pct(trueCount, tf.length)}  False ${tf.length - trueCount} ${pct(tf.length - trueCount, tf.length)}`);
}

function main(): void {
  const dir = argValue('--dir') ?? PACKS_DIR;
  const { packs, errors, warnings } = validatePacks({ dir });
  console.log(`Question packs in ${dir}`);
  for (const pack of packs) printPack(pack);

  if (warnings.length > 0) {
    console.log(`\n${warnings.length} warning(s):`);
    for (const w of warnings) console.log(`  ! ${formatIssue(w)}`);
  }
  if (errors.length > 0) {
    console.log(`\n${errors.length} error(s):`);
    for (const e of errors) console.log(`  x ${formatIssue(e)}`);
    process.exitCode = 1;
    return;
  }
  const total = packs.reduce((n, p) => n + p.questions.length, 0);
  console.log(`\nOK: ${packs.length} pack(s), ${total} questions, no errors.`);
}

main();
