#!/usr/bin/env python3
"""
Run full-stack VRP Theta backtest and write a CSV with every **closed** trade including ``legs_json``.

**Default preset:** overlap slice 1, vol scaling off, R2 crossover off, DD risk scaling off (legacy
export for toggle-matrix-style overlap runs).

**``--low-dd-overlap``:** matches ``VRP_FUND_PITCH_INTERNAL_REFERENCE.md`` §13 — vol scaling **off**,
R2 crossover **on**, DD risk scaling **on**, overlap on with ``--overlap-slice-contracts`` (default **1**).

By default uses **all** trading days in the Theta chunks directory ∩ yfinance SPY/VIX panel. For the
short **VRP_TOGGLE_MATRIX** window (2016-01-04 → 2019-01-03), pass ``--start`` / ``--end`` explicitly.
"""
from __future__ import annotations

import argparse
import csv
import sys
from pathlib import Path

_REPO_ROOT = Path(__file__).resolve().parents[2]
if str(_REPO_ROOT) not in sys.path:
    sys.path.insert(0, str(_REPO_ROOT))

import pandas as pd

from RenTech.core.theta_chunks_loader import ThetaChunksLoader, theta_chunks_date_bounds
from RenTech.strategy_stack.vrp_backtester import (
    ClosedTrade,
    VRPBacktester,
    load_spy_vix_from_yfinance,
    normalize_spy_df,
    trading_days_intersecting_spy,
)
from RenTech.strategy_stack.vrp_strategy_config import (
    DEFAULT_STRATEGY_CONFIG_PATH,
    apply_strategy_params_to_vrp_backtester_module,
    load_strategy_config_file,
)

_DEFAULT_OUT = _REPO_ROOT / "RenTech" / "data" / "logs" / "vrp_full_trade_log_with_legs.csv"
_DEFAULT_LOW_DD_OUT = (
    _REPO_ROOT / "RenTech" / "data" / "logs" / "vrp_low_dd_overlap_full_trade_log_with_legs.csv"
)
_THETA_DIR = _REPO_ROOT / "RenTech" / "data" / "theta_chunks"


def _write_csv(path: Path, trades: list[ClosedTrade]) -> None:
    path.parent.mkdir(parents=True, exist_ok=True)
    with path.open("w", newline="", encoding="utf-8") as f:
        w = csv.writer(f)
        w.writerow(
            [
                "entry_date",
                "exit_date",
                "days_in_trade",
                "qty",
                "pnl_usd",
                "exit_reason",
                "initial_net_premium",
                "max_margin",
                "regime",
                "legs_json",
            ]
        )
        for t in trades:
            w.writerow(
                [
                    pd.Timestamp(t.entry_date).strftime("%Y-%m-%d"),
                    pd.Timestamp(t.exit_date).strftime("%Y-%m-%d"),
                    int(t.days_in_trade),
                    int(t.qty),
                    f"{float(t.pnl_usd):.6f}",
                    str(t.exit_reason),
                    f"{float(t.initial_net_premium):.6f}",
                    f"{float(t.max_margin):.6f}",
                    str(t.regime),
                    str(getattr(t, "legs_json", "") or ""),
                ]
            )


def main() -> None:
    ap = argparse.ArgumentParser(description="Export full VRP Theta trade log with leg strikes.")
    ap.add_argument("--theta-dir", type=Path, default=_THETA_DIR)
    ap.add_argument("--capital", type=float, default=100_000.0)
    ap.add_argument(
        "--start",
        type=str,
        default="",
        help="YYYY-MM-DD inclusive floor. Empty = first day in Theta∩SPY intersection.",
    )
    ap.add_argument(
        "--end",
        type=str,
        default="",
        help="YYYY-MM-DD inclusive cap. Empty = last day in Theta∩SPY intersection.",
    )
    ap.add_argument("--out-csv", type=Path, default=None, help="Output CSV path (default: preset-specific).")
    ap.add_argument("--no-progress", action="store_true")
    ap.add_argument(
        "--low-dd-overlap",
        action="store_true",
        help="Pitch-doc low-DD overlap: --no-vol-scaling + --dd-risk-scaling + overlap + R2 crossover ON.",
    )
    ap.add_argument(
        "--overlap-slice-contracts",
        type=int,
        default=1,
        metavar="N",
        help="Contracts per sleeve per day when overlap is on (default: 1).",
    )
    ap.add_argument(
        "--max-days",
        type=int,
        default=0,
        help="If >0, only first N sessions after start/end filter (smoke test). 0 = all in range.",
    )
    args = ap.parse_args()

    out_default = _DEFAULT_LOW_DD_OUT if bool(args.low_dd_overlap) else _DEFAULT_OUT
    out_csv = args.out_csv.expanduser().resolve() if args.out_csv is not None else out_default

    theta_dir = args.theta_dir.expanduser().resolve()
    d0, d1 = theta_chunks_date_bounds(theta_dir)
    yf_start = (d0 - pd.Timedelta(days=400)).strftime("%Y-%m-%d")
    yf_end = (d1 + pd.Timedelta(days=14)).strftime("%Y-%m-%d")
    spy_wide = normalize_spy_df(load_spy_vix_from_yfinance(yf_start, yf_end))
    ld = ThetaChunksLoader(theta_dir, spy_df=spy_wide)
    days = trading_days_intersecting_spy(ld, spy_wide.index, d0, d1)
    if str(args.start).strip():
        t0 = pd.Timestamp(str(args.start).strip())
        days = [d for d in days if d >= t0]
    if str(args.end).strip():
        t1 = pd.Timestamp(str(args.end).strip())
        days = [d for d in days if d <= t1]
    if int(args.max_days) > 0:
        days = days[: int(args.max_days)]

    cfg = load_strategy_config_file(DEFAULT_STRATEGY_CONFIG_PATH)
    apply_strategy_params_to_vrp_backtester_module(cfg.strategy_params)

    if bool(args.low_dd_overlap):
        vol_on = False
        r2_on = True
        dd_on = True
    else:
        vol_on = False
        r2_on = False
        dd_on = False

    bt = VRPBacktester(
        ld,
        initial_capital=float(args.capital),
        spy_df=spy_wide,
        vol_risk_scaling=vol_on,
        r2_crossover_filters=r2_on,
        dd_risk_scaling=dd_on,
        sleeve_risk_fractions=dict(cfg.sleeve_risk_fractions),
        overlap_portfolio=True,
        overlap_slice_contracts=max(1, int(args.overlap_slice_contracts)),
    )
    if not days:
        raise SystemExit("No trading days after Theta∩SPY intersection and optional --start/--end filter.")
    bt.run_backtest(trading_days=days, show_progress=not bool(args.no_progress))
    _write_csv(out_csv, bt.trade_log)
    preset = "low_dd_overlap" if bool(args.low_dd_overlap) else "overlap_gates_off"
    print(
        f"Wrote {len(bt.trade_log)} closed trades to {out_csv} "
        f"(preset={preset}, sessions {pd.Timestamp(days[0]).date()} → {pd.Timestamp(days[-1]).date()}, n={len(days)})"
    )


if __name__ == "__main__":
    main()
