"""19-variable credit ontology as a WorldDAG.

Defines the causal structure of credit risk: macro → borrower → loan → performance.
Each entity has causal role, variable type, bounds, sensitivity, and regulatory tags.
Each edge has mechanism, confidence, and temporal lag.
"""

from __future__ import annotations

from orxaq.kernel import (
    CausalEdge,
    CausalRole,
    Entity,
    SensitivityLevel,
    VariableType,
    WorldDAG,
)

CREDIT_VARIABLES: dict[str, str] = {
    "unemployment_rate": "National unemployment rate",
    "fed_funds_rate": "Federal funds target rate",
    "hpi": "House price index",
    "gdp_growth": "Real GDP growth rate",
    "cpi": "Consumer price index",
    "credit_score": "Borrower FICO credit score",
    "dti": "Debt-to-income ratio",
    "income": "Borrower annual income",
    "employment_length": "Years of continuous employment",
    "age": "Borrower age in years",
    "loan_amount": "Original loan amount",
    "interest_rate": "Loan interest rate",
    "ltv": "Loan-to-value ratio",
    "term": "Loan term in months",
    "dpd_30": "30+ days past due flag",
    "dpd_60": "60+ days past due flag",
    "dpd_90": "90+ days past due flag",
    "current_balance": "Current outstanding balance",
    "default_flag": "Loan default indicator",
}

_ENTITIES: list[Entity] = [
    # Macro variables (all exogenous)
    Entity(
        entity_id="unemployment_rate",
        name="Unemployment Rate",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.MACRO,
        bounds=(0.0, 0.30),
        regulatory_tags=("CCAR", "DFAST"),
        domain="macro",
    ),
    Entity(
        entity_id="fed_funds_rate",
        name="Federal Funds Rate",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.MACRO,
        bounds=(-0.01, 0.20),
        regulatory_tags=("CCAR",),
        domain="macro",
    ),
    Entity(
        entity_id="hpi",
        name="House Price Index",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.MACRO,
        bounds=(0.0, None),
        regulatory_tags=("CCAR",),
        domain="macro",
    ),
    Entity(
        entity_id="gdp_growth",
        name="GDP Growth Rate",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.MACRO,
        bounds=(-0.10, 0.15),
        regulatory_tags=("CCAR", "DFAST"),
        domain="macro",
    ),
    Entity(
        entity_id="cpi",
        name="Consumer Price Index",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.MACRO,
        bounds=(0.0, None),
        regulatory_tags=("CCAR",),
        domain="macro",
    ),
    # Borrower variables
    Entity(
        entity_id="credit_score",
        name="Credit Score",
        causal_role=CausalRole.CONFOUNDER,
        variable_type=VariableType.DYNAMIC,
        bounds=(300.0, 850.0),
        regulatory_tags=("CECL", "CCAR", "CFPB"),
        domain="borrower",
    ),
    Entity(
        entity_id="dti",
        name="Debt-to-Income Ratio",
        causal_role=CausalRole.CONFOUNDER,
        variable_type=VariableType.DYNAMIC,
        bounds=(0.0, 1.0),
        domain="borrower",
    ),
    Entity(
        entity_id="income",
        name="Annual Income",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        sensitivity=SensitivityLevel.CONFIDENTIAL,
        domain="borrower",
    ),
    Entity(
        entity_id="employment_length",
        name="Employment Length",
        causal_role=CausalRole.CONFOUNDER,
        variable_type=VariableType.STATIC,
        bounds=(0.0, 50.0),
        domain="borrower",
    ),
    Entity(
        entity_id="age",
        name="Borrower Age",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.STATIC,
        sensitivity=SensitivityLevel.RESTRICTED,
        bounds=(18.0, 100.0),
        regulatory_tags=("CFPB", "ECOA"),
        domain="borrower",
    ),
    # Loan variables
    Entity(
        entity_id="loan_amount",
        name="Loan Amount",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.STATIC,
        bounds=(1000.0, None),
        domain="loan",
    ),
    Entity(
        entity_id="interest_rate",
        name="Interest Rate",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL", "CCAR"),
        domain="loan",
    ),
    Entity(
        entity_id="ltv",
        name="Loan-to-Value Ratio",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        bounds=(0.0, 2.0),
        domain="loan",
    ),
    Entity(
        entity_id="term",
        name="Loan Term",
        causal_role=CausalRole.EXOGENOUS,
        variable_type=VariableType.STATIC,
        domain="loan",
    ),
    # Performance variables
    Entity(
        entity_id="dpd_30",
        name="30 Days Past Due",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL",),
        domain="performance",
    ),
    Entity(
        entity_id="dpd_60",
        name="60 Days Past Due",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL",),
        domain="performance",
    ),
    Entity(
        entity_id="dpd_90",
        name="90 Days Past Due",
        causal_role=CausalRole.MEDIATOR,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL",),
        domain="performance",
    ),
    Entity(
        entity_id="current_balance",
        name="Current Balance",
        causal_role=CausalRole.OUTCOME,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL",),
        domain="performance",
    ),
    Entity(
        entity_id="default_flag",
        name="Default Flag",
        causal_role=CausalRole.OUTCOME,
        variable_type=VariableType.DYNAMIC,
        regulatory_tags=("CECL", "CCAR", "CFPB"),
        domain="performance",
    ),
]

