"""Unit tests for bond risk scoring — matches PMChat test conventions."""
import pytest
from app.scoring.bond import compute_bond_risk, _spread_score


# ── Composite scoring ─────────────────────────────────────────────────────────

def test_aaa_low_spread_is_low_risk():
    result = compute_bond_risk(
        isin="TEST1",
        rating_sp="AAA",
        z_spread=30.0,
    )
    assert result.composite_grade == "LOW RISK"
    assert result.is_investment_grade is True
    assert result.composite_score >= 75


def test_ccc_wide_spread_is_high_risk():
    result = compute_bond_risk(
        isin="TEST2",
        rating_moodys="Caa2",
        z_spread=900.0,
    )
    assert result.composite_grade == "HIGH RISK"
    assert result.is_investment_grade is False
    assert result.composite_score < 35


def test_bbb_moderate_risk():
    result = compute_bond_risk(
        isin="TEST3",
        rating_sp="BBB",
        z_spread=150.0,
    )
    assert result.composite_grade in {"MODERATE RISK", "ELEVATED RISK"}
    assert result.is_investment_grade is True


def test_spread_priority_z_spread_over_asset_swap_spread():
    result = compute_bond_risk(
        isin="TEST4",
        z_spread=100.0,
        asset_swap_spread=500.0,
    )
    assert result.spread_used == "z_spread"
    assert result.spread_bps == 100.0


def test_spread_fallback_to_z_spread():
    result = compute_bond_risk(
        isin="TEST5",
        z_spread=200.0,
    )
    assert result.spread_used == "z_spread"


def test_no_rating_redistributes_weights():
    result = compute_bond_risk(
        isin="TEST6",
        z_spread=50.0,
    )
    assert result.rating_score is None
    assert result.rating_grade is None
    assert 0.0 <= result.composite_score <= 100.0


def test_all_missing_data_returns_neutral():
    result = compute_bond_risk(isin="TEST7")
    assert result.spread_used == "none"
    assert result.spread_bps is None
    assert result.spread_score == 50.0


# ── Spread score thresholds ───────────────────────────────────────────────────

@pytest.mark.parametrize("bps,expected", [
    (30,   100.0),
    (75,    90.0),
    (150,   75.0),
    (300,   55.0),
    (450,   40.0),
    (600,   25.0),
    (1000,  10.0),
])
def test_spread_score_thresholds(bps, expected):
    assert _spread_score(bps) == expected
