#!/usr/bin/env node
// run-toxic-flow.mjs — Toxic-flow analyzer (TFA) walkthrough
// Drives scanners/toxic-flow-analyzer.mjs against a deliberately
// misconfigured plugin fixture and verifies that the lethal-trifecta
// detector emits at least one CRITICAL finding for the single-component
// trifecta planted in fixture/agents/exfil-helper.fixture.md.
//
// TFA is the only scanner in this plugin that operates at the
// component level (not the line/file level). Other scanners catch
// dangerous *content*; TFA catches dangerous *capability combinations*
// across a plugin's commands/agents/skills surface.
//
// Usage:
//   cd plugins/llm-security
//   node examples/toxic-agent-demo/run-toxic-flow.mjs
//   node examples/toxic-agent-demo/run-toxic-flow.mjs --verbose

import { resolve, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const PLUGIN_ROOT = resolve(__dirname, '../..');
const FIXTURE = resolve(__dirname, 'fixture');
const VERBOSE = process.argv.includes('--verbose');

const { discoverFiles } = await import(resolve(PLUGIN_ROOT, 'scanners/lib/file-discovery.mjs'));
const { scan } = await import(resolve(PLUGIN_ROOT, 'scanners/toxic-flow-analyzer.mjs'));

console.log('TOXIC-FLOW ANALYZER (TFA) WALKTHROUGH');
console.log('=====================================\n');
console.log(`Fixture: ${FIXTURE}`);
console.log('Component in scope:');
console.log('  - agents/exfil-helper.fixture.md (tools: [Bash, Read, WebFetch])');
console.log('Plugin marker: plugin.fixture.json (recognised by isPlugin())');
console.log('Hook guards: none (no hooks/hooks.json) — keeps trifecta at CRITICAL\n');

const discovery = await discoverFiles(FIXTURE);
const result = await scan(FIXTURE, discovery, {});
const findings = result.findings || [];

const directTrifectas = findings.filter(f =>
  typeof f.title === 'string' && f.title.startsWith('Lethal trifecta:')
);
const crossTrifectas = findings.filter(f =>
  typeof f.title === 'string' && f.title.startsWith('Cross-component')
);
const projectLevel = findings.filter(f =>
  typeof f.title === 'string' && f.title.startsWith('Project-level trifecta')
);

const expectations = [
  {
    label: 'Direct trifecta — single component covers all 3 legs',
    bucket: directTrifectas,
    minCount: 1,
    expectSeverity: 'critical',
  },
  {
    label: 'Trifecta finding mentions exfil-helper component',
    bucket: directTrifectas.filter(f =>
      typeof f.title === 'string' && /exfil-helper/i.test(f.title)
    ),
    minCount: 1,
  },
  {
    label: 'No mitigation — guards line is "No hook guards detected"',
    bucket: directTrifectas.filter(f =>
      typeof f.description === 'string' &&
      /no hook guards detected/i.test(f.description)
    ),
    minCount: 1,
  },
];

let pass = 0;
let fail = 0;

for (const exp of expectations) {
  const ok = exp.bucket.length >= exp.minCount &&
    (!exp.expectSeverity || exp.bucket.some(f =>
      String(f.severity || '').toLowerCase() === exp.expectSeverity
    ));
  if (ok) pass++; else fail++;
  console.log(`[${ok ? 'PASS' : 'FAIL'}] ${exp.label}`);
  console.log(`       findings: ${exp.bucket.length} (need >= ${exp.minCount})`);
  if (exp.expectSeverity) {
    console.log(`       expected severity: ${exp.expectSeverity}`);
  }
  for (const f of exp.bucket.slice(0, 1)) {
    const sev = String(f.severity || '').toUpperCase().padEnd(8);
    const title = (f.title || '').slice(0, 90);
    console.log(`         ${sev} ${title}`);
  }
  console.log();
}

console.log(`Total TFA findings:        ${findings.length}`);
console.log(`  direct trifectas:        ${directTrifectas.length}`);
console.log(`  cross-component:         ${crossTrifectas.length}`);
console.log(`  project-level fallback:  ${projectLevel.length}`);
console.log(`Files scanned (components): ${result.files_scanned ?? '?'}`);
console.log(`Scanner status:            ${result.status}`);

if (VERBOSE) {
  console.log('\nFull findings list:');
  for (const f of findings) {
    const sev = String(f.severity || '').toUpperCase().padEnd(8);
    console.log(`  ${sev} [${f.file || '-'}] ${(f.title || '').slice(0, 110)}`);
    if (f.evidence) console.log(`           evidence: ${String(f.evidence).slice(0, 150)}`);
  }
}

console.log('\n---');
console.log(`Result: ${pass} pass, ${fail} fail`);

if (fail > 0) {
  console.log('\nFAILURE — TFA did not emit the expected single-component trifecta.');
  console.log('Inspect verbose output (--verbose) to see what was actually returned.');
  process.exit(1);
}

console.log('\nSUCCESS — TFA flagged the planted lethal trifecta as CRITICAL.');
console.log('Read examples/toxic-agent-demo/README.md for the OWASP / framework mapping.');
process.exit(0);
