"""Build the unlock sleeve from the WAREHOUSE close panel (not crypto_pit_dir): the warehouse holds
{sym: {epoch_day: close}}; `warehouse_unlock_panel` adapts it to the (close, qvol, funding) tuple the
runner needs (fallback qvol clears min_qvol; funding 0.0 — documented approximation). A name with a
cliff in the historical-cliff calendar must surface a NEGATIVE (short) weight in its pre-cliff window."""
from fxhnt.application.unlock_runner import UnlockShortRunner, warehouse_unlock_panel


def _close_series(start, n, close=100.0, vol=0.03):
    out = {}
    px = close
    for i in range(n):
        px = px * (1.0 + (vol if i % 2 == 0 else -vol))
        out[start + i] = px
    return out


def test_warehouse_panel_yields_pre_cliff_short():
    # warehouse close panel ({sym: {epoch_day: close}}) for ALT + BTC
    close_panel = {
        "ALTUSDT": _close_series(100, 80),
        "BTCUSDT": _close_series(100, 80),
    }
    panel = warehouse_unlock_panel(close_panel)
    # tuple shape (close, qvol, funding); qvol clears the default min_qvol; funding neutral
    day = next(iter(panel["ALTUSDT"]))
    close, qvol, funding = panel["ALTUSDT"][day]
    assert close > 0 and qvol >= 5e6 and funding == 0.0

    events = [{"sym": "ALT", "cliff_day": 150, "n": 5e7, "cat": "insiders"}]
    r = UnlockShortRunner(panel, events, pre_window=10, min_shock=0.0)
    w = r.current_weights("epoch:145")  # 140 <= 145 < 150 -> in window
    assert w.get("ALTUSDT", 0.0) < 0


def test_warehouse_panel_skips_name_without_closes():
    # a symbol with an empty close series is skipped (never crashes)
    close_panel = {"ALTUSDT": _close_series(100, 80), "DEADUSDT": {}}
    panel = warehouse_unlock_panel(close_panel)
    assert "DEADUSDT" not in panel
    assert "ALTUSDT" in panel
