"""启动本地服务器展示 SPX complacency K 线。

用法: python -m sentiment_indicator.web.serve [--port 8080]

自动刷新: 每次 HTTP 请求 /complacency.html 或 /complacency_data.json 时,
检查 CSV/parquet 源 (complacency_score.csv, trade_actions.csv, SPX.parquet)
的 mtime, 若任一源比已生成的 JSON 新就自动 regen JSON, 浏览器刷新页面即可
看到最新数据, 无需重启 server.
"""

import argparse
import http.server
import os
from pathlib import Path

from .generate_complacency_data import (
    main as gen,
    OUTPUT as DATA_JSON_PATH,
    SPX_PATH,
    SCORE_PATH,
    ACTIONS_PATH,
)
from .generate_backtest_data import (
    main as gen_backtest,
    OUTPUT as BACKTEST_JSON_PATH,
)
from .generate_trade_actions_data import (
    main as gen_actions,
    OUTPUT as ACTIONS_JSON_PATH,
)


SOURCE_PATHS = [SPX_PATH, SCORE_PATH, ACTIONS_PATH]
# 只有这些 path 的 GET 才触发 mtime 检查 (避免每个静态资源都查)
REFRESH_TRIGGER_PATHS = {"/complacency_data.json", "/complacency.html", "/"}
BACKTEST_TRIGGER_PATHS = {"/backtest_data.json", "/backtest.html"}
ACTIONS_TRIGGER_PATHS = {"/trade_actions_data.json", "/trade_actions.html"}


def _maybe_regenerate() -> None:
    """若任一源文件比 JSON 新 (或 JSON 不存在), 重新生成 JSON."""
    if not DATA_JSON_PATH.exists():
        print("[auto-refresh] data JSON missing, generating ...")
        gen()
        return
    json_mtime = DATA_JSON_PATH.stat().st_mtime
    stale_sources = [
        src.name for src in SOURCE_PATHS
        if src.exists() and src.stat().st_mtime > json_mtime
    ]
    if stale_sources:
        print(f"[auto-refresh] stale sources: {', '.join(stale_sources)}, regenerating ...")
        gen()


def _maybe_regenerate_backtest() -> None:
    """若 trade_actions.csv 比 backtest_data.json 新, 重新生成 backtest JSON."""
    if not BACKTEST_JSON_PATH.exists():
        print("[auto-refresh] backtest JSON missing, generating ...")
        gen_backtest()
        return
    json_mtime = BACKTEST_JSON_PATH.stat().st_mtime
    if ACTIONS_PATH.exists() and ACTIONS_PATH.stat().st_mtime > json_mtime:
        print("[auto-refresh] trade_actions.csv newer than backtest JSON, regenerating ...")
        gen_backtest()


def _maybe_regenerate_actions() -> None:
    """若 trade_actions.csv 比 trade_actions_data.json 新, 重新生成 actions JSON."""
    if not ACTIONS_JSON_PATH.exists():
        print("[auto-refresh] actions JSON missing, generating ...")
        gen_actions()
        return
    json_mtime = ACTIONS_JSON_PATH.stat().st_mtime
    if ACTIONS_PATH.exists() and ACTIONS_PATH.stat().st_mtime > json_mtime:
        print("[auto-refresh] trade_actions.csv newer than actions JSON, regenerating ...")
        gen_actions()


class RefreshingHandler(http.server.SimpleHTTPRequestHandler):
    def do_GET(self):  # noqa: N802 (stdlib API name)
        # 去掉 query string 再比对 (浏览器会加 ?t=timestamp 做 cache-busting)
        path = self.path.split("?", 1)[0]
        if path in REFRESH_TRIGGER_PATHS:
            _maybe_regenerate()
        elif path in BACKTEST_TRIGGER_PATHS:
            _maybe_regenerate_backtest()
        elif path in ACTIONS_TRIGGER_PATHS:
            _maybe_regenerate_actions()
        super().do_GET()


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--port", type=int, default=8080)
    parser.add_argument("--no-generate", action="store_true",
                        help="Skip data generation at startup (auto-refresh 仍生效)")
    args = parser.parse_args()

    web_dir = Path(__file__).resolve().parent
    page_file = "complacency.html"

    if not args.no_generate or not DATA_JSON_PATH.exists():
        print("Generating chart data ...")
        gen()
    if not args.no_generate or not BACKTEST_JSON_PATH.exists():
        print("Generating backtest data ...")
        gen_backtest()
    if not args.no_generate or not ACTIONS_JSON_PATH.exists():
        print("Generating trade actions data ...")
        gen_actions()

    os.chdir(web_dir)
    server = http.server.HTTPServer(("0.0.0.0", args.port), RefreshingHandler)
    print(f"\n🌐 Dashboard: http://localhost:{args.port}/{page_file}")
    print("   自动刷新: 源 CSV/parquet 更新后浏览器刷新页面即生效")
    print("   Press Ctrl+C to stop\n")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\nServer stopped.")


if __name__ == "__main__":
    main()
