"""Regression tests for the squeeze-tail ACCOUNTING fix: the trustworthy squeeze-tail now OVERRIDES the
daily-close basis with the REAL stored `worst_basis` (mirroring Binance's carry_return_by_symbol), instead of
ADDING a high/low-proxy charge EVERY day (which compounded to −100% / Sharpe −20.85).

Proves:
  * worst_basis ≈ daily-close basis  ⇒  charge_squeeze_tail metrics ≈ no-tail metrics (NO blow-up);
  * a genuine squeeze day deepens DD / lowers return MODESTLY (not −100%);
  * a normal store with the OLD inflated daily high/low ranges (which the broken proxy would have charged)
    is NOT charged anymore — the override reads `worst_basis`, not high/low.
NO network — in-memory SQLite store.
"""
from __future__ import annotations

import math

from fxhnt.adapters.warehouse.timescale_feature_store import TimescaleFeatureStore
from fxhnt.application.bybit_carry_revalidate import carry_metrics_from_store

_DAY = 86_400


def _seed_carry(store: TimescaleFeatureStore, sym: str, *, days: int, funding: float,
                turnover: float, basis_drift: float = 0.0, range_frac: float = 0.03,
                worst_basis: dict[int, float] | None = None, wobble: float = 0.0002,
                idx: int = 0) -> None:
    """Seed one coin's funding + perp/spot close + a WIDE daily high/low band (range_frac, what the OLD
    broken proxy would have over-charged on) + turnover, and OPTIONALLY a stored `worst_basis` series."""
    rows = []
    perp_px = 100.0
    spot_px = 100.0
    for d in range(days):
        f = funding + wobble * math.cos(0.5 * d + idx)
        spot_px *= (1.0 + basis_drift)
        ph = perp_px * (1.0 + range_frac)
        pl = perp_px * (1.0 - range_frac)
        sh = spot_px * (1.0 + range_frac)
        sl = spot_px * (1.0 - range_frac)
        feats = {"funding": f, "close": perp_px, "spot_close": spot_px,
                 "high": ph, "low": pl, "spot_high": sh, "spot_low": sl, "turnover": turnover}
        if worst_basis is not None and d in worst_basis:
            feats["worst_basis"] = worst_basis[d]
        rows.append((d * _DAY, feats))
    store.write_features(sym, rows)


def _seed_book(store: TimescaleFeatureStore, *, days: int = 60, worst_basis_per_day: float | None = None,
               squeeze: tuple[int, float] | None = None) -> None:
    """6 dispersion coins. If `worst_basis_per_day` is set, every coin gets that benign worst_basis EVERY day
    (≈ the daily-close basis = ~0). `squeeze`=(day, value) injects ONE deep squeeze day into the LONG-side
    coins only (the high-funding longs the carry book holds long) — an ASYMMETRIC adverse basis that does NOT
    cancel in the dollar-neutral book, so it actually bites the curve (unlike a uniform move)."""
    coins = {"AAAUSDT": 0.001, "BBBUSDT": 0.001, "CCCUSDT": 0.001,
             "XXXUSDT": -0.001, "YYYUSDT": -0.001, "ZZZUSDT": -0.001}
    long_side = {"AAAUSDT", "BBBUSDT", "CCCUSDT"}
    for i, (sym, f) in enumerate(coins.items()):
        wb: dict[int, float] | None = None
        if worst_basis_per_day is not None:
            wb = {d: worst_basis_per_day for d in range(days)}
        if squeeze is not None and sym in long_side:
            wb = dict(wb or {})
            wb[squeeze[0]] = squeeze[1]
        _seed_carry(store, sym, days=days, funding=f, turnover=50_000_000.0, worst_basis=wb, idx=i)


def test_benign_worst_basis_matches_no_tail() -> None:
    """worst_basis ≈ 0 (≈ the daily-close basis on these flat-price coins) ⇒ the override barely changes the
    curve: charge_squeeze_tail metrics ≈ no-tail metrics. This is the NO-BLOW-UP proof: the override does not
    subtract a charge every day."""
    store = TimescaleFeatureStore("sqlite://", table="bybit_features")
    _seed_book(store, worst_basis_per_day=0.0)   # benign worst_basis every day == close basis (~0)
    no_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=False)
    with_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=True)
    store.close()
    assert math.isclose(with_tail["total_return"], no_tail["total_return"], rel_tol=1e-9, abs_tol=1e-9)
    assert math.isclose(with_tail["sharpe"], no_tail["sharpe"], rel_tol=1e-9, abs_tol=1e-9)
    # And the curve is NOT −100% (the old additive bug).
    assert with_tail["total_return"] > -0.5


def test_real_squeeze_day_lowers_return_modestly_not_minus_100() -> None:
    """A single genuine squeeze day (worst_basis −0.15 on one day, benign otherwise) deepens DD / lowers
    return MODESTLY — NOT the −100% the additive proxy produced."""
    store = TimescaleFeatureStore("sqlite://", table="bybit_features")
    _seed_book(store, worst_basis_per_day=0.0, squeeze=(40, -0.15))
    no_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=False)
    with_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=True)
    store.close()
    # The squeeze bites: return lower, DD deeper.
    assert with_tail["total_return"] < no_tail["total_return"]
    assert with_tail["max_dd"] <= no_tail["max_dd"]
    # But it is a MODEST single-day hit, not a −100% wipeout.
    assert with_tail["total_return"] > -0.5


def test_override_ignores_high_low_ranges() -> None:
    """The OLD broken proxy charged abs(spot_low/perp_high−1) EVERY day from the WIDE high/low band. The fix
    reads `worst_basis` only — so a store with a wide high/low band but NO worst_basis is charged NOTHING
    (falls back to daily-close basis), bit-identical to no-tail."""
    store = TimescaleFeatureStore("sqlite://", table="bybit_features")
    # range_frac=0.05 → the old proxy would have charged ~10% adverse basis EVERY day (→ −100%).
    _seed_book(store, worst_basis_per_day=None)   # NO worst_basis feature at all
    no_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=False)
    with_tail = carry_metrics_from_store(store, cost_bps=0.0, charge_squeeze_tail=True)
    store.close()
    # No worst_basis stored → override has nothing → identical to no-tail (NOT the −100% proxy artifact).
    assert math.isclose(with_tail["total_return"], no_tail["total_return"], rel_tol=1e-9, abs_tol=1e-9)
    assert with_tail["total_return"] > -0.5
