"""Tests for credit risk reporting module."""

from __future__ import annotations

import json

from orxaq.credit.reporting import (
    ReportSection,
    RiskReport,
    RiskReportBuilder,
    _classify_risk,
)


class TestClassifyRisk:
    def test_critical_high_ratio(self) -> None:
        assert _classify_risk(60.0, 100.0) == "critical"

    def test_high_ratio(self) -> None:
        assert _classify_risk(35.0, 100.0) == "high"

    def test_moderate_ratio(self) -> None:
        assert _classify_risk(20.0, 100.0) == "moderate"

    def test_low_ratio(self) -> None:
        assert _classify_risk(10.0, 100.0) == "low"

    def test_zero_ec_with_el(self) -> None:
        assert _classify_risk(1.0, 0.0) == "critical"

    def test_zero_both(self) -> None:
        assert _classify_risk(0.0, 0.0) == "low"

    def test_boundary_critical(self) -> None:
        assert _classify_risk(50.1, 100.0) == "critical"

    def test_boundary_high(self) -> None:
        assert _classify_risk(30.1, 100.0) == "high"

    def test_boundary_moderate(self) -> None:
        assert _classify_risk(15.1, 100.0) == "moderate"


class TestReportSection:
    def test_frozen(self) -> None:
        s = ReportSection(title="Test", metrics={"a": 1.0}, narrative="ok")
        assert s.title == "Test"
        assert s.metrics == {"a": 1.0}
        assert s.narrative == "ok"


class TestRiskReport:
    def _sample_report(self) -> RiskReport:
        return RiskReport(
            report_id="test-123",
            generated_at="2026-02-18T00:00:00Z",
            sections=[
                ReportSection(title="S1", metrics={"m1": 1.0}, narrative="n1"),
                ReportSection(title="S2", metrics={"m2": 2.0}, narrative="n2"),
            ],
            summary="Test summary",
            risk_rating="moderate",
        )

    def test_to_dict(self) -> None:
        r = self._sample_report()
        d = r.to_dict()
        assert d["report_id"] == "test-123"
        assert d["risk_rating"] == "moderate"
        assert len(d["sections"]) == 2
        assert d["sections"][0]["title"] == "S1"

    def test_to_dict_json_serializable(self) -> None:
        r = self._sample_report()
        s = json.dumps(r.to_dict())
        assert '"test-123"' in s

    def test_to_text(self) -> None:
        r = self._sample_report()
        text = r.to_text()
        assert "MODERATE" in text
        assert "test-123" in text
        assert "S1" in text
        assert "S2" in text
        assert "Test summary" in text