_EDGES: list[CausalEdge] = [
    # Macro → Borrower
    CausalEdge(
        source="unemployment_rate",
        target="income",
        mechanism="Job loss reduces income",
        confidence=0.85,
        temporal_lag=1.0,
        provenance="BLS labor statistics",
    ),
    CausalEdge(
        source="unemployment_rate",
        target="employment_length",
        mechanism="Layoffs truncate tenure",
        confidence=0.75,
        temporal_lag=0.5,
        provenance="BLS labor statistics",
    ),
    CausalEdge(
        source="fed_funds_rate",
        target="interest_rate",
        mechanism="Rate transmission to lending rates",
        confidence=0.90,
        temporal_lag=0.25,
        provenance="Federal Reserve monetary policy",
    ),
    CausalEdge(
        source="hpi",
        target="ltv",
        mechanism="Home price changes shift LTV denominator",
        confidence=0.88,
        temporal_lag=1.0,
        provenance="FHFA house price index",
    ),
    CausalEdge(
        source="gdp_growth",
        target="income",
        mechanism="Economic growth supports wage growth",
        confidence=0.70,
        temporal_lag=2.0,
        provenance="BEA GDP data",
    ),
    CausalEdge(
        source="cpi",
        target="dti",
        mechanism="Inflation erodes real income, increasing DTI",
        confidence=0.65,
        temporal_lag=1.0,
        provenance="BLS CPI data",
    ),
    # Borrower → Performance
    CausalEdge(
        source="credit_score",
        target="dpd_30",
        mechanism="Creditworthiness predicts payment behavior",
        confidence=0.82,
        provenance="Credit bureau performance data",
    ),
    CausalEdge(
        source="dti",
        target="dpd_30",
        mechanism="Debt burden strains payment capacity",
        confidence=0.78,
        provenance="Loan servicing records",
    ),
    CausalEdge(
        source="income",
        target="dpd_30",
        mechanism="Income buffers payment ability",
        confidence=0.80,
        provenance="Income verification data",
    ),
    CausalEdge(
        source="employment_length",
        target="dpd_30",
        mechanism="Tenure signals job stability",
        confidence=0.60,
        provenance="Employment verification",
    ),
    # Loan → Performance
    CausalEdge(
        source="interest_rate",
        target="dpd_30",
        mechanism="Higher payments increase delinquency risk",
        confidence=0.75,
        provenance="Loan servicing records",
    ),
    CausalEdge(
        source="ltv",
        target="default_flag",
        mechanism="Underwater borrowers strategically default",
        confidence=0.83,
        provenance="Mortgage performance data",
    ),
    CausalEdge(
        source="loan_amount",
        target="current_balance",
        mechanism="Original amount drives outstanding balance",
        confidence=0.95,
        provenance="Loan origination records",
    ),
    # Performance cascade
    CausalEdge(
        source="dpd_30",
        target="dpd_60",
        mechanism="Delinquency escalation — 30 to 60 days",
        confidence=0.88,
        provenance="Roll rate analysis",
    ),
    CausalEdge(
        source="dpd_60",
        target="dpd_90",
        mechanism="Further deterioration — 60 to 90 days",
        confidence=0.85,
        provenance="Roll rate analysis",
    ),
    CausalEdge(
        source="dpd_90",
        target="default_flag",
        mechanism="Severe delinquency leads to default",
        confidence=0.90,
        provenance="Loss mitigation records",
    ),
    # Age → Employment (legitimate indirect path for fair lending)
    CausalEdge(
        source="age",
        target="employment_length",
        mechanism="Older borrowers have longer potential tenure",
        confidence=0.70,
        provenance="Demographic data",
    ),
]


def build_credit_ontology() -> WorldDAG:
    """Build the 19-variable credit risk WorldDAG.

    Returns a WorldDAG with 19 entities and ~17 causal edges representing
    the causal structure of credit risk: macro → borrower → loan → performance.
    """
    dag = WorldDAG()

    for entity in _ENTITIES:
        dag.add_entity(entity)

    for edge in _EDGES:
        dag.add_edge(edge)

    return dag


def get_regulatory_variables(tag: str) -> list[Entity]:
    """Return entities that have the specified regulatory tag."""
    return [e for e in _ENTITIES if tag in e.regulatory_tags]


def get_macro_variables() -> list[Entity]:
    """Return all macro-domain entities."""
    return [e for e in _ENTITIES if e.domain == "macro"]
