/**
 * Generate evaluation reports in JSON and Markdown format.
 */

import type { EvalMetrics } from "./metrics.js";

interface EvalResult {
  scenarioId: string;
  runId: number;
  passed: boolean;
  assertions: { name: string; passed: boolean; expected: string; actual: string }[];
  latencyMs: number;
  cost: number;
  hud: string;
  digest: string;
  escalationScore: number;
}

interface EvalReport {
  runDate: string;
  config: Record<string, unknown>;
  scenarios: number;
  runsPerScenario: number;
  results: EvalResult[];
  metrics: EvalMetrics;
}

// Quality gates
const GATES = {
  passRate: { threshold: 0.9, blocking: true, label: "Pass rate" },
  judgeScore: { threshold: 3.0, blocking: true, label: "Judge quality" },
  latencyP95: { threshold: 5000, blocking: false, label: "P95 latency" },
  avgCost: { threshold: 0.001, blocking: false, label: "Avg cost/tick" },
};

function gateStatus(value: number, threshold: number, lowerIsBetter: boolean): string {
  if (lowerIsBetter) {
    return value <= threshold ? "\u2705" : "\u26a0\ufe0f";
  }
  return value >= threshold ? "\u2705" : "\u274c";
}

export function generateReport(report: EvalReport): string {
  const m = report.metrics;
  const lines: string[] = [];

  lines.push(`## Eval Report \u2014 ${report.runDate.slice(0, 10)}`);
  lines.push("");
  lines.push(`**Model:** ${report.config.model}`);
  lines.push(`**Richness:** ${report.config.richness}`);
  lines.push(`**Scenarios:** ${report.scenarios} \u00d7 ${report.runsPerScenario} runs = ${m.totalResults} invocations`);
  lines.push("");

  // Quality gates
  lines.push("### Quality Gates");
  lines.push("");
  lines.push(`| Gate | Metric | Threshold | Value | Status |`);
  lines.push(`|------|--------|-----------|-------|--------|`);
  lines.push(`| P0: No regressions | - | - | - | \u2014 |`);
  lines.push(`| P1: Pass rate | ${(m.passRate * 100).toFixed(0)}% | \u2265 90% | ${(m.passRate * 100).toFixed(1)}% | ${gateStatus(m.passRate, GATES.passRate.threshold, false)} |`);
  lines.push(`| P2: Quality | ${m.avgJudgeScore}/4.0 | \u2265 3.0 | ${m.avgJudgeScore.toFixed(1)} | ${m.avgJudgeScore > 0 ? gateStatus(m.avgJudgeScore, GATES.judgeScore.threshold, false) : "\u2014"} |`);
  lines.push(`| P3: Latency | P95=${m.latencyP95}ms | \u2264 5,000ms | ${m.latencyP95}ms | ${gateStatus(m.latencyP95, GATES.latencyP95.threshold, true)} |`);
  lines.push(`| P4: Cost | $${m.avgCostPerTick.toFixed(6)}/tick | \u2264 $0.001 | $${m.avgCostPerTick.toFixed(6)} | ${gateStatus(m.avgCostPerTick, GATES.avgCost.threshold, true)} |`);
  lines.push("");

  // Summary stats
  lines.push("### Summary");
  lines.push("");
  lines.push(`- **Pass rate:** ${(m.passRate * 100).toFixed(1)}% (${Math.round(m.passRate * report.scenarios)}/${report.scenarios})`);
  lines.push(`- **Assertion pass rate:** ${(m.assertionPassRate * 100).toFixed(1)}%`);
  lines.push(`- **Escalation accuracy:** ${(m.escalationAccuracy * 100).toFixed(1)}%`);
  lines.push(`- **P50 latency:** ${m.latencyP50}ms`);
  lines.push(`- **P95 latency:** ${m.latencyP95}ms`);
  lines.push(`- **Total cost:** $${m.totalCost.toFixed(6)}`);
  lines.push(`- **95% CI on pass rate:** [${m.confidenceInterval[0]}, ${m.confidenceInterval[1]}]`);
  lines.push("");

  // Failures
  if (m.failedScenarios.length > 0) {
    lines.push(`### Failures (${m.failedScenarios.length})`);
    lines.push("");
    for (const scenarioId of m.failedScenarios) {
      const scenarioResults = report.results.filter(r => r.scenarioId === scenarioId);
      lines.push(`#### ${scenarioId}`);
      for (const r of scenarioResults) {
        if (!r.passed) {
          const failedAssertions = r.assertions.filter(a => !a.passed);
          for (const a of failedAssertions) {
            lines.push(`- **${a.name}**: expected=${a.expected}, actual=${a.actual}`);
          }
          lines.push(`  HUD: "${r.hud}"`);
          lines.push(`  Digest: "${r.digest.slice(0, 200)}"`);
        }
      }
      lines.push("");
    }
  } else {
    lines.push("### Failures: 0 \ud83c\udf89");
    lines.push("");
  }

  lines.push("---");
  lines.push(`*Generated by sinain-core eval harness*`);

  return lines.join("\n");
}
