#!/usr/bin/env tsx
/**
 * Priority1 全矩阵 canonical 路径批量询价（24 条）
 *
 *   npm run benchmark:priority1-canonical-matrix
 *   $env:PRIORITY1_MATRIX_FILTER="F04"; npm run benchmark:priority1-canonical-matrix
 *   $env:PRIORITY1_MATRIX_LIMIT="3"; npm run benchmark:priority1-canonical-matrix
 */
import { randomUUID } from "node:crypto";
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import {
  formatPriority1InputSummary,
  PRIORITY1_CANONICAL_PATHS,
} from "@/workers/rpa/priority1/demo-input";
import { validatePriority1FormConstraints } from "@/workers/rpa/priority1/form-constraints";
import {
  formatPriority1QuoteOutcomeMessage,
  formatPriority1QuotesTable,
  type Priority1QuoteOutcome,
} from "@/workers/rpa/priority1/quote-extract";
import { runPriority1VisualChain } from "./visual-priority1-full-chain";

function resolveMatrixBatchStatus(r: {
  ok: boolean;
  quoteCount: number;
  quoteOutcome?: Priority1QuoteOutcome;
  allObservedOk: boolean;
}): string {
  if (r.quoteCount > 0) return "quote_ok";
  if (r.quoteOutcome === "manual_followup") return "manual_followup";
  if (r.allObservedOk) return "form_only";
  return "fail";
}

function formatMatrixCaseLine(r: {
  caseId: string;
  ok: boolean;
  quoteCount: number;
  quoteOutcome?: Priority1QuoteOutcome;
  message?: string;
}): string {
  if (r.quoteCount > 0) return `✓ ${r.caseId} quotes=${r.quoteCount}`;
  if (r.quoteOutcome === "manual_followup") {
    return `✓ ${r.caseId} manual_followup — ${r.message ?? formatPriority1QuoteOutcomeMessage("manual_followup")}`;
  }
  return `✗ ${r.caseId} quotes=0`;
}

process.env.RPA_HEADLESS = process.env.RPA_HEADLESS ?? "true";
process.env.RPA_KEEP_BROWSER_OPEN = "false";
process.env.RPA_SLOW_MO_MS = process.env.RPA_SLOW_MO_MS ?? "0";
process.env.RPA_DWELL_MS = process.env.RPA_DWELL_MS ?? "0";
process.env.RPA_QUOTE_WAIT_MS = process.env.RPA_QUOTE_WAIT_MS ?? "120000";

const FILTER = process.env.PRIORITY1_MATRIX_FILTER?.trim();
const LIMIT = Number(process.env.PRIORITY1_MATRIX_LIMIT ?? 0);
const START = Number(process.env.PRIORITY1_MATRIX_START ?? 0);

function filterPaths() {
  let paths = [...PRIORITY1_CANONICAL_PATHS];
  if (FILTER) {
    const re = new RegExp(FILTER, "i");
    paths = paths.filter((p) => re.test(p.id) || re.test(p.title));
  }
  if (START > 0) paths = paths.slice(START);
  if (LIMIT > 0) paths = paths.slice(0, LIMIT);
  return paths;
}

