"""I-spread helpers.

I-spreads are reported in basis points. The underlying swap rate is pulled as
a raw decimal from the supplied yield curve.
"""

from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal

from fuggers_py.bonds.traits import Bond
from fuggers_py.core.traits import YieldCurve
from fuggers_py.core.types import Date

from .benchmark import _to_decimal
from ..error import AnalyticsError


def i_spread(bond_yield: object, swap_rate: object) -> Decimal:
    """Return the I-spread in basis points."""
    by = _to_decimal(bond_yield)
    sr = _to_decimal(swap_rate)
    return (by - sr) * Decimal(10_000)


@dataclass(frozen=True, slots=True)
class ISpreadCalculator:
    """Curve-backed I-spread calculator returning basis-point outputs."""

    curve: YieldCurve

    def spread_bps(self, bond: Bond, bond_yield: object, settlement_date: Date | None = None) -> Decimal:
        """Return the I-spread in basis points for `bond`."""
        maturity = bond.maturity_date()
        if settlement_date is not None and settlement_date >= maturity:
            raise AnalyticsError.invalid_settlement("Settlement date must be before maturity for I-spread.")
        swap_rate = self.curve.zero_rate(maturity).value()
        return i_spread(bond_yield, swap_rate)


__all__ = ["ISpreadCalculator", "i_spread"]
