import { describe, expect, it } from "vitest";
import type { CandidateEvidenceItem, ProblemUnit } from "../src/types/stage2ProblemUnits";
import { enrichProblemUnitLifecycle, rankLifecycleProblemUnits, resolveLifecycle } from "../src/services/lifecycleRuntime";

function buildBaseProblemUnit(input: {
  id: string;
  type: ProblemUnit["problem_unit_type"];
  expectedState?: string;
  actualState?: string;
  failedEdge?: string;
  impactCloseRisk?: boolean;
  severity?: number;
  confidence?: number;
}): ProblemUnit {
  const severityScore = input.severity ?? 0.62;
  const confidenceScore = input.confidence ?? 0.58;
  const severityGrade: ProblemUnit["severity"]["grade"] = severityScore >= 0.7 ? "high" : severityScore >= 0.4 ? "medium" : "low";
  const confidenceGrade: ProblemUnit["confidence"]["grade"] =
    confidenceScore >= 0.75 ? "high" : confidenceScore >= 0.45 ? "medium" : "low";
  return {
    schema_version: "problem_unit_v0_1",
    problem_unit_id: input.id,
    problem_unit_type: input.type,
    title: "Synthetic unit",
    mechanism_summary: "Synthetic mechanism",
    business_defect_class: "broken_lifecycle",
    severity: {
      score: Number(severityScore.toFixed(2)),
      grade: severityGrade
    },
    confidence: {
      score: Number(confidenceScore.toFixed(2)),
      grade: confidenceGrade
    },
    affected_entities: ["Document:DOC-1"],
    affected_documents: ["Document:DOC-1"],
    affected_postings: [],
    affected_accounts: ["51", "60"],
    affected_counterparties: [],
    affected_contracts: [],
    ...(input.expectedState
      ? {
          expected_state: input.expectedState
        }
      : {}),
    ...(input.actualState
      ? {
          actual_state: input.actualState
        }
      : {}),
    ...(input.failedEdge
      ? {
          failed_expected_edge: input.failedEdge
        }
      : {}),
    ...(input.impactCloseRisk
      ? {
          period_impact: {
            is_period_sensitive: true,
            impact_class: "close_risk" as const
          }
        }
      : {}),
    evidence_pack: ["cand-1"],
    entity_backlinks: [{ entity: "Document", id: "DOC-1" }],
    snapshot_limitations: []
  };
}

function buildCandidate(input: {
  id: string;
  anomalies?: string[];
  relations?: string[];
  confidence?: "high" | "medium" | "low";
}): CandidateEvidenceItem {
  return {
    schema_version: "candidate_evidence_v0_1",
    candidate_id: input.id,
    route: "hybrid_store_plus_live",
    source_ref: {
      schema_version: "evidence_source_ref_v1",
      namespace: "snapshot_2020",
      entity: "Document",
      id: "DOC-1",
      period: "2020-06",
      canonical_ref: "evidence_source_ref_v1|snapshot_2020|document|doc-1|2020-06"
    },
    relation_pattern_hits: input.relations ?? [],
    anomaly_patterns: input.anomalies ?? [],
    entity_backlinks: [{ entity: "Document", id: "DOC-1" }],
    confidence_hint: input.confidence ?? "medium"
  };
}

describe("lifecycle runtime stage3", () => {
  it("resolves stale missing transition for bank settlement chains", () => {
    const unit = buildBaseProblemUnit({
      id: "pu-bank-1",
      type: "broken_chain_segment",
      expectedState: "settlement_closed",
      failedEdge: "payment_to_settlement"
    });
    const candidates = [
      buildCandidate({
        id: "cand-1",
        relations: ["payment_to_settlement", "statement_to_document"],
        anomalies: ["broken_lifecycle", "missing_link", "no_continuation"]
      })
    ];

    const resolution = resolveLifecycle({ unit, candidates });
    expect(resolution.lifecycle_domain).toBe("bank_settlement");
    expect(resolution.missing_transitions.length).toBeGreaterThan(0);
    expect(resolution.detected_defects[0]).toBe("stale_active_state");
  });

  it("classifies cross-branch conflicts for VAT flow", () => {
    const unit = buildBaseProblemUnit({
      id: "pu-vat-1",
      type: "cross_branch_inconsistency_cluster"
    });
    const candidates = [
      buildCandidate({
        id: "cand-1",
        anomalies: ["cross_branch_inconsistency", "vat_chain_conflict"],
        relations: ["invoice_to_vat"]
      })
    ];

    const enriched = enrichProblemUnitLifecycle({ unit, candidates });
    expect(enriched.lifecycle_domain).toBe("vat_flow");
    expect(enriched.lifecycle_defect_type).toBe("cross_branch_state_conflict");
    expect(typeof enriched.business_lifecycle_interpretation).toBe("string");
  });

  it("sorts lifecycle-ranked units by lifecycle severity and ranking score", () => {
    const stale = enrichProblemUnitLifecycle({
      unit: buildBaseProblemUnit({
        id: "pu-stale",
        type: "period_risk_cluster",
        impactCloseRisk: true,
        expectedState: "close_completed"
      }),
      candidates: [buildCandidate({ id: "cand-stale", anomalies: ["period_close_risk", "missing_link", "no_continuation"] })]
    });

    const generic = enrichProblemUnitLifecycle({
      unit: buildBaseProblemUnit({
        id: "pu-generic",
        type: "document_conflict",
        severity: 0.4,
        confidence: 0.45
      }),
      candidates: [buildCandidate({ id: "cand-generic", anomalies: ["anomaly_signal"] })]
    });

    const ranked = rankLifecycleProblemUnits([generic, stale]);
    expect(ranked[0].problem_unit_id).toBe("pu-stale");
    expect((ranked[0].lifecycle_ranking_score ?? 0) >= (ranked[1].lifecycle_ranking_score ?? 0)).toBe(true);
  });
});