class TestRiskReportBuilder:
    def test_empty_build(self) -> None:
        report = RiskReportBuilder().build()
        assert report.risk_rating == "low"
        assert report.sections == []
        assert report.report_id  # uuid generated
        assert report.generated_at  # timestamp generated

    def test_portfolio_section(self) -> None:
        builder = RiskReportBuilder()
        builder.add_portfolio_section(
            expected_loss=2000.0,
            unexpected_loss=5000.0,
            economic_capital=11630.0,
            hhi=0.05,
            gini=0.3,
            count=100,
            total_ead=1_000_000.0,
        )
        report = builder.build()
        assert len(report.sections) == 1
        assert report.sections[0].title == "Portfolio Risk Metrics"
        assert report.sections[0].metrics["expected_loss"] == 2000.0
        assert "low" in report.sections[0].narrative  # HHI 0.05 = low concentration

    def test_ecl_section(self) -> None:
        builder = RiskReportBuilder()
        builder.add_ecl_section(
            total_ecl=1500.0,
            horizon_quarters=8,
            horizon_method="soliton_dynamic",
            pd_mean=0.05,
            lgd=0.45,
            confidence_low=1200.0,
            confidence_high=1800.0,
        )
        report = builder.build()
        assert len(report.sections) == 1
        assert "CECL" in report.sections[0].title
        assert report.sections[0].metrics["total_ecl"] == 1500.0

    def test_stress_section(self) -> None:
        builder = RiskReportBuilder()
        builder.add_stress_section(
            scenario_name="adverse",
            base_el=2000.0,
            stressed_el=3500.0,
            base_ec=10000.0,
            stressed_ec=15000.0,
        )
        report = builder.build()
        s = report.sections[0]
        assert "adverse" in s.title
        assert s.metrics["delta_el"] == 1500.0
        assert s.metrics["delta_ec"] == 5000.0

    def test_fairness_section(self) -> None:
        builder = RiskReportBuilder()
        builder.add_fairness_section(
            protected_var="age",
            total_effect=0.02,
            direct_effect=0.01,
            indirect_paths=3,
            concerning_paths=1,
        )
        report = builder.build()
        s = report.sections[0]
        assert "Fair Lending" in s.title
        assert "elevated" in s.narrative

    def test_fairness_no_concern(self) -> None:
        builder = RiskReportBuilder()
        builder.add_fairness_section(
            protected_var="age",
            total_effect=0.001,
            direct_effect=0.0005,
            indirect_paths=2,
            concerning_paths=0,
        )
        report = builder.build()
        assert "acceptable" in report.sections[0].narrative

    def test_full_report(self) -> None:
        report = (
            RiskReportBuilder()
            .add_portfolio_section(
                expected_loss=5000.0,
                unexpected_loss=8000.0,
                economic_capital=18608.0,
                hhi=0.15,
                gini=0.4,
                count=50,
                total_ead=500_000.0,
            )
            .add_ecl_section(
                total_ecl=4500.0,
                horizon_quarters=12,
                horizon_method="soliton_dynamic",
                pd_mean=0.08,
                lgd=0.45,
                confidence_low=3600.0,
                confidence_high=5400.0,
            )
            .add_stress_section(
                scenario_name="severely_adverse",
                base_el=5000.0,
                stressed_el=9000.0,
                base_ec=18608.0,
                stressed_ec=25000.0,
            )
            .add_fairness_section(
                protected_var="race",
                total_effect=0.03,
                direct_effect=0.01,
                indirect_paths=4,
                concerning_paths=2,
            )
            .build()
        )
        assert len(report.sections) == 4
        assert report.risk_rating == "moderate"  # 5000/18608 ≈ 0.269
        assert "5,000" in report.summary
        assert report.to_dict()["sections"][0]["title"] == "Portfolio Risk Metrics"

    def test_fluent_interface(self) -> None:
        builder = RiskReportBuilder()
        result = builder.add_portfolio_section(
            expected_loss=100.0,
            unexpected_loss=200.0,
            economic_capital=465.2,
            hhi=0.5,
            gini=0.1,
            count=5,
            total_ead=10000.0,
        )
        assert result is builder  # fluent returns self

    def test_risk_rating_critical(self) -> None:
        report = (
            RiskReportBuilder()
            .add_portfolio_section(
                expected_loss=600.0,
                unexpected_loss=100.0,
                economic_capital=232.6,
                hhi=1.0,
                gini=0.0,
                count=1,
                total_ead=1000.0,
            )
            .build()
        )
        assert report.risk_rating == "critical"  # 600/232.6 > 0.5

    def test_concentration_high(self) -> None:
        builder = RiskReportBuilder()
        builder.add_portfolio_section(
            expected_loss=100.0,
            unexpected_loss=200.0,
            economic_capital=465.2,
            hhi=0.30,
            gini=0.5,
            count=3,
            total_ead=50000.0,
        )
        report = builder.build()
        assert "high" in report.sections[0].narrative

    def test_concentration_moderate(self) -> None:
        builder = RiskReportBuilder()
        builder.add_portfolio_section(
            expected_loss=100.0,
            unexpected_loss=200.0,
            economic_capital=465.2,
            hhi=0.15,
            gini=0.3,
            count=10,
            total_ead=100000.0,
        )
        report = builder.build()
        assert "moderate" in report.sections[0].narrative
