# -*- coding: utf-8 -*-
"""Project-level extended CLI commands."""

from __future__ import annotations

import argparse
import shutil
import sys
from pathlib import Path
from typing import Any, Dict, List

from services.commands import (
    check_node_status,
    check_nodes_status,
    DEFAULT_CONFIG_FILE,
    generate_start_config,
    get_erl_cmd,
    get_local_ip,
    get_rebar3_cmd,
    run_startup_migrations,
)
from services.hot_update import get_version_info
from services.rg_search import find_rg_executable
from services.server_creator import (
    generate_server_dir_name,
    get_default_port,
    get_existing_server_ids,
    get_server_type_name,
)

from .common import all_servers, emit_json, is_json_output, mask_config, print_kv


def handle_info(args: argparse.Namespace, cli: Any) -> None:
    config = mask_config(cli.config, include_sensitive=args.include_sensitive)
    data = {
        "version": get_version_info().get("version"),
        "python": sys.version.split()[0],
        "platform": sys.platform,
        "server_root": cli.server_root,
        "run_dir": cli.run_dir,
        "config_dir": str(cli.config_path),
        "local_ip": get_local_ip(),
        "server_count": len(all_servers(cli)),
        "tools": {
            "erl": get_erl_cmd(cli.config.get("erl_path")),
            "rebar3": get_rebar3_cmd(cli.server_root, cli.config.get("erl_path")),
            "rg": str(find_rg_executable() or ""),
        },
        "config": config,
    }
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== 项目信息 ==========")
    for key in ("version", "python", "platform", "server_root", "run_dir", "config_dir", "local_ip", "server_count"):
        print(f"{key}: {data[key]}")
    print("\n工具:")
    print_kv(data["tools"])
    print("================================\n")


def handle_status(args: argparse.Namespace, cli: Any) -> None:
    servers = args.servers or all_servers(cli)
    if args.strict:
        status = {
            server: check_node_status(server, cli.cookie, target_ip=args.ip, erl_path=cli.config.get("erl_path"))
            for server in servers
        }
    else:
        status = check_nodes_status(servers, cli.cookie, target_ip=args.ip, erl_path=cli.config.get("erl_path"))
    data = {
        "server_root": cli.server_root,
        "run_dir": cli.run_dir,
        "target_ip": args.ip,
        "strict": bool(args.strict),
        "status": status,
    }
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== 节点状态 ==========")
    if not servers:
        print("(暂无服务器)")
    for server in servers:
        mark = "online" if status.get(server) else "offline"
        print(f"{server:<40} {mark}")
    print("================================\n")


def handle_ids(args: argparse.Namespace, cli: Any) -> None:
    prefix = args.prefix or getattr(cli, "prefix", "ddxq2")
    existing = sorted(get_existing_server_ids(cli.run_dir, args.type, prefix))
    next_id = 1
    while next_id in existing:
        next_id += 1
    default_tcp, default_http = get_default_port(args.type, next_id)
    data = {
        "type": args.type,
        "type_name": get_server_type_name(args.type),
        "prefix": prefix,
        "existing_ids": existing,
        "next_id": next_id,
        "next_dir": generate_server_dir_name(prefix, args.type, next_id),
        "default_tcp_port": default_tcp,
        "default_http_port": default_http,
    }
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== 服务器 ID ==========")
    print(f"类型: {data['type_name']} ({args.type})")
    print(f"前缀: {prefix}")
    print(f"已有 ID: {', '.join(map(str, existing)) if existing else '(无)'}")
    print(f"下一个可用 ID: {next_id}")
    print(f"目录名: {data['next_dir']}")
    print(f"默认端口: tcp={default_tcp}, http={default_http}")
    print("================================\n")


def handle_doctor(args: argparse.Namespace, cli: Any) -> None:
    config_dir = Path(cli.config_path)
    checks = [
        _check("server_root", Path(cli.server_root).is_dir(), cli.server_root),
        _check("run_dir", Path(cli.run_dir).is_dir(), cli.run_dir),
        _check("config_dir", config_dir.is_dir(), str(config_dir)),
        _check("default_config", (config_dir / DEFAULT_CONFIG_FILE).is_file(), str(config_dir / DEFAULT_CONFIG_FILE)),
        _check("erl", _tool_exists(get_erl_cmd(cli.config.get("erl_path"))), get_erl_cmd(cli.config.get("erl_path"))),
        _check("rg", find_rg_executable() is not None, str(find_rg_executable() or "")),
    ]
    rebar_cmd = get_rebar3_cmd(cli.server_root, cli.config.get("erl_path"))
    rebar_ok = (Path(cli.server_root) / "rebar3").exists() or shutil.which("rebar3") is not None or "escript" in rebar_cmd
    checks.append(_check("rebar3", rebar_ok, rebar_cmd))
    data = {"ok": all(item["ok"] for item in checks), "checks": checks}
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== Doctor ==========")
    for item in checks:
        print(f"{'OK' if item['ok'] else 'FAIL':<5} {item['name']:<12} {item['detail']}")
    print(f"\n结果: {'通过' if data['ok'] else '存在问题'}")
    print("============================\n")


def handle_migrate(args: argparse.Namespace, cli: Any) -> None:
    messages: List[str] = []
    result = run_startup_migrations(cli.server_root, logger_func=messages.append)
    data = {"server_root": cli.server_root, "result": result, "messages": messages}
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== 配置迁移 ==========")
    for message in messages:
        print(message, end="" if message.endswith("\n") else "\n")
    print("完成")
    print("================================\n")


def handle_regen_all(args: argparse.Namespace, cli: Any) -> None:
    servers = all_servers(cli)
    results = []
    for server in servers:
        merged = generate_start_config(cli.server_root, server)
        results.append({
            "server": server,
            "success": bool(merged),
            "config_file": (merged or {}).get("_config_file", ""),
        })
    data = {
        "total": len(results),
        "success": sum(1 for item in results if item["success"]),
        "failed": sum(1 for item in results if not item["success"]),
        "results": results,
    }
    if is_json_output(args):
        emit_json(data)
        return
    print("\n========== 重新生成全部 sys.config ==========")
    for item in results:
        mark = "✓" if item["success"] else "✗"
        print(f"{mark} {item['server']} {item['config_file']}")
    print(f"\n成功 {data['success']} / 总计 {data['total']}")
    print("============================================\n")


def _check(name: str, ok: bool, detail: str) -> Dict[str, Any]:
    return {"name": name, "ok": bool(ok), "detail": detail}


def _tool_exists(command: str) -> bool:
    if not command:
        return False
    if command in {"erl", "escript", "rebar3", "rebar3.cmd"}:
        return shutil.which(command) is not None
    return Path(command.strip('"')).exists()
