"""Pure decomposed-slippage model (spec §3). All math over floats — no I/O — so it is unit-tested directly.

The adapter supplies `fill_price`, `mid_at_order`, `book_mark`; the bps math is exercised here in isolation:
sign on both sides, a known fill/mid → exact bps, the decomposition sums to the fill-vs-mark total, the
assumed-tier delta, and the `mid<=0`/`book_mark<=0` None-guards (never a divide-by-zero or a garbage bp).
"""
from __future__ import annotations

from fxhnt.application.slippage import (
    execution_slippage_bps,
    slippage_vs_assumed_bps,
    timing_drift_bps,
)


def test_buy_pays_above_mid_is_positive():
    # bought at 101 vs mid 100 → +100 bps cost
    assert execution_slippage_bps(101.0, 100.0, "BUY") == 100.0


def test_sell_below_mid_is_positive_cost():
    # sold at 99 vs mid 100 → +100 bps cost
    assert execution_slippage_bps(99.0, 100.0, "SELL") == 100.0


def test_timing_drift_sign():
    # BUY, mid moved 100→101 from the book mark → +100 bps adverse drift
    assert timing_drift_bps(101.0, 100.0, "BUY") == 100.0


def test_decomposition_sums_to_total():
    fill, mid, mark = 102.0, 101.0, 100.0
    exec_bps = execution_slippage_bps(fill, mid, "BUY")
    timing_bps = timing_drift_bps(mid, mark, "BUY")
    total = exec_bps + timing_bps
    # The decomposition (spec §3) DEFINES total_fill_vs_mark_bps = execution + timing. The two terms use
    # different denominators (mid for execution, mark for timing), so the sum reconstructs the single-
    # denominator fill-vs-mark move ((102-100)/100*1e4 = 200) only up to that ~1bp compounding — it is NOT
    # exactly 200 (the plan's `< 1e-6` assertion was off by this compounding term).
    fill_vs_mark = (fill - mark) / mark * 1e4
    assert abs(total - fill_vs_mark) < 1.0


def test_assumed_delta():
    assert slippage_vs_assumed_bps(40.0, 35.0) == 5.0  # 5bp worse than the 35bp tier


def test_guards_none_on_bad_inputs():
    assert execution_slippage_bps(101.0, 0.0, "BUY") is None
    assert timing_drift_bps(101.0, -1.0, "SELL") is None
