import { describe, expect, it } from "vitest";
import type { ParsedArtifactCandidate } from "./artifactOcrParser";
import {
  createStoredScanResultEntry,
  deriveArtifactValueStatus,
  deriveScanResultExtractionStatus,
} from "./scanResultEntry";

function parsedArtifact(overrides: Partial<ParsedArtifactCandidate> = {}): ParsedArtifactCandidate {
  const field = { value: "", confidence: 92, source: "ocr" as const };
  return {
    name: "Pristine Plume of the Blessed",
    slot: "Plume of Death",
    level: 20,
    mainStat: "ATK",
    mainValue: "311",
    substats: ["CRIT DMG+7.0%", "DEF%+30.6%", "Elemental Mastery+40", "ATK%+5.8%"],
    setName: "Silken Moon's Serenade",
    equipped: "Aino",
    confidence: 93,
    notes: [],
    fields: {
      name: field,
      slot: field,
      level: field,
      mainStat: field,
      mainValue: field,
      setName: field,
      equipped: field,
      substats: field,
    },
    ...overrides,
  };
}

describe("scan result entries", () => {
  it("keeps clean extraction separate from deferred artifact value evaluation", () => {
    const entry = createStoredScanResultEntry({
      runId: "run-1",
      sequence: 1,
      page: 0,
      row: 1,
      col: 2,
      source: "native-ik-scan",
      imagePath: "artifact-0001.png",
      parsed: parsedArtifact(),
      needsReview: false,
      confidence: 93,
      artifactRecordId: "artifact-id",
      persistedArtifact: true,
      locked: true,
      ikMatch: {
        matched: true,
        confidence: 100,
        source: "ik-inventorylists",
        setKey: "silkenmoonsserenade",
        setGood: "SilkenMoonsSerenade",
        setName: "Silken Moon's Serenade",
        artifactKey: "pristineplumeoftheblessed",
        artifactGood: "PristinePlumeOfTheBlessed",
        artifactName: "Pristine Plume of the Blessed",
        slotKey: "plume",
        notes: [],
      },
    });

    expect(entry.extractionStatus).toBe("parsed");
    expect(entry.needsReview).toBe(false);
    expect(entry.valueStatus).toBe("deferred");
    expect(entry.valueScore).toBeNull();
    expect(entry.artifactRecordId).toBe("artifact-id");
    expect(entry.persistedArtifact).toBe(true);
    expect(entry.artifact).toMatchObject({
      name: "Pristine Plume of the Blessed",
      slot: "Plume of Death",
      setName: "Silken Moon's Serenade",
      mainStat: "ATK",
      mainValue: "311",
      locked: true,
    });
    expect(entry.ikMatch).toMatchObject({
      matched: true,
      source: "ik-inventorylists",
      artifactGood: "PristinePlumeOfTheBlessed",
    });
    expect(entry.fieldConfidences).toEqual([
      { key: "name", label: "Name", value: "", confidence: 92, source: "ocr" },
      { key: "slot", label: "Slot", value: "", confidence: 92, source: "ocr" },
      { key: "level", label: "Level", value: "", confidence: 92, source: "ocr" },
      { key: "mainStat", label: "Main stat", value: "", confidence: 92, source: "ocr" },
      { key: "mainValue", label: "Main value", value: "", confidence: 92, source: "ocr" },
      { key: "setName", label: "Set", value: "", confidence: 92, source: "ocr" },
      { key: "equipped", label: "Equipped", value: "", confidence: 92, source: "ocr" },
      { key: "substats", label: "Substats", value: "", confidence: 92, source: "ocr" },
    ]);
  });

  it("turns low-confidence or incomplete parses into review results without value scores", () => {
    const entry = createStoredScanResultEntry({
      runId: "run-1",
      sequence: 2,
      source: "native-ik-scan",
      imagePath: "artifact-0002.png",
      parsed: parsedArtifact({
        confidence: 65,
        notes: ["main stat not confidently parsed"],
      }),
      needsReview: true,
      confidence: 65,
    });

    expect(entry.extractionStatus).toBe("review");
    expect(entry.needsReview).toBe(true);
    expect(entry.valueStatus).toBe("review");
    expect(entry.valueScore).toBeNull();
    expect(entry.persistedArtifact).toBe(false);
  });

  it("keeps non-artifact categories as review-only scan evidence", () => {
    const entry = createStoredScanResultEntry({
      runId: "run-1",
      sequence: 3,
      category: "weapon",
      source: "native-ik-scan",
      imagePath: "weapon-0003.png",
      parsed: null,
      needsReview: true,
      confidence: 0,
      error: "Native post-capture processing for category 'weapons' is not implemented yet; IK catalog is available only.",
      notes: ["catalog-only"],
    });

    expect(entry.category).toBe("weapon");
    expect(entry.extractionStatus).toBe("error");
    expect(entry.valueStatus).toBe("review");
    expect(entry.artifact).toBeUndefined();
    expect(entry.persistedArtifact).toBe(false);
  });

  it("maps missing crops and parse failures to explicit extraction states", () => {
    expect(deriveScanResultExtractionStatus({
      parsed: false,
      needsReview: true,
      error: "Card crop image missing.",
    })).toBe("missing_crop");
    expect(deriveScanResultExtractionStatus({
      parsed: false,
      needsReview: true,
    })).toBe("parse_error");
    expect(deriveArtifactValueStatus("missing_crop")).toBe("review");
    expect(deriveArtifactValueStatus("parsed")).toBe("deferred");
  });
});
