"""
Strategy summaries for the Best Ideas command center UI.

Static copy + optional metrics from ``RenTech/data/logs/*_meta.json``.
"""
from __future__ import annotations

import json
from pathlib import Path
from typing import Any

_REPO = Path(__file__).resolve().parents[2]
LOGS = _REPO / "RenTech" / "data" / "logs"

STRATEGY_DEFINITIONS: dict[str, dict[str, Any]] = {
    "spy_theta": {
        "token": "lit4 + vrp",
        "role": "SPY options (Theta margin + MTM)",
        "summary": (
            "Literature four (S055, S057, S059, S089) plus 4-regime VRP on SPY Theta chains. "
            "One margin simulation: overlapping sleeves, daily MTM on open legs."
        ),
        "rules": [
            "VRP: no PMCC, VIX-scale R2 contracts, term-structure gate, overlap slices=2",
            "Lit sleeves: one position at a time per spec, bid/ask execution",
            "Headline risk: max_drawdown_frac_mtm on combined book",
        ],
        "runner": "python -m RenTech.strategy_stack.diverse_theta_strategies_v1.evaluate_theta_margin",
        "artifacts": [
            "RenTech/data/logs/lit_stack_vrp_margin_daily.csv",
            "RenTech/data/logs/lit_stack_vrp_margin_meta.json",
        ],
        "meta_path": LOGS / "lit_stack_vrp_margin_meta.json",
    },
    "vxx_regime": {
        "token": "vxx_regime_stack",
        "role": "VXX regime stack (6 sleeves)",
        "summary": (
            "Dynamic VXX Regime Strategy Stack: six regime strategies summed on one capital base "
            "(contango, steep contango, backwardation, etc.)."
        ),
        "rules": [
            "Approach B: sum daily_pnl_mtm_usd across sleeves",
            "Preload chains for MTM; combine-only rebuild from sleeve CSVs",
        ],
        "runner": "RenTech/strategy_stack/run_vxx_regime_mtm_report.py",
        "artifacts": [
            "RenTech/data/logs/vxx_regime_mtm_2016_2026_dynamic_vxx_regime_stack_daily_mtm.csv",
            "RenTech/data/logs/vxx_regime_mtm_2016_2026_dynamic_vxx_regime_stack_meta.json",
        ],
        "meta_path": LOGS / "vxx_regime_mtm_2016_2026_dynamic_vxx_regime_stack_meta.json",
    },
    "vxx_long_call": {
        "token": "vxx_long_call",
        "role": "VXX tail hedge",
        "summary": "Long OTM VXX calls sized to ~5% of stacked-book PnL contribution (not full 1% audit sizing).",
        "rules": ["10% OTM calls", "Combined via fund weight × quarterly NAV scale"],
        "runner": "RenTech/strategy_stack/run_vxx_long_call_daily.py",
        "artifacts": ["RenTech/data/logs/vxx_long_call_standard_daily.csv"],
        "meta_path": None,
    },
    "macro_aw": {
        "token": "macro_aw",
        "role": "Macro all-weather options",
        "summary": (
            "Eight ETF option sleeves (TLT, USO, DBC, GLD, …) equal-weight in combine. "
            "Low equity beta complement to SPY theta."
        ),
        "rules": ["Equal-weight portfolio curve", "Theta 15:45 chunks per underlying"],
        "runner": "RenTech/strategy_stack/macro_aw_options_portfolio.py",
        "artifacts": [
            "RenTech/data/logs/macro_aw_options_portfolio_eq_daily.csv",
            "RenTech/data/logs/macro_aw_options_portfolio_eq_trades.csv",
        ],
        "meta_path": LOGS / "macro_aw_options_portfolio_eq_meta.json",
    },
    "sector_momentum": {
        "token": "sector_momentum",
        "role": "SPDR sector rotation",
        "summary": "12−1 month momentum on SPDR sectors; hold top-3 names, monthly rebalance.",
        "rules": ["Rank by trailing momentum", "Long sector ETFs, no short"],
        "runner": "RenTech/strategy_stack/run_sector_momentum_standard.py",
        "artifacts": [
            "RenTech/data/logs/sector_momentum_standard_daily.csv",
            "RenTech/data/logs/sector_momentum_standard_rebalances.csv",
        ],
        "meta_path": LOGS / "sector_momentum_standard_meta.json",
    },
    "tactical_aw": {
        "token": "tactical_aw",
        "role": "Tactical all-weather (macro ETFs)",
        "summary": (
            "Bridgewater-style static weights on SPY/TLT/IEF/GLD/DBC with per-sleeve trend + momentum gates. "
            "Production variant: TLT/IEF baseline ×0.7 (bond70 sweep winner)."
        ),
        "rules": [
            "Invest baseline weight when close > SMA(200) and 12−1 momentum > 0",
            "Else cash at ~4% annual yield; weights execute next day",
            "bond_baseline_mult=0.7 on TLT and IEF",
        ],
        "runner": "RenTech/strategy_stack/run_tactical_all_weather_standard.py",
        "artifacts": [
            "RenTech/data/logs/tactical_aw_standard_daily.csv",
            "RenTech/data/logs/tactical_aw_standard_allocations.csv",
            "RenTech/data/logs/tactical_aw_variant_sweep_best.json",
        ],
        "meta_path": LOGS / "tactical_aw_standard_meta.json",
        "config_path": LOGS / "tactical_aw_variant_sweep_best.json",
    },
    "tsmom": {
        "token": "tsmom",
        "role": "Managed futures / TSMOM",
        "summary": (
            "8-asset time-series momentum (SPY, EFA, EEM, TLT, IEF, GLD, DBC, UUP). "
            "3/6/12m signal blend, vol-normalized, monthly rebalance. Low SPY beta."
        ),
        "rules": ["Long/short by trend sign", "Vol targeting per asset"],
        "runner": "RenTech/strategy_stack/run_tsmom_managed_futures.py",
        "artifacts": ["RenTech/data/logs/tsmom_managed_futures_daily.csv"],
        "meta_path": LOGS / "tsmom_managed_futures_meta.json",
    },
}


