"""Valida il CrossSectionalWorker: replay bar-per-bar == backtest XS01.xsec_sim?

Come validate_worker_pairs: alimenta il worker con finestre trailing crescenti del
pannello 8-asset e confronta capitale finale e n.trade col backtest di riferimento
scripts.strategies.XS01_cross_sectional.xsec_sim. Se combaciano, la semantica live e' fedele.
"""
from __future__ import annotations

import shutil
import sys
import tempfile
from pathlib import Path

import pandas as pd

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

from src.live.xsec_worker import CrossSectionalWorker
from scripts.strategies.XS01_cross_sectional import aligned_panel, xsec_sim, UNIVERSE, LB, HOLD


def _replay(M, dfs, params):
    """Alimenta il worker bar-per-bar su finestre trailing; ritorna il worker."""
    n = len(M)
    tmp = Path(tempfile.mkdtemp(prefix="xsec_val_"))
    try:
        w = CrossSectionalWorker(UNIVERSE, tf="1h", params=params,
                                 fee_rt=0.0005, data_dir=tmp)
        w._save = lambda: None; w._log = lambda *a, **k: None; w._notify = lambda *a, **k: None
        window = LB + 6
        for k in range(LB + 1, n + 1):           # prima finestra = lb+1 barre -> ingresso al bar lb
            lo = max(0, k - window)
            w.tick({a: dfs[a].iloc[lo:k] for a in UNIVERSE})
        return w
    finally:
        shutil.rmtree(tmp, ignore_errors=True)


def main():
    print("=" * 88)
    print("  VALIDAZIONE CrossSectionalWorker — replay live vs backtest xsec_sim (fee 0.10% RT/book)")
    print("=" * 88)
    M = aligned_panel(UNIVERSE)
    dfs = {a: pd.DataFrame({"timestamp": M.index.values, "close": M[a].values}) for a in UNIVERSE}

    # [1] K=1: parita' storica col backtest canonico
    w = _replay(M, dfs, {"lb": LB, "hold": HOLD})
    bt = xsec_sim(UNIVERSE)
    bt_cap = 1000.0 * (1 + bt["ret"] / 100)
    cap_ok = abs(w.capital - bt_cap) / bt_cap < 0.02 if bt_cap else False
    trd_ok = abs(w.total_trades - bt["trades"]) <= max(2, bt["trades"] * 0.02)
    ww = w.total_wins / w.total_trades * 100 if w.total_trades else 0
    print(f"\n  [K=1] {'':<6}{'cap':>14}{'trades':>8}{'win%':>7}")
    print(f"  WORKER{w.capital:>14.0f}{w.total_trades:>8d}{ww:>7.1f}")
    print(f"  BCKTST{bt_cap:>14.0f}{bt['trades']:>8d}{bt['win']:>7.1f}")
    ok1 = cap_ok and trd_ok
    print(f"  ESITO: {'OK (replay == backtest)' if ok1 else 'DIFF -> INDAGARE'}")

    # [2] K=3 (tranching live): parita' con l'unione delle fasi 0,4,8 (gate
    # xs01_tranche_gate) — capitale comune, PnL/K per trade in ordine di exit.
    # POS/LEV importati dal modulo canonico, NON hardcoded: una costante stantia
    # qui farebbe passare la validazione contro un sistema diverso (code-review)
    from scripts.analysis.xs01_tranche_research import xsec_trades
    from scripts.strategies.XS01_cross_sectional import POS, LEV
    K = 3
    w3 = _replay(M, dfs, {"lb": LB, "hold": HOLD, "tranches": K})
    step = HOLD // K
    allt = sorted([t for j in range(K) for t in xsec_trades(phase=j * step, M=M)],
                  key=lambda t: t[1])
    cap = 1000.0
    for _, _, net in allt:
        cap = max(cap + cap * POS * LEV * net / K, 10.0)
    cap_ok3 = abs(w3.capital - cap) / cap < 0.02
    trd_ok3 = abs(w3.total_trades - len(allt)) <= max(2, len(allt) * 0.02)
    print(f"\n  [K=3] {'':<6}{'cap':>14}{'trades':>8}")
    print(f"  WORKER{w3.capital:>14.0f}{w3.total_trades:>8d}")
    print(f"  BCKTST{cap:>14.0f}{len(allt):>8d}")
    ok3 = cap_ok3 and trd_ok3
    print(f"  ESITO: {'OK (replay == unione fasi)' if ok3 else 'DIFF -> INDAGARE'}")
    print(f"\n  ESITO COMPLESSIVO: {'OK' if (ok1 and ok3) else 'DIFF -> INDAGARE'}")
    print("  (diff minime attese da bar finale aperta / troncamento)")


if __name__ == "__main__":
    main()
