"""
Tests for individual CXR model variants (k1, k2, sim1, lite1, audit1).
"""

from copy import deepcopy

import pytest

from kernel_service.models.k1 import CXRK1Model
from kernel_service.models.k2 import CXRK2Model
from kernel_service.models.sim1 import CXRSim1Model
from kernel_service.models.lite1 import CXRLite1Model
from kernel_service.models.audit1 import CXRAudit1Model


class FakeContextCollector:
    """Stub context collector returning deterministic values."""

    def get_patient_context(self, claim):
        return {"patient_denial_rate": 0.2, "patient_risk_flag": False}

    def get_provider_context(self, claim):
        return {"provider_denial_rate": 0.25, "provider_risk_level": "MODERATE"}

    def get_payer_context(self, claim, archetype_code):
        return {"payer_denial_rate": 0.3, "payer_strictness": "MODERATE"}

    def get_temporal_context(self, claim):
        return {"claim_age_days": 60, "is_urgent": False}

    def get_financial_context(self, claim):
        return {"financial_zscore": 1.2}

    def get_relationship_context(self, claim):
        return {}

    def get_policy_context(self, claim, archetype_code=None):
        return {"policy_days_active": 120}


class FakeSevenPlaneFusionEngine:
    """Stub SevenPlaneFusionEngine with configurable fused confidence."""

    def __init__(self, fused_confidence=0.85):
        self.fused_confidence = fused_confidence
        self.default_weights = {
            "structured": 0.25,
            "unstructured": 0.15,
            "contextual": 0.10,
            "patient": 0.15,
            "provider": 0.15,
            "payer": 0.10,
            "temporal": 0.10,
        }

    def get_structured_evidence(self, claim, archetype_code):
        return 0.8

    def get_unstructured_evidence(self, claim, archetype):
        return 0.7

    def get_contextual_evidence(self, claim):
        return 0.6

    def get_patient_evidence(self, context):
        return context.get("patient_denial_rate", 0.5)

    def get_provider_evidence(self, context):
        return context.get("provider_denial_rate", 0.4)

    def get_payer_evidence(self, context):
        return context.get("payer_denial_rate", 0.3)

    def get_temporal_evidence(self, context):
        return 0.55

    def fuse(self, evidence, weights=None):
        weights = weights or self.default_weights
        contributions = {}
        for plane, weight in weights.items():
            score = evidence.get(plane, 0.5)
            contributions[plane] = {
                "score": score,
                "weight": weight,
                "contribution": score * weight,
            }
        return self.fused_confidence, contributions


class FakeThreePlaneFusionEngine:
    """Stub EvidenceFusionEngine for lite1 model."""

    def get_structured_evidence(self, claim, archetype_code):
        return {"confidence": 0.8}

    def get_unstructured_evidence(self, claim, archetype):
        return {"confidence": 0.7}

    def get_contextual_evidence(self, claim):
        return {"confidence": 0.6}


class FakeMonteCarlo:
    """Stub Monte Carlo simulator returning deterministic results."""

    def forecast_recovery(self, base_amount, confidence, volatility=0.2):
        return {
            "mean": 123.45,
            "median": 120.0,
            "p5": 80.0,
            "p25": 100.0,
            "p75": 140.0,
            "p95": 160.0,
            "std_dev": 15.0,
            "confidence_interval_95": (80.0, 160.0),
        }

    def simulate_denial_scenarios(self, claim_amount, denial_probability, num_scenarios=100):
        return {
            "expected_recovery": 110.0,
            "denial_rate": denial_probability,
            "scenarios_simulated": num_scenarios,
        }


def _prep_claim(sample_claim, **metadata):
    claim = deepcopy(sample_claim)
    claim.setdefault("metadata", {}).update(metadata)
    return claim


def test_k1_high_confidence_triggers_review(sample_claim):
    model = CXRK1Model()
    model._fusion_engine = FakeSevenPlaneFusionEngine(fused_confidence=0.9)
    model._context_collector = FakeContextCollector()

    claim = _prep_claim(sample_claim, reviewThreshold=0.8)
    result = model._analyze_claim(claim, tenant_id="tenant")

    assert result["verdict"] == "pending_review"
    assert result["explanation"]["fused_confidence"] == pytest.approx(0.9)
    assert len(result["explanation"]["drivers"]) > 0


def test_k1_medium_confidence_denied(sample_claim):
    model = CXRK1Model()
    model._fusion_engine = FakeSevenPlaneFusionEngine(fused_confidence=0.6)
    model._context_collector = FakeContextCollector()

    claim = _prep_claim(sample_claim, reviewThreshold=0.8)
    result = model._analyze_claim(claim, tenant_id="tenant")

    assert result["verdict"] == "denied"


def test_k2_custom_weights_and_threshold(sample_claim):
    model = CXRK2Model()
    model._fusion_engine = FakeSevenPlaneFusionEngine(fused_confidence=0.7)
    model._context_collector = FakeContextCollector()

    claim = _prep_claim(sample_claim)  # default 0.75 threshold
    result = model._analyze_claim(claim, tenant_id="tenant")

    assert result["verdict"] == "denied"  # 0.7 < 0.75 threshold but >= 0.45
    assert any("weight" in driver for driver in result["explanation"]["drivers"])


def test_sim1_includes_monte_carlo(sample_claim):
    model = CXRSim1Model()
    model._fusion_engine = FakeSevenPlaneFusionEngine(fused_confidence=0.65)
    model._context_collector = FakeContextCollector()
    model._monte_carlo = FakeMonteCarlo()

    claim = _prep_claim(sample_claim, reviewThreshold=0.8)
    result = model._analyze_claim(claim, tenant_id="tenant")

    assert result["verdict"] == "denied"
    assert "monteCarlo" in result["financialImpact"]
    assert result["financialImpact"]["monteCarlo"]["mean"] == 123.45


def test_lite1_fast_fusion(sample_claim):
    model = CXRLite1Model()
    model._fusion_engine = FakeThreePlaneFusionEngine()

    result = model._analyze_claim(sample_claim, tenant_id="tenant")

    assert result["explanation"]["summary"].startswith("Fast analysis")
    assert result["financialImpact"]["currency"] == "USD"


def test_audit1_compliance_enforced(sample_claim):
    model = CXRAudit1Model()
    model._fusion_engine = FakeSevenPlaneFusionEngine(fused_confidence=0.55)
    model._context_collector = FakeContextCollector()

    # Remove documentation to trigger compliance issues
    claim = deepcopy(sample_claim)
    claim.pop("documentation", None)

    result = model._analyze_claim(claim, tenant_id="tenant")

    assert result["verdict"] == "pending_review"
    assert result["explanation"]["compliance"]["issues"]

