"""Funding-specific pricing router.

The funding router stays separate from the bond router because repo trades use
raw decimal funding rates, percent-of-par collateral prices, and currency cash
amounts rather than bond clean-price conventions.
"""

from __future__ import annotations

from dataclasses import dataclass
from decimal import Decimal

from fuggers_py.funding.curves import RepoCurve
from fuggers_py.funding.instruments import RepoTrade


@dataclass(frozen=True, slots=True)
class RepoPricingResult:
    """Structured pricing output for a repo trade."""

    collateral_value: Decimal
    haircut_amount: Decimal
    cash_lent: Decimal
    year_fraction: Decimal
    interest_amount: Decimal
    repurchase_amount: Decimal
    curve_zero_rate: Decimal | None = None
    forward_rate: Decimal | None = None
    funding_spread: Decimal | None = None


@dataclass(frozen=True, slots=True)
class FundingPricingRouter:
    """Price repo trades against an optional repo curve."""

    def price_repo(self, trade: RepoTrade, *, repo_curve: object | None = None) -> RepoPricingResult:
        """Price a repo trade and report carry and spread diagnostics.

        The funding spread is reported as ``trade.rate - curve_zero_rate`` so a
        positive spread indicates the trade funds above the curve.
        """
        active_curve = None if repo_curve is None else RepoCurve.of(repo_curve)
        zero_rate = None if active_curve is None else active_curve.zero_rate(trade.end_date)
        forward_rate = None if active_curve is None else active_curve.forward_rate(trade.start_date, trade.end_date)
        return RepoPricingResult(
            collateral_value=trade.collateral_market_value(),
            haircut_amount=trade.haircut_amount(),
            cash_lent=trade.cash_lent(),
            year_fraction=trade.year_fraction(),
            interest_amount=trade.interest_amount(),
            repurchase_amount=trade.repurchase_amount(),
            curve_zero_rate=zero_rate,
            forward_rate=forward_rate,
            funding_spread=None if zero_rate is None else trade.rate - zero_rate,
        )

    def price_batch(self, trades: list[RepoTrade] | tuple[RepoTrade, ...], *, repo_curve: object | None = None) -> tuple[RepoPricingResult, ...]:
        """Price a batch of repo trades against the same curve input."""
        return tuple(self.price_repo(trade, repo_curve=repo_curve) for trade in trades)


__all__ = ["FundingPricingRouter", "RepoPricingResult"]
