"""PM2 重启当前实例(仅 Linux 部署环境)."""
from __future__ import annotations

import os
import shlex
import subprocess
import sys
from typing import Any


def default_pm2_app_name(exchange_key: str) -> str:
    mapping = {
        "okx": "crypto_okx",
        "binance": "crypto_binance",
        "gate": "crypto_gate",
    }
    return mapping.get((exchange_key or "").strip().lower(), "crypto_okx")


def resolve_pm2_app_name(exchange_key: str) -> str:
    explicit = (os.getenv("PM2_APP_NAME") or "").strip()
    if explicit:
        return explicit
    return default_pm2_app_name(exchange_key)


def schedule_pm2_restart(app_name: str, *, delay_seconds: float = 1.0) -> dict[str, Any]:
    """延迟触发 PM2 重启,便于 HTTP 响应先返回(避免重启当前进程导致请求中断)."""
    if not sys.platform.startswith("linux"):
        return {"ok": False, "msg": "仅 Linux 服务器支持 PM2 重启", "app": app_name}
    if not (app_name or "").strip():
        return {"ok": False, "msg": "未指定 PM2 应用名", "app": app_name}
    app_name = app_name.strip()
    try:
        cmd = f"sleep {delay_seconds} && exec pm2 restart {shlex.quote(app_name)} --update-env"
        subprocess.Popen(
            ["bash", "-c", cmd],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL,
            start_new_session=True,
        )
        return {"ok": True, "app": app_name, "msg": "重启已触发", "deferred": True}
    except FileNotFoundError:
        return {"ok": False, "msg": "未找到 bash 或 pm2 命令", "app": app_name}
    except Exception as e:
        return {"ok": False, "msg": str(e), "app": app_name}


def restart_instance_pm2(exchange_key: str, *, defer: bool = False) -> dict[str, Any]:
    if not sys.platform.startswith("linux"):
        return {"ok": False, "msg": "仅 Linux 服务器支持 PM2 重启", "app": None}
    app_name = resolve_pm2_app_name(exchange_key)
    if defer:
        return schedule_pm2_restart(app_name)
    try:
        proc = subprocess.run(
            ["pm2", "restart", app_name, "--update-env"],
            capture_output=True,
            text=True,
            timeout=120,
        )
        ok = proc.returncode == 0
        return {
            "ok": ok,
            "app": app_name,
            "msg": (proc.stdout or proc.stderr or "").strip()[:500],
            "returncode": proc.returncode,
        }
    except FileNotFoundError:
        return {"ok": False, "msg": "未找到 pm2 命令", "app": app_name}
    except subprocess.TimeoutExpired:
        return {"ok": False, "msg": "pm2 restart 超时", "app": app_name}
    except Exception as e:
        return {"ok": False, "msg": str(e), "app": app_name}
