# -*- coding: utf-8 -*-
"""Server start/stop/remsh command builders."""

from .shared import *
from .config_files import read_config_file
from .erlang import get_ebin_paths, get_erl_cmd, get_local_ip, get_rebar3_cmd
from .node_status import _check_nodes_status_via_ping

def get_rebar_profile(server_type: str) -> tuple:
    """根据服务器类型获取 rebar3 profile 和 app 名称
    
    Args:
        server_type: 服务器类型 (game_server/login_server/center_server/cross_server/client_server)
    
    Returns:
        (profile, app_name) 元组
    """
    if server_type == 'login_server':
        return ('login_server_dev', 'login_server')
    elif server_type == 'client_server':
        return ('client_server_dev', 'client_server')
    else:
        # 游戏服、中心服、跨服都使用 game_server_dev
        return ('game_server_dev', 'game_server')


def _build_rebar_eval_expr(app_name: str) -> str:
    # Keep the leading dummy expression; rebar3/getopt can split --eval values on commas.
    return f'-1,application:ensure_all_started({app_name}).'


def build_start_command_by_config(server_root: str, merged_config: Dict[str, str], 
                                   cookie: str, use_rebar: bool = True,
                                   erl_path: str = None) -> str:
    """根据配置构建启动服务器的命令
    
    关键设计：
    - 命令在 server_root 目录下运行（这样可以找到 rebar.config、_build）
    - 不再通过 file:set_cwd 改变工作目录（避免影响 Erlang shell 的 c() 命令）
      sys.config 生成时已把日志路径拼上 run/<服务器名称>/，日志会落到正确位置
    
    Args:
        server_root: 服务器根目录
        merged_config: 合并后的配置字典
        cookie: Erlang cookie
        use_rebar: 是否使用 rebar3 启动（True=标准启动，False=快速启动）
        erl_path: Erlang 安装路径
    
    Returns:
        启动命令字符串
    """
    server_dir = merged_config.get('_server_dir', '')
    config_file = merged_config.get('_config_file', '')
    game_host = merged_config.get('game_host', get_local_ip())
    node_name = merged_config.get('node_name', f'{server_dir}@{game_host}')
    server_type = merged_config.get('server_type', 'game_server').strip('"').strip("'")
    
    # 移除 node_name 中的引号
    node_name = node_name.replace('"', '').replace("'", '')
    
    # 根据服务器类型获取 profile
    profile, app_name = get_rebar_profile(server_type)
    
    if use_rebar:
        rebar3 = get_rebar3_cmd(server_root, erl_path)
        eval_expr = _build_rebar_eval_expr(app_name)
        cmd = (
            f'{rebar3} as {profile} shell '
            f'--eval "{eval_expr}" '
            f'--setcookie {cookie} '
            f'--name {node_name} '
            f'--config "{config_file}"'
        )
    else:
        erl = get_erl_cmd(erl_path)
        ebin_paths = get_ebin_paths(server_root, profile)
        pa_args = " ".join([f'-pa "{p}"' for p in ebin_paths])
        
        eval_str = f'application:ensure_all_started({app_name}).'
        
        cmd = (
            f'"{erl}" {pa_args} '
            f'-smp enable '
            f'-setcookie {cookie} '
            f'-name {node_name} '
            f'-config "{config_file}" '
            f'-eval "{eval_str}"'
        )
    
    return cmd


