from __future__ import annotations

from app.models.savings import (
    ProfileBaselineSnapshot,
    SavingsEvent,
    SavingsEvidenceLink,
    SavingsOpportunity,
    SavingsRealization,
)


def _constraint_names(model: type[object]) -> set[str]:
    return {
        str(constraint.name)
        for constraint in model.__table__.constraints  # type: ignore[attr-defined]
        if constraint.name is not None
    }


def test_savings_models_declare_tenant_safe_fact_and_audit_invariants() -> None:
    assert {
        ProfileBaselineSnapshot.__table__.name,
        SavingsOpportunity.__table__.name,
        SavingsRealization.__table__.name,
        SavingsEvidenceLink.__table__.name,
        SavingsEvent.__table__.name,
    } == {
        "profile_baseline_snapshots",
        "savings_opportunities",
        "savings_realizations",
        "savings_evidence_links",
        "savings_events",
    }

    assert {
        "uq_profile_baseline_snapshots_tenant_id",
        "uq_profile_baseline_snapshots_tenant_key",
        "ck_profile_baseline_snapshots_historical_shape",
        "ck_profile_baseline_snapshots_policy_shape",
        "ck_profile_baseline_snapshots_quality_status",
        "ck_profile_baseline_snapshots_keys",
    }.issubset(_constraint_names(ProfileBaselineSnapshot))
    assert {
        "uq_savings_opportunities_tenant_id",
        "uq_savings_opportunities_tenant_key",
        "fk_savings_opportunities_tenant_case",
        "fk_savings_opportunities_tenant_event",
        "fk_savings_opportunities_tenant_baseline",
        "fk_savings_opportunities_tenant_ai_decision",
        "ck_savings_opportunities_net_math",
        "ck_savings_opportunities_interval",
        "ck_savings_opportunities_currencies",
        "ck_savings_opportunities_acceptance",
        "ck_savings_opportunities_started",
        "ck_savings_opportunities_realized",
        "ck_savings_opportunities_verified",
        "ck_savings_opportunities_closed",
    }.issubset(_constraint_names(SavingsOpportunity))
    assert {
        "uq_savings_realizations_tenant_id",
        "uq_savings_realizations_tenant_key",
        "uq_savings_realizations_tenant_opportunity_benefit_id",
        "uq_savings_realizations_tenant_benefit_id",
        "fk_savings_realizations_tenant_opportunity",
        "fk_savings_realizations_tenant_case",
        "fk_savings_realizations_tenant_event",
        "fk_savings_realizations_tenant_reversal",
        "fk_savings_realizations_tenant_canonical",
        "ck_savings_realizations_amount_direction",
        "ck_savings_realizations_duplicate_target",
        "ck_savings_realizations_confirmation",
        "ck_savings_realizations_net_math",
        "ck_savings_realizations_currencies",
    }.issubset(_constraint_names(SavingsRealization))
    assert {
        "uq_savings_evidence_links_tenant_id",
        "uq_savings_evidence_links_tenant_key",
        "fk_savings_evidence_links_tenant_baseline",
        "fk_savings_evidence_links_tenant_opportunity",
        "fk_savings_evidence_links_tenant_realization",
        "ck_savings_evidence_links_entity_shape",
        "ck_savings_evidence_links_verifier",
        "ck_savings_evidence_links_keys",
    }.issubset(_constraint_names(SavingsEvidenceLink))
    assert {
        "uq_savings_events_tenant_id",
        "uq_savings_events_actor_request",
        "uq_savings_events_aggregate_version",
        "fk_savings_events_tenant_baseline",
        "fk_savings_events_tenant_opportunity",
        "fk_savings_events_tenant_realization",
        "ck_savings_events_aggregate_shape",
        "ck_savings_events_version",
        "ck_savings_events_request",
    }.issubset(_constraint_names(SavingsEvent))

    assert not SavingsOpportunity.__table__.c.claim_id.foreign_keys
    assert not SavingsOpportunity.__table__.c.claim_item_id.foreign_keys
    assert not SavingsRealization.__table__.c.claim_id.foreign_keys
    assert not SavingsRealization.__table__.c.claim_item_id.foreign_keys

    realization_constraints = {
        constraint.name: constraint for constraint in SavingsRealization.__table__.constraints
    }
    reversal_fk = realization_constraints["fk_savings_realizations_tenant_reversal"]
    assert tuple(reversal_fk.column_keys) == (
        "tenant_id",
        "opportunity_id",
        "benefit_key",
        "reversal_of_realization_id",
    )
    canonical_fk = realization_constraints["fk_savings_realizations_tenant_canonical"]
    assert tuple(canonical_fk.column_keys) == (
        "tenant_id",
        "benefit_key",
        "canonical_realization_id",
    )
    confirmation = realization_constraints["ck_savings_realizations_confirmation"]
    assert "finance_confirmer_id <> recorded_by_id" in str(confirmation.sqltext)
    assert "realization_type = 'reversal'" in str(confirmation.sqltext)

    canonical_index = next(
        index
        for index in SavingsRealization.__table__.indexes
        if index.name == "uq_savings_realizations_actual_canonical_benefit"
    )
    assert canonical_index.unique is True
    predicate = str(canonical_index.dialect_options["postgresql"]["where"])
    assert "realization_type = 'actual'" in predicate
    assert "dedupe_status = 'canonical'" in predicate
    assert SavingsEvent.__table__.c.response_json.nullable is False