async function main(): Promise<void> {
  const runId = randomUUID().slice(0, 8);
  const batchDir = join(process.cwd(), ".rpa", "visual-priority1-matrix", runId);
  mkdirSync(batchDir, { recursive: true });

  const paths = filterPaths();
  if (paths.length === 0) {
    console.error("[matrix] 无匹配路径");
    process.exit(1);
  }

  console.log(
    `\n[matrix] Priority1 canonical 全矩阵 batch=${runId} cases=${paths.length}/${PRIORITY1_CANONICAL_PATHS.length}`,
  );

  writeFileSync(
    join(batchDir, "cases-input.json"),
    `${JSON.stringify({ runId, filter: FILTER ?? null, paths: paths.map((p) => ({ id: p.id, title: p.title, verified: p.verified, input: p.input })) }, null, 2)}\n`,
    "utf8",
  );

  const results: Awaited<ReturnType<typeof runPriority1VisualChain>>[] = [];

  for (let i = 0; i < paths.length; i += 1) {
    const path = paths[i]!;
    console.log(`\n[matrix] ▶ ${i + 1}/${paths.length} ${path.id} — ${path.title}`);
    console.log(formatPriority1InputSummary(path.input));

    const constraintErrors = validatePriority1FormConstraints(path.input).filter(
      (v) => v.severity === "error",
    );
    if (constraintErrors.length) {
      console.error(`[matrix] ✗ ${path.id} 违反填写规则：${constraintErrors.map((e) => e.message).join("；")}`);
      results.push({
        runId,
        caseId: path.id,
        outDir: join(batchDir, path.id),
        demo: path.input,
        finishedAt: new Date().toISOString(),
        durationMs: 0,
        finalUrl: "",
        observations: [],
        quotes: [],
        quoteCount: 0,
        quoteOutcome: "no_result",
        allObservedOk: false,
        ok: false,
        error: constraintErrors.map((e) => e.message).join("；"),
      });
      continue;
    }

    const result = await runPriority1VisualChain({
      demo: path.input,
      caseId: path.id,
      runId,
      outDir: join(batchDir, path.id),
      keepBrowserOpen: false,
    });
    results.push(result);

    console.log(`\n${formatMatrixCaseLine({ caseId: path.id, ...result })}`);
    if (result.quotes.length) console.log(formatPriority1QuotesTable(result.quotes));
    if (result.quoteOutcome === "manual_followup" && result.message) {
      console.log(result.message);
    }
    if (result.error) console.log(`错误: ${result.error}`);
  }

  const instantPass = results.filter((r) => r.quoteCount > 0).length;
  const manualPass = results.filter((r) => r.quoteOutcome === "manual_followup").length;
  const pass = results.filter((r) => r.ok).length;
  const formOk = results.filter((r) => r.allObservedOk).length;

  const summary = {
    runId,
    total: paths.length,
    canonicalTotal: PRIORITY1_CANONICAL_PATHS.length,
    pass,
    instantQuote: instantPass,
    manualFollowup: manualPass,
    fail: paths.length - pass,
    formObservationsOk: formOk,
    finishedAt: new Date().toISOString(),
    cases: results.map((r, idx) => ({
      caseId: r.caseId,
      title: paths[idx]?.title,
      persona: paths[idx]?.persona,
      priorVerified: paths[idx]?.verified,
      batchStatus: resolveMatrixBatchStatus(r),
      ok: r.ok,
      quoteCount: r.quoteCount,
      quoteOutcome: r.quoteOutcome ?? null,
      message: r.message ?? null,
      allObservedOk: r.allObservedOk,
      error: r.error,
      outDir: r.outDir,
      quotes: r.quotes,
    })),
  };

  const summaryPath = join(batchDir, "batch-summary.json");
  writeFileSync(summaryPath, `${JSON.stringify(summary, null, 2)}\n`, "utf8");

  const md: string[] = [
    `# Priority1 Canonical 全矩阵报告`,
    ``,
    `- 批次: \`${runId}\``,
    `- 执行: ${paths.length} / ${PRIORITY1_CANONICAL_PATHS.length} 条`,
    `- 即时报价: **${instantPass}/${paths.length}**`,
    `- 人工跟进: **${manualPass}/${paths.length}**`,
    `- 成功合计: **${pass}/${paths.length}**`,
    `- 表单观测全绿: ${formOk}/${paths.length}`,
    ``,
    `| ID | 路径 | 原状态 | 批量结果 | 报价数 |`,
    `|----|------|--------|----------|--------|`,
  ];

  for (let i = 0; i < results.length; i += 1) {
    const r = results[i]!;
    const p = paths[i]!;
    const status =
      r.quoteCount > 0
        ? "✓ 即时报价"
        : r.quoteOutcome === "manual_followup"
          ? "✓ 人工跟进"
          : r.allObservedOk
            ? "△ 仅填表"
            : "✗ 失败";
    md.push(
      `| ${r.caseId} | ${p.title} | ${p.verified === "recorded" ? "已录制" : "待录制"} | ${status} | ${r.quoteCount} |`,
    );
  }

  md.push("", "## 未成功详情", "");
  for (let i = 0; i < results.length; i += 1) {
    const r = results[i]!;
    if (r.ok) continue;
    md.push(`### ${r.caseId}`);
    md.push(r.error ?? r.message ?? "(无报价)");
    md.push("");
  }

  const mdPath = join(batchDir, "batch-summary.md");
  writeFileSync(mdPath, `${md.join("\n")}\n`, "utf8");

  console.log(
    `\n[matrix] 完成 成功 ${pass}/${paths.length}（即时 ${instantPass} + 人工跟进 ${manualPass}）`,
  );
  console.log(`[matrix] JSON: ${summaryPath}`);
  console.log(`[matrix] MD:   ${mdPath}`);

  process.exit(pass === paths.length ? 0 : 1);
}

main().catch((e) => {
  console.error(e);
  process.exit(1);
});
