import { describe, expect, it } from "vitest";
import { formatReport, runOcrEval } from "./ocrEvalHarness";
import { seedCorpus } from "./corpus/seedCorpus";

// Regression gate: the seed corpus is verified ground truth, so the parser must
// read every labeled field correctly. A drop here means an OCR/parser change
// regressed a previously-correct read - look at the printed failures. If a
// change intentionally alters a correct output, update the corpus label in the
// same commit (the label is the source of truth, not the code).

describe("OCR eval harness", () => {
  const report = runOcrEval(seedCorpus);

  it("prints the accuracy report", () => {
    // Surfaced in test output for humans; not an assertion.
    // eslint-disable-next-line no-console
    console.log("\n" + formatReport(report) + "\n");
    expect(report.totalCases).toBe(seedCorpus.length);
  });

  it("reads every labeled field on the seed corpus correctly", () => {
    const failureSummary = report.failures
      .map((failure) => {
        const wrong = failure.fields
          .filter((entry) => !entry.correct)
          .map((entry) => `${entry.field}: expected "${entry.expected}" got "${entry.actual}"`)
          .join("; ");
        return `${failure.id} -> ${wrong}`;
      })
      .join("\n");

    expect(report.fieldAccuracy, `field regressions:\n${failureSummary}`).toBe(1);
    expect(report.criticalFieldAccuracy).toBe(1);
    expect(report.exactRate).toBe(1);
  });

  it("labels every critical field at least once across the corpus", () => {
    const criticalCoverage = report.perField.filter(
      (entry) => ["name", "slot", "mainStat", "mainValue", "setName"].includes(entry.field) && entry.evaluated > 0,
    );
    // name is derived indirectly on most cases; slot/mainStat/mainValue/setName must be exercised.
    expect(criticalCoverage.length).toBeGreaterThanOrEqual(4);
  });
});