def _read_json(path: Path | None) -> dict[str, Any] | None:
    if path is None or not path.is_file():
        return None
    try:
        raw = json.loads(path.read_text(encoding="utf-8"))
        return raw if isinstance(raw, dict) else None
    except json.JSONDecodeError:
        return None


def _normalize_standalone_meta(meta: dict[str, Any] | None) -> dict[str, Any] | None:
    if not meta:
        return None
    out: dict[str, Any] = {}
    tr = meta.get("total_return_pct")
    if tr is not None:
        out["total_return_pct"] = float(tr)
    cagr = meta.get("cagr_pct")
    if cagr is not None:
        out["cagr_pct"] = float(cagr)
    sh = meta.get("sharpe") or meta.get("portfolio_sharpe_daily_mtm")
    if sh is not None:
        out["sharpe"] = float(sh)
    dd = meta.get("max_drawdown_pct")
    if dd is None and meta.get("max_drawdown_frac_mtm") is not None:
        dd = float(meta["max_drawdown_frac_mtm"]) * 100.0
    if dd is not None:
        out["max_drawdown_pct"] = float(dd)
    if meta.get("start") or meta.get("first_day"):
        out["start"] = str(meta.get("start") or meta.get("first_day"))
    if meta.get("end") or meta.get("last_day"):
        out["end"] = str(meta.get("end") or meta.get("last_day"))
    return out or None


