#!/usr/bin/env node

/**
 * audit-all.mjs — Three-Layer Protocol Audit Orchestrator
 *
 * Runs all three protocol audits sequentially:
 *   1. AGENTS.md — Execution Protocol
 *   2. GOVERNANCE.md — Execution Governance
 *   3. PORTFOLIO.md — Portfolio Management
 *
 * Outputs:
 *   - Console: colorized summary with PASS / WARN / FAIL
 *   - File:    audit-report.md      (generated in workspace root)
 *
 * Usage:
 *   node scripts/audit-all.mjs
 *
 * npm script (add to package.json):
 *   "audit": "node scripts/audit-all.mjs"
 */

import { fileURLToPath } from 'url';
import path from 'path';
import fs from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const WORKSPACE = path.resolve(__dirname, '..');

// Dynamic imports for the three audit modules
const [agentsMod, govMod, portMod] = await Promise.all([
  import(path.join(__dirname, 'audit-agents.mjs')),
  import(path.join(__dirname, 'audit-governance.mjs')),
  import(path.join(__dirname, 'audit-portfolio.mjs')),
]);

/** @returns {{ layer: string, checks: import('./audit-agents.mjs').CheckResult[] }[]} */
function runAll() {
  const layers = [
    { layer: 'Execution Protocol (AGENTS.md)',   fn: () => agentsMod.runAgentAudit(WORKSPACE) },
    { layer: 'Execution Governance (GOVERNANCE.md)', fn: () => govMod.runGovernanceAudit(WORKSPACE) },
    { layer: 'Portfolio Management (PORTFOLIO.md)',  fn: () => portMod.runPortfolioAudit(WORKSPACE) },
  ];
  return layers.map(({ layer, fn }) => ({ layer, checks: fn() }));
}

/** Colorized console output */
function printConsole(results) {
  let totalPass = 0, totalWarn = 0, totalFail = 0, totalChecks = 0;

  for (const { layer, checks } of results) {
    // Skip summary rows for individual counts
    const realChecks = checks.filter(c => !c.id.endsWith('-SUMMARY'));
    const pass = realChecks.filter(c => c.status === 'PASS').length;
    const warn = realChecks.filter(c => c.status === 'WARN').length;
    const fail = realChecks.filter(c => c.status === 'FAIL').length;
    totalPass += pass;
    totalWarn += warn;
    totalFail += fail;
    totalChecks += realChecks.length;

    const overall = fail > 0 ? '\x1b[31mFAIL\x1b[0m' : warn > 0 ? '\x1b[33mWARN\x1b[0m' : '\x1b[32mPASS\x1b[0m';
    console.log(`\n\x1b[1m${'='.repeat(60)}\x1b[0m`);
    console.log(`\x1b[1m  ${layer}\x1b[0m  ${overall}`);
    console.log(`\x1b[1m${'='.repeat(60)}\x1b[0m`);

    for (const r of checks) {
      if (r.id.endsWith('-SUMMARY')) continue;
      const icon = r.status === 'PASS' ? '\x1b[32m✅\x1b[0m' : r.status === 'WARN' ? '\x1b[33m⚠️\x1b[0m' : '\x1b[31m❌\x1b[0m';
      const statusTag = r.status === 'PASS' ? '\x1b[32mPASS\x1b[0m' : r.status === 'WARN' ? '\x1b[33mWARN\x1b[0m' : '\x1b[31mFAIL\x1b[0m';
      console.log(`  ${icon} [${statusTag}] [${r.id}] ${r.name}`);
      console.log(`     ${r.evidence}`);
      if (r.suggestion) console.log(`     \x1b[90m→ ${r.suggestion}\x1b[0m`);
      console.log();
    }
  }

  // Final summary
  console.log(`\x1b[1m${'='.repeat(60)}\x1b[0m`);
  console.log(`\x1b[1m  THREE-LAYER AUDIT COMPLETE\x1b[0m`);
  console.log(`\x1b[1m${'='.repeat(60)}\x1b[0m`);
  console.log(`  Total checks:   ${totalChecks}`);
  console.log(`  \x1b[32mPASS:           ${totalPass}\x1b[0m`);
  console.log(`  \x1b[33mWARN:           ${totalWarn}\x1b[0m`);
  console.log(`  \x1b[31mFAIL:           ${totalFail}\x1b[0m`);

  const verdict = totalFail > 0 ? '\x1b[31mFAIL' : totalWarn > 0 ? '\x1b[33mWARN' : '\x1b[32mPASS';
  console.log(`\n  VERDICT: ${verdict}\x1b[0m`);
  console.log();
}

