"""Test dello sleeve VRP01 (options short-vol: put credit spread + gate IV-rank)."""
import sys
from pathlib import Path

import numpy as np
import pandas as pd
import pytest

PROJECT_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJECT_ROOT))

from src.portfolio.sleeves import (
    _bs_put, _strike_from_delta, _vrp_combo_returns, vrp_sleeve, _HL_DIR)

_HAS_DVOL = (_HL_DIR / "dvol_btc.parquet").exists() and (_HL_DIR / "dvol_eth.parquet").exists()
_skip_data = pytest.mark.skipif(not _HAS_DVOL, reason="serve data/raw/dvol_*.parquet (scripts/research/fetch_dvol.py)")


def test_bs_put_monotonic_in_strike():
    """Put piu' ITM (strike piu' alto) vale di piu'."""
    S, T, sig = 100.0, 7 / 365.25, 0.6
    vals = [_bs_put(S, K, T, sig) for K in (80, 90, 100, 110)]
    assert all(b < a for b, a in zip(vals, vals[1:]))           # crescente nello strike


def test_strike_from_delta_ordering():
    """La put venduta delta -0.28 ha strike piu' alto (piu' vicino) della comprata -0.10."""
    S, T, sig = 100.0, 7 / 365.25, 0.6
    Ks = _strike_from_delta(S, T, sig, -0.28)
    Kl = _strike_from_delta(S, T, sig, -0.10)
    assert Kl < Ks < S                                          # entrambe OTM, long piu' lontana


@_skip_data
def test_sleeve_is_deterministic_and_daily():
    a = vrp_sleeve().daily()
    b = _vrp_combo_returns()
    assert isinstance(a.index, pd.DatetimeIndex) and a.index.tz is not None
    assert (a.index.normalize() == a.index).all()               # griglia giornaliera
    # presente ogni giorno nel suo span (nessun buco) -> peso costante nel portafoglio
    full = pd.date_range(a.index.min(), a.index.max(), freq="1D", tz="UTC")
    assert len(a) == len(full)
    np.testing.assert_array_equal(a.values, vrp_sleeve().daily().values)   # deterministico


@_skip_data
def test_gates_reduce_activity():
    """I gate (IV-rank/VRP/crash-skip) devono lasciare flat parte delle settimane: i giorni con
    rendimento != 0 sono molto meno del totale (lump settimanale + settimane saltate)."""
    s = _vrp_combo_returns()
    active = float((s != 0).mean())
    assert 0.0 < active < 0.25                                  # ~1/7 (lump weekly) e meno per i gate


@_skip_data
def test_sleeve_positive_and_capped_tail():
    """Lo sleeve e' profittevole e la coda e' tagliata dal long wing (worst-day moderato)."""
    s = _vrp_combo_returns()
    nz = s[s != 0]
    assert s.sum() > 0                                          # somma rendimenti positiva
    assert nz.min() > -0.15                                     # defined-risk: nessuna settimana < -15%