def build_strategy_summaries(
    portfolio: dict[str, Any],
    combine_meta: dict[str, Any] | None = None,
) -> dict[str, Any]:
    """
    Build ordered strategy cards for the command center.

    Merges static definitions, standalone backtest meta, and in-fund attribution.
    """
    combine_meta = combine_meta or {}
    fund_weights = portfolio.get("fund_weights") or {}
    sleeves = portfolio.get("sleeves") or {}
    yearly = portfolio.get("yearly") or []

    book_blurb = (
        "Fund-mode 2.2× gross, quarterly NAV-sized sleeves. "
        "Daily sleeve PnL scales from $100k standalone backtests: "
        "notional = weight × fund_scale × quarter-open NAV."
    )
    if combine_meta.get("combine_mode"):
        book_blurb = (
            f"{combine_meta.get('combine_mode')} · "
            f"fund_scale={combine_meta.get('fund_scale', '2.2')} · "
            f"nav_rebalance={combine_meta.get('fund_nav_rebalance', 'quarterly')}. "
            + book_blurb
        )

    strategies: list[dict[str, Any]] = []
    keys = sorted(
        fund_weights.keys(),
        key=lambda k: float(fund_weights.get(k, 0)),
        reverse=True,
    )
    for key in keys:
        defn = STRATEGY_DEFINITIONS.get(key, {})
        sl = sleeves.get(key, {})
        meta = _normalize_standalone_meta(_read_json(defn.get("meta_path")))
        cfg_raw = _read_json(defn.get("config_path"))
        config = (cfg_raw or {}).get("config") if cfg_raw else None
        if config is None and cfg_raw and "bond_baseline_mult" in str(cfg_raw):
            config = cfg_raw.get("config", cfg_raw)

        strategies.append(
            {
                "id": key,
                "label": sl.get("label") or defn.get("label", key),
                "token": defn.get("token", key),
                "role": defn.get("role", ""),
                "summary": defn.get("summary", ""),
                "rules": list(defn.get("rules") or []),
                "runner": defn.get("runner", ""),
                "artifacts": list(defn.get("artifacts") or []),
                "weight": float(fund_weights[key]),
                "weight_pct": float(fund_weights[key]) * 100.0,
                "config": config,
                "variant_name": (cfg_raw or {}).get("best_variant") if cfg_raw else None,
                "standalone": meta,
                "in_fund": {
                    "notional_usd": sl.get("notional_usd"),
                    "mean_notional_usd": sl.get("mean_notional_usd"),
                    "total_pnl_usd": sl.get("total_pnl_usd"),
                    "return_on_start_capital_pct": sl.get("return_on_start_capital_pct"),
                    "pct_of_fund_pnl": sl.get("pct_of_fund_pnl"),
                    "pnl_today_usd": sl.get("pnl_today_usd"),
                },
            }
        )

    return {
        "book_title": "Best Ideas — 7-sleeve fund (reference backtest)",
        "book_blurb": book_blurb,
        "window": {
            "start": portfolio.get("start_date"),
            "end": portfolio.get("end_date"),
            "as_of": portfolio.get("date"),
        },
        "headline": {
            "total_return_pct": portfolio.get("total_return_pct"),
            "cagr_pct": portfolio.get("cagr_pct"),
            "sharpe": portfolio.get("sharpe"),
            "max_drawdown_pct": portfolio.get("max_drawdown_pct"),
            "fund_nav_usd": portfolio.get("fund_nav_usd"),
            "capital_usd": portfolio.get("capital_usd"),
        },
        "yearly": yearly,
        "strategies": strategies,
        "regenerate_combine": (
            "cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 .venv/bin/python "
            "RenTech/strategy_stack/combine_best_ideas_stack.py "
            "--start 2016-01-04 --end 2026-04-02 --capital 100000 "
            "--mtm --fund-mode --fund-scale 2.2 "
            "--with-vxx-long-call --with-macro-aw --with-sector-momentum "
            "--with-tactical-aw --with-tsmom "
            "--lit-mtm-daily RenTech/data/logs/lit_stack_vrp_margin_daily.csv "
            "--out-prefix RenTech/data/logs/best_ideas_stack_10dd"
        ),
        "regenerate_snapshot": (
            "cd /Users/robzingale/trading_bot && PYTHONUNBUFFERED=1 "
            ".venv/bin/python -m RenTech.monitor.build_command_center_snapshot --ibkr"
        ),
    }
