import { describe, expect, it } from "vitest";
import { composeAssistantAnswer } from "../src/services/answerComposer";
import type { AnswerGroundingCheck, RequirementCoverageReport, UnifiedRetrievalResult } from "../src/types/assistant";
import type { ProblemUnit, ProblemUnitSummary } from "../src/types/stage2ProblemUnits";

function buildRouteSummary() {
  return {
    mode: "deterministic_v2" as const,
    message_in_scope: true,
    scope_confidence: "high" as const,
    planner: {
      total_fragments: 1,
      in_scope_fragments: 1,
      out_of_scope_fragments: 0,
      discarded_fragments: 0,
      contains_multiple_tasks: false
    },
    decisions: [],
    fallback: {
      type: "none" as const,
      message: null
    }
  };
}

function buildCoverage(partial = false): RequirementCoverageReport {
  return {
    requirements_total: 1,
    requirements_covered: partial ? 0 : 1,
    requirements_uncovered: partial ? ["R1"] : [],
    requirements_partially_covered: partial ? ["R1"] : [],
    clarification_needed_for: [],
    out_of_scope_requirements: []
  };
}

function buildGrounding(status: AnswerGroundingCheck["status"]): AnswerGroundingCheck {
  return {
    status,
    route_subject_match: true,
    missing_requirements: status === "partial" ? ["R1"] : [],
    reasons: status === "partial" ? ["Coverage is partial for lifecycle-focused analysis."] : [],
    why_included_summary: ["synthetic-test"],
    selection_reason_summary: ["synthetic-test"]
  };
}

function buildLifecycleProblemUnit(): ProblemUnit {
  return {
    schema_version: "problem_unit_v0_1",
    problem_unit_id: "pu-lc-1",
    problem_unit_type: "lifecycle_anomaly_node",
    title: "Lifecycle anomaly node detected",
    mechanism_summary: "Mechanism candidate: expected transition is missing.",
    business_defect_class: "missing_expected_transition",
    severity: {
      score: 0.84,
      grade: "high"
    },
    confidence: {
      score: 0.68,
      grade: "medium"
    },
    affected_entities: ["Document:DOC-1"],
    affected_documents: ["Document:DOC-1"],
    affected_postings: [],
    affected_accounts: ["51", "60"],
    affected_counterparties: ["Counterparty:CP-1"],
    affected_contracts: ["Contract:CTR-1"],
    expected_state: "settlement_closed",
    actual_state: "stale_unlinked_payment",
    failed_expected_edge: "payment_to_settlement",
    period_impact: {
      is_period_sensitive: true,
      impact_class: "close_risk"
    },
    evidence_pack: ["cand-1"],
    entity_backlinks: [{ entity: "Document", id: "DOC-1" }],
    snapshot_limitations: [],
    lifecycle_domain: "bank_settlement",
    lifecycle_object_id: "lcobj-pu-lc-1",
    current_lifecycle_state: "stale_unlinked_payment",
    expected_lifecycle_state: "settlement_closed",
    missing_transition: "payment_to_settlement",
    lifecycle_defect_type: "stale_active_state",
    stale_duration: "period_boundary_exceeded",
    lifecycle_confidence: {
      score: 0.79,
      grade: "high"
    },
    business_lifecycle_interpretation:
      "Текущая стадия: stale_unlinked_payment; ожидаемая стадия: settlement_closed. Объект завис во времени и не дошел до ожидаемого перехода.",
    lifecycle_ranking_score: 1.41,
    lifecycle_ranking_basis: ["base_problem_severity", "stale_duration_weight", "period_close_impact"]
  };
}

function buildSummary(units: ProblemUnit[]): ProblemUnitSummary {
  const unitTypes = Array.from(new Set(units.map((item) => item.problem_unit_type)));
  return {
    schema_version: "problem_unit_summary_v0_1",
    units_total: units.length,
    duplicate_collapses: 0,
    unit_types: unitTypes,
    type_distribution: {
      lifecycle_anomaly_node: units.length
    },
    severity_distribution: {
      low: 0,
      medium: 0,
      high: units.length
    },
    confidence_distribution: {
      low: 0,
      medium: units.length,
      high: 0
    },
    primary_unit_type: unitTypes[0] ?? null,
    lifecycle_enriched_units: units.length,
    lifecycle_domain_distribution: {
      bank_settlement: units.length
    },
    lifecycle_defect_distribution: {
      stale_active_state: units.length
    }
  };
}

function buildRetrievalResult(problemUnits: ProblemUnit[]): UnifiedRetrievalResult {
  return {
    fragment_id: "F1",
    requirement_ids: ["R1"],
    route: "hybrid_store_plus_live",
    status: "ok",
    result_type: "chain",
    items: [
      {
        counterparty_id: "CP-1",
        operations_count: 5,
        document_refs_count: 3
      }
    ],
    raw_entities: [],
    candidate_evidence: [],
    problem_units: problemUnits,
    problem_unit_summary: buildSummary(problemUnits),
    summary: {
      broad_query_detected: true,
      broad_result_flag: true,
      minimum_evidence_failed: false,
      degraded_to: "partial",
      narrowing_strength: "weak"
    },
    evidence: [
      {
        evidence_id: "ev-1",
        claim_ref: "requirement:R1",
        source_type: "retrieval_item",
        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"
        },
        pointer: {
          fragment_id: "F1",
          route: "hybrid_store_plus_live",
          source: {
            namespace: "snapshot_2020",
            entity: "Document",
            id: "DOC-1",
            period: "2020-06"
          },
          locator: {
            field_path: "risk_score",
            item_index: 0
          }
        },
        evidence_kind: "mechanism_link",
        mechanism_note: "failed_edge=payment_to_settlement",
        confidence: "medium",
        limitation: null,
        payload: {
          risk_score: 5
        }
      }
    ],
    why_included: ["synthetic-test"],
    selection_reason: ["synthetic-test"],
    risk_factors: ["broken_chain"],
    business_interpretation: ["synthetic-test"],
    confidence: "medium",
    limitations: [],
    errors: []
  };
}

describe("assistant lifecycle-aware answer mode v1", () => {
  it("promotes stage3 lifecycle mode when lifecycle answer flag is enabled", () => {
    const units = [buildLifecycleProblemUnit()];
    const output = composeAssistantAnswer({
      userMessage: "Проверь, где зависли платежи по 51/60 и какой переход не завершился.",
      routeSummary: buildRouteSummary(),
      retrievalResults: [buildRetrievalResult(units)],
      requirements: [
        {
          requirement_id: "R1",
          source_fragment_id: "F1",
          requirement_text: "Проверить lifecycle-переход",
          subject_tokens: ["chain", "account_51", "account_60"],
          status: "covered",
          route: "hybrid_store_plus_live"
        }
      ],
      coverageReport: buildCoverage(true),
      groundingCheck: buildGrounding("partial"),
      enableAnswerPolicyV11: true,
      enableProblemCentricAnswerV1: true,
      enableLifecycleAnswerV1: true
    });

    expect(output.problem_centric_answer_applied).toBe(true);
    expect(output.problem_answer_mode).toBe("stage3_lifecycle_aware_v1");
    expect(output.answer_structure_v11?.answer_summary).toMatch(/lifecycle|Lifecycle/i);
    expect(output.answer_structure_v11?.direct_answer).toContain("current=stale_unlinked_payment");
    expect(output.answer_structure_v11?.direct_answer).toContain("expected=settlement_closed");
    expect(output.answer_structure_v11?.direct_answer).toContain("defect=stale_active_state");
  });
});

