import { afterEach, describe, expect, it, vi } from "vitest";

const ENRICHMENT_FLAG = "FEATURE_ASSISTANT_EVIDENCE_ENRICHMENT_V1";
const ORIGINAL_FLAG_VALUE = process.env[ENRICHMENT_FLAG];

function restoreFlag(): void {
  if (ORIGINAL_FLAG_VALUE === undefined) {
    delete process.env[ENRICHMENT_FLAG];
  } else {
    process.env[ENRICHMENT_FLAG] = ORIGINAL_FLAG_VALUE;
  }
}

async function normalizeSingleEvidence(flagValue: "0" | "1", evidenceRecord: Record<string, unknown>) {
  process.env[ENRICHMENT_FLAG] = flagValue;
  vi.resetModules();
  const { normalizeRetrievalResult } = await import("../src/services/retrievalResultNormalizer");
  return normalizeRetrievalResult("F1", ["R1"], "store_feature_risk", {
    status: "ok",
    result_type: "list",
    items: [],
    summary: {},
    evidence: [evidenceRecord],
    why_included: [],
    selection_reason: [],
    risk_factors: [],
    business_interpretation: [],
    confidence: "medium",
    limitations: [],
    errors: []
  });
}

describe.sequential("retrieval evidence enrichment", () => {
  afterEach(() => {
    restoreFlag();
    vi.resetModules();
  });

  it("builds deterministic canonical source_ref from pointer/source", async () => {
    const rawEvidence = {
      evidence_id: "ev-1",
      claim_ref: "requirement:R1",
      source_type: "retrieval_item",
      pointer: {
        fragment_id: "F1",
        route: "store_feature_risk",
        source: {
          namespace: "snapshot_2020",
          entity: "Document",
          id: "DOC-42",
          period: "2020-06"
        },
        locator: {
          field_path: "risk_score",
          item_index: 0
        }
      },
      risk_score: 3
    };

    const first = await normalizeSingleEvidence("1", rawEvidence);
    const second = await normalizeSingleEvidence("1", rawEvidence);

    expect(first.evidence[0].source_ref.canonical_ref).toBe(second.evidence[0].source_ref.canonical_ref);
    expect(first.evidence[0].source_ref.schema_version).toBe("evidence_source_ref_v1");
    expect(first.evidence[0].source_ref.namespace).toBe("snapshot_2020");
    expect(first.evidence[0].source_ref.entity).toBe("Document");
    expect(first.evidence[0].source_ref.id).toBe("DOC-42");
  });

  it("uses honest weak-evidence fallback when mechanism is not reliable", async () => {
    const result = await normalizeSingleEvidence("1", {
      evidence_id: "ev-weak",
      source_entity: "DocumentJournal",
      source_id: "doc-weak-1",
      risk_score: 2
    });

    expect(result.evidence[0].mechanism_note).toBeNull();
    expect(result.evidence[0].limitation?.reason_code).toBe("missing_mechanism");
    expect(result.evidence[0].confidence).toBe("low");
  });

  it("maps explicit limitation to reason-coded structure", async () => {
    const result = await normalizeSingleEvidence("1", {
      evidence_id: "ev-limited",
      source_entity: "DocumentJournal",
      source_id: "doc-limited-1",
      limitation: "Snapshot-only evidence."
    });

    expect(result.evidence[0].limitation?.reason_code).toBe("snapshot_only");
    expect(result.evidence[0].limitation?.note).toBe("Snapshot-only evidence.");
  });

  it("keeps legacy inferred mechanism when enrichment flag is OFF", async () => {
    const result = await normalizeSingleEvidence("0", {
      evidence_id: "ev-legacy",
      source_entity: "DocumentJournal",
      source_id: "doc-legacy-1",
      risk_score: 2
    });

    expect(typeof result.evidence[0].mechanism_note).toBe("string");
    expect(result.evidence[0].mechanism_note).toContain("Anomaly signal inferred");
    expect(result.evidence[0].limitation).toBeNull();
  });
});