def build_start_command(server_root: str, server_name: str, cookie: str, 
                        use_rebar: bool = True, erl_path: str = None) -> str:
    """构建启动服务器的命令（兼容旧接口，使用服务器目录名）
    
    关键设计：
    - 命令在 server_root 目录下运行（这样可以找到 rebar.config、_build）
    - 不再通过 file:set_cwd 改变工作目录（避免影响 Erlang shell 的 c() 命令）
      sys.config 生成时已把日志路径拼上 run/<服务器名称>/，日志会落到正确位置
    
    Args:
        server_root: 服务器根目录
        server_name: 服务器目录名（如 ddxq_game_s1）
        cookie: Erlang cookie
        use_rebar: 是否使用 rebar3 启动
    
    Returns:
        启动命令字符串
    """
    ip = get_local_ip()
    run_dir = Path(server_root) / "run" / server_name
    config_file = run_dir / "config" / "sys.config"
    kv_config_file = run_dir / "config" / "kv.config"
    
    # 从 kv.config 或服务器名称推断服务器类型
    server_type = 'game_server'
    if kv_config_file.exists():
        kv_config = read_config_file(str(kv_config_file))
        server_type = kv_config.get('server_type', 'game_server').strip('"').strip("'")
    elif 'login_server' in server_name or '_login_' in server_name:
        server_type = 'login_server'
    elif 'client_server' in server_name or '_client_' in server_name:
        server_type = 'client_server'
    elif 'center_server' in server_name or '_center_' in server_name:
        server_type = 'center_server'
    elif 'cross_server' in server_name or '_cross_' in server_name:
        server_type = 'cross_server'
    
    # 根据服务器类型获取 profile
    profile, app_name = get_rebar_profile(server_type)
    
    if use_rebar:
        rebar3 = get_rebar3_cmd(server_root, erl_path)
        eval_expr = _build_rebar_eval_expr(app_name)
        cmd = (
            f'{rebar3} as {profile} shell '
            f'--eval "{eval_expr}" '
            f'--setcookie {cookie} '
            f'--name {server_name}@{ip} '
            f'--config "{config_file}"'
        )
    else:
        erl = get_erl_cmd(erl_path)
        ebin_paths = get_ebin_paths(server_root, profile)
        pa_args = " ".join([f'-pa "{p}"' for p in ebin_paths])
        
        eval_str = f'application:ensure_all_started({app_name}).'
        
        cmd = (
            f'"{erl}" {pa_args} '
            f'-smp enable '
            f'-setcookie {cookie} '
            f'-name {server_name}@{ip} '
            f'-config "{config_file}" '
            f'-eval "{eval_str}"'
        )
    
    return cmd


def build_stop_command(server_name: str, cookie: str, local_host: str = None,
                       erl_path: str = None) -> List[str]:
    """构建停止服务器的命令参数列表
    
    使用 erl -noshell + rpc:call 方式停止服务器。
    返回参数列表，调用方应使用 subprocess.run(args) 直接执行，
    避免 shell=True 导致 cmd.exe 错误解析括号/引号。
    
    Args:
        server_name: 服务器名称
        cookie: Erlang cookie
        local_host: 本地节点使用的IP/主机名（默认使用 get_local_ip()）
        erl_path: Erlang 安装路径
    
    Returns:
        命令参数列表
    """
    ip = local_host if local_host else get_local_ip()
    erl = get_erl_cmd(erl_path)
    
    import time
    stop_node = f"stop_{int(time.time() * 1000) % 100000}"
    
    if '@' in server_name:
        target_node = server_name
    else:
        target_node = f"{server_name}@{ip}"
    
    return [
        erl, "-noshell",
        "-name", f"{stop_node}@{ip}",
        "-setcookie", cookie,
        "-eval", f"rpc:call('{target_node}', init, stop, [])",
        "-s", "c", "q",
    ]


def build_remsh_command(server_name: str, cookie: str, target_ip: str = None,
                        local_host: str = None, erl_path: str = None) -> str:
    """构建远程连接的命令
    
    Args:
        server_name: 服务器名称（完整节点名如 xxx@ip 或仅名称）
        cookie: Erlang cookie
        target_ip: 目标IP（如果 server_name 不包含 @ip 时使用）
        local_host: 本地节点使用的IP/主机名（用于 remsh 节点名，默认使用 get_local_ip()）
        erl_path: Erlang 安装路径
    
    Returns:
        远程连接命令字符串
    """
    local_ip = get_local_ip()
    remsh_host = local_host if local_host else local_ip
    erl = get_erl_cmd(erl_path)
    
    if '@' in server_name:
        target_node = server_name
    else:
        ip = target_ip if target_ip else remsh_host
        target_node = f'{server_name}@{ip}'
    
    timestamp = int(time.time()) % 10000
    return (
        f'"{erl}" +P 1024000 '
        f'-name remsh_{timestamp}@{remsh_host} '
        f'-setcookie {cookie} '
        f'-remsh {target_node}'
    )
