# tests/test_feature_block_skew_smile.py

import polars as pl

from ocf.data.normalize import (
    normalize_ohlcv,
    normalize_ivol_30,
    normalize_ivol_60,
)
from ocf.features.skew_smile import build_skew_smile_features


def test_skew_smile_feature_block_from_raw():
    """
    Test skew & smile features using real Bloomberg-style IV surfaces.

    Verifies:
    - normalization works
    - skew/smile feature builder runs in isolation
    - expected skew/smile feature columns exist
    - row-wise smile logic does not crash
    - base columns are preserved

    Does NOT validate numerical correctness.
    """

    raw_dir = "data/raw/bloomberg/spy"
    symbol = "SPY"

    # ------------------------------------------------------------------
    # Load + normalize required inputs
    # ------------------------------------------------------------------
    ohlcv = normalize_ohlcv(
        pl.read_csv(f"{raw_dir}/ohlcv.csv"),
        symbol,
    )

    iv30 = normalize_ivol_30(
        pl.read_csv(f"{raw_dir}/ivol_30_mny.csv"),
        symbol,
    )

    iv60 = normalize_ivol_60(
        pl.read_csv(f"{raw_dir}/ivol_60_mny.csv"),
        symbol,
    )

    # ------------------------------------------------------------------
    # Minimal canonical_underlying_daily
    # (join OHLCV + IV surfaces)
    # ------------------------------------------------------------------
    underlying_daily = (
        ohlcv
        .join(iv30, on=["symbol", "date"], how="left")
        .join(iv60, on=["symbol", "date"], how="left")
    )

    assert not underlying_daily.is_empty()

    base_cols = set(underlying_daily.columns)

    # ------------------------------------------------------------------
    # Build skew / smile features
    # ------------------------------------------------------------------
    featured = build_skew_smile_features(
        underlying_daily
    )

    # ------------------------------------------------------------------
    # Assertions
    # ------------------------------------------------------------------
    assert not featured.is_empty()

    # Base columns must be preserved
    assert base_cols.issubset(set(featured.columns))

    # Expected skew / smile feature columns (subset)
    expected_features = {
        # ATM IV
        "iv_30_atm",
        "iv_60_atm",

        # skew
        "iv_30_put_skew",
        "iv_30_call_skew",
        "iv_60_put_skew",
        "iv_60_call_skew",

        # risk reversal & butterfly
        "iv_30_rr",
        "iv_30_bf",
        "iv_60_rr",
        "iv_60_bf",

        # smile geometry
        "iv_30_smile_slope",
        "iv_30_smile_curvature",
        "iv_60_smile_slope",
        "iv_60_smile_curvature",
    }

    assert expected_features.issubset(set(featured.columns))

    # Sanity: at least some rows should have smile info
    non_null_rows = featured.select(
        pl.any_horizontal(
            [pl.col(c).is_not_null() for c in expected_features]
        )
    ).sum().item()

    assert non_null_rows > 0