/** Generate audit-report.md */
function writeReport(results) {
  const reportPath = path.join(WORKSPACE, 'audit-report.md');

  const timestamp = new Date().toISOString().replace('T', ' ').slice(0, 19) + ' +08:00';
  let md = `# Audit Report — ${timestamp}\n\n`;
  md += `> Generated by \`scripts/audit-all.mjs\`\n\n`;
  md += `## Global Summary\n\n`;

  let totalPass = 0, totalWarn = 0, totalFail = 0, totalChecks = 0;

  // First pass: aggregate all checks across layers
  const allChecksFlat = [];
  for (const { layer, checks } of results) {
    for (const r of checks) {
      if (r.id.endsWith('-SUMMARY')) continue;
      allChecksFlat.push({ ...r, layer });
      if (r.status === 'PASS') totalPass++;
      else if (r.status === 'WARN') totalWarn++;
      else if (r.status === 'FAIL') totalFail++;
      totalChecks++;
    }
  }

  md += `| Metric | Value |\n|--------|-------|\n`;
  md += `| Total Checks | ${totalChecks} |\n`;
  md += `| ✅ PASS | ${totalPass} |\n`;
  md += `| ⚠️ WARN | ${totalWarn} |\n`;
  md += `| ❌ FAIL | ${totalFail} |\n`;
  md += `| **Verdict** | **${totalFail > 0 ? '❌ FAIL' : totalWarn > 0 ? '⚠️ WARN' : '✅ PASS'}** |\n\n`;

  const verdictOverall = totalFail > 0 ? 'FAIL' : totalWarn > 0 ? 'WARN' : 'PASS';
  md += `**Verdict: ${verdictOverall}**\n\n`;

  // Layer-by-layer tables
  for (const { layer, checks } of results) {
    const real = checks.filter(c => !c.id.endsWith('-SUMMARY'));
    const lp = real.filter(c => c.status === 'PASS').length;
    const lw = real.filter(c => c.status === 'WARN').length;
    const lf = real.filter(c => c.status === 'FAIL').length;
    const lv = lf > 0 ? '❌ FAIL' : lw > 0 ? '⚠️ WARN' : '✅ PASS';
    md += `## ${layer} — ${lv}\n\n`;
    md += `| ID | Name | Status | Evidence | Suggestion |\n`;
    md += `|----|------|--------|----------|------------|\n`;

    for (const r of real) {
      const icon = r.status === 'PASS' ? '✅' : r.status === 'WARN' ? '⚠️' : '❌';
      const sug = r.suggestion ? r.suggestion.replace(/\|/g, '\\|') : '';
      const ev = r.evidence.replace(/\|/g, '\\|').replace(/\n/g, ' ').slice(0, 120);
      md += `| ${r.id} | ${r.name} | ${icon} ${r.status} | ${ev} | ${sug} |\n`;
    }

    md += `| **Layer Summary** | **${lp} PASS / ${lw} WARN / ${lf} FAIL** | **${lv}** | | |\n\n`;
  }

  // Fails list
  const fails = allChecksFlat.filter(c => c.status === 'FAIL');
  if (fails.length > 0) {
    md += `## ❌ Failures (repair required)\n\n`;
    for (const f of fails) {
      md += `- **[${f.id}]** ${f.name} — ${f.evidence}\n`;
      if (f.suggestion) md += `  - *Repair:* ${f.suggestion}\n`;
    }
    md += '\n';
  }

  // Warnings list
  const warns = allChecksFlat.filter(c => c.status === 'WARN');
  if (warns.length > 0) {
    md += `## ⚠️ Warnings (improvement recommended)\n\n`;
    for (const w of warns) {
      md += `- **[${w.id}]** ${w.name} — ${w.evidence}\n`;
      if (w.suggestion) md += `  - *Suggestion:* ${w.suggestion}\n`;
    }
    md += '\n';
  }

  // Coverage summary
  md += `## Coverage\n\n`;
  md += `| Layer | Sections | Checks |\n|-------|----------|--------|\n`;
  const agentsReal = results[0].checks.filter(c => !c.id.endsWith('-SUMMARY'));
  const govReal = results[1].checks.filter(c => !c.id.endsWith('-SUMMARY'));
  const portReal = results[2].checks.filter(c => !c.id.endsWith('-SUMMARY'));
  md += `| AGENTS.md | §0-§7, Learning Loop, Context Budget | ${agentsReal.length} |\n`;
  md += `| GOVERNANCE.md | §1-§12 | ${govReal.length} |\n`;
  md += `| PORTFOLIO.md | §1-§14 | ${portReal.length} |\n`;
  md += `| **Total** | **3 layers** | **${totalChecks}** |\n\n`;

  md += `---\n*Audit complete. ${timestamp}*\n`;

  fs.writeFileSync(reportPath, md, 'utf8');
  console.log(`\n  📄 Report written to: audit-report.md`);
  return reportPath;
}

// ---- Main ----
console.log(`\x1b[1m\x1b[36m`);
console.log(`  ╔══════════════════════════════════════════════════╗`);
console.log(`  ║        THREE-LAYER PROTOCOL AUDIT              ║`);
console.log(`  ║  AGENTS.md · GOVERNANCE.md · PORTFOLIO.md      ║`);
console.log(`  ╚══════════════════════════════════════════════════╝`);
console.log(`\x1b[0m`);

const results = runAll();
printConsole(results);
writeReport(results);
