#!/usr/bin/env python3
"""
Weekend Full Backtest - 周末执行全量离线训练并输出结果摘要。
"""

from __future__ import annotations

import json
import subprocess
import sys
from datetime import datetime
from pathlib import Path

# ROOT now resolved via frozen_path (PyInstaller-safe)
from frozen_path import APP_ROOT as ROOT
# LOG_DIR now resolved via frozen_path
from frozen_path import LOGS_DIR as LOG_DIR
OFFLINE_TRAIN = ROOT / "src" / "offline_train.py"
RESULT_FILE = LOG_DIR / f"weekend_backtest_{datetime.now().strftime('%Y%m%d')}.json"
OFFLINE_OUTPUT_DIR = LOG_DIR / "offline"


def log(msg: str) -> None:
    print(f"[{datetime.now().strftime('%H:%M:%S')}] {msg}")


def check_already_run() -> bool:
    if not RESULT_FILE.exists():
        return False
    try:
        data = json.loads(RESULT_FILE.read_text(encoding="utf-8"))
    except Exception:
        return False
    return bool(data.get("completed"))


def write_progress(step: str, detail: str = "") -> None:
    payload = {
        "started": datetime.now().isoformat(),
        "step": step,
        "detail": detail,
        "completed": False,
    }
    RESULT_FILE.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")


def run_full_backtest() -> dict[str, object]:
    LOG_DIR.mkdir(exist_ok=True)
    OFFLINE_OUTPUT_DIR.mkdir(exist_ok=True)
    write_progress("running", "执行 30 天 5m 离线训练")

    cmd = [
        sys.executable,
        str(OFFLINE_TRAIN),
        "--days",
        "30",
        "--interval",
        "5m",
        "--mode",
        "train",
    ]
    log(f"执行: {' '.join(cmd)}")

    weekend_log = LOG_DIR / "weekend_backtest.log"
    with weekend_log.open("a", encoding="utf-8") as handle:
        proc = subprocess.run(
            cmd,
            cwd=str(ROOT),
            stdout=handle,
            stderr=subprocess.STDOUT,
            check=False,
        )

    stats_file = ROOT / "data" / "offline" / "offline_stats.json"
    if proc.returncode != 0:
        payload = {
            "started": datetime.now().isoformat(),
            "completed": False,
            "return_code": proc.returncode,
            "report_file": str(weekend_log),
        }
        RESULT_FILE.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
        return payload

    if not stats_file.exists():
        payload = {
            "started": datetime.now().isoformat(),
            "completed": False,
            "return_code": proc.returncode,
            "detail": "offline_stats.json 未生成",
            "report_file": str(weekend_log),
        }
        RESULT_FILE.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
        return payload

    stats = json.loads(stats_file.read_text(encoding="utf-8"))
    best_params = stats.get("best_params", {}) if isinstance(stats.get("best_params"), dict) else {}
    payload = {
        "started": datetime.now().isoformat(),
        "completed": True,
        "best_params": best_params,
        "total_trades": stats.get("total_trades", 0),
        "win_rate": stats.get("win_rate", 0),
        "total_pnl": stats.get("total_pnl", 0),
        "score": stats.get("score", 0),
        "return_pct": stats.get("return_pct", 0),
        "report_file": str(stats_file),
        "log_file": str(weekend_log),
    }
    RESULT_FILE.write_text(json.dumps(payload, indent=2, ensure_ascii=False), encoding="utf-8")
    return payload


def format_report(result: dict[str, object]) -> str:
    params = result.get("best_params", {}) if isinstance(result.get("best_params"), dict) else {}
    return f"""[Weekend Backtest] {datetime.now().strftime('%Y-%m-%d')}

Trades: {int(result.get('total_trades', 0) or 0)}
Win Rate: {float(result.get('win_rate', 0) or 0):.2f}%
PnL: ${float(result.get('total_pnl', 0) or 0):+.2f}
Score: {float(result.get('score', 0) or 0):.2f}
EMA: {params.get('ema_short', '?')}/{params.get('ema_long', '?')}
SL/TP: {params.get('sl_atr', '?')} / {params.get('tp_atr', '?')} ATR
Report: {result.get('report_file', '')}
"""


if __name__ == "__main__":
    if check_already_run():
        log("周末回测今日已完成，跳过")
        raise SystemExit(0)

    result = run_full_backtest()
    print(format_report(result))
