# -*- coding: utf-8 -*-
"""Main tab views."""

from util.runtime import *
from util.utils import node_host_only, _server_id_sort_key
from models.config import Config, apply_terminal_launch_config
from controllers.workers import (
    CommandRunner,
    GroupedNodeStatusCheckWorker,
    NodeStatusCheckWorker,
    StopServerWorker,
)
from views.common import (
    NoWheelComboBox,
    NoWheelDateTimeEdit,
    NoWheelSpinBox,
    ServerIdTableItem,
    apply_button_style,
    make_line_icon,
    set_button_icon,
)
from views.console import OutputConsole
from views.dialogs import (
    ClearDatabaseDialog,
    KvConfigEditDialog,
    RemoteConnectDialog,
    ServerSelectDialog,
    ViewAccountsDialog,
)


class ServerManageActionsMixin:

    def _start_local_server(self, server_name: str):
        """快速启动本地服务器；若实际已在线，则改为连接。"""
        server_root = self.config.get('workspace', 'server_root', default='')
        if not server_root:
            QMessageBox.warning(self, "警告", "请先在配置页面设置服务器根目录")
            return

        cookie = self.config.get('server', 'cookie', default='')
        if not cookie:
            merged = read_merged_config(server_root)
            cookie = merged.get('cookie', 'ddxq2-node')

        self.console.append_output(f"[检查] 正在检查节点 {server_name} 是否在线...\n")
        is_online = check_node_status(server_name, cookie, erl_path=self._get_erl_path())
        cache = get_node_status_cache()
        cache.set(server_name, is_online)
        self._update_server_item_status(server_name, is_online)

        if is_online:
            self._connect_to_remote_node(server_name)
            return

        cmd = build_start_command(server_root, server_name, cookie, use_rebar=False, erl_path=self._get_erl_path())
        self.console.append_output(f"[命令] {cmd}\n")
        self.console.append_output(f"[目录] {server_root}\n")
        server_title = f"SERVER {server_name}"
        launch_info = run_cmd_in_new_window(
            cmd,
            server_root,
            server_title,
            self._get_erl_path(),
            **get_terminal_launch_options(self.config),
        )
        register_launched_window(server_name, 'server', server_title, launch_info)
        self.console.append_output(f"[服务器] 正在快速启动 {server_name}（erl 模式）...\n")
        self._set_local_server_starting(server_name)
        self._schedule_status_check(server_name, cookie)

    def _stop_local_server(self, server_name: str):
        """停止本地服务器，并同步本地列表状态。"""
        if getattr(self, '_local_stop_worker', None) is not None and self._local_stop_worker.isRunning():
            QMessageBox.information(self, "提示", "当前已有停止任务正在执行，请稍候")
            return

        data = self.local_servers_data.get(server_name, {})
        cached_status = get_node_status_cache().get(server_name)
        is_online = cached_status if cached_status is not None else data.get('online')
        if is_online is not True:
            return

        reply = QMessageBox.question(
            self,
            '确认停服',
            f'确定要停止服务器 {server_name} 吗？\n\n'
            f'停止后会等待节点完全离线，并关闭由本工具启动的相关窗口。',
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        if reply != QMessageBox.StandardButton.Yes:
            return

        server_root = self.config.get('workspace', 'server_root', default='')
        cookie = self.config.get('server', 'cookie', default='')
        if not cookie and server_root:
            merged = read_merged_config(server_root)
            cookie = merged.get('cookie', 'ddxq2-node')
        if not cookie:
            cookie = 'ddxq2-node'

        logger.info(f"停止本地服务器: {server_name}")
        self._pending_status_checks.pop(server_name, None)
        self._restart_status_check_timer()
        self._set_local_server_stopping(server_name)

        worker = StopServerWorker(
            server_name,
            cookie,
            erl_path=self._get_erl_path(),
            parent=self,
        )
        worker.progress_signal.connect(self.console.append_output)
        worker.finished_signal.connect(
            lambda ok, msg, s=server_name: self._on_local_stop_server_finished(s, ok, msg)
        )
        worker.finished.connect(worker.deleteLater)
        worker.finished.connect(
            lambda w=worker: setattr(self, '_local_stop_worker', None)
            if getattr(self, '_local_stop_worker', None) is w else None
        )
        self._local_stop_worker = worker
        worker.start()

    def _on_local_stop_server_finished(self, server_name: str, is_success: bool, message: str):
        """停止服务器结束回调：更新状态缓存和本地列表。"""
        cache = get_node_status_cache()
        if is_success:
            cache.set_offline(server_name)
            self.refresh_status_from_cache()
            self.console.append_output(f"[成功] {message}\n")
            logger.info(f"本地服务器停止成功: {server_name}")
            return

        cache.set(server_name, True)
        self.refresh_status_from_cache()
        self.console.append_output(f"[失败] {message}\n")
        logger.warning(f"本地服务器停止失败: {server_name} - {message}")
        QMessageBox.warning(self, "停止失败", message)

    def _open_local_log_directory(self, server_name: str):
        """打开本地服务器的日志目录。"""
        server_root = self.config.get('workspace', 'server_root', default='')
        run_dir = self.config.get('workspace', 'run_dir', default='')
        if not run_dir and server_root:
            run_dir = str(Path(server_root) / 'run')

        if not run_dir or not Path(run_dir).exists():
            QMessageBox.warning(self, "打开日志", "请先在配置页面设置有效的运行目录")
            return

        log_dir = Path(run_dir) / server_name / 'log'
        if not log_dir.is_dir():
            QMessageBox.information(
                self,
                "打开日志",
                f"目录不存在：\n{log_dir}\n\n请先在该服务器下产生日志或检查路径。",
            )
            return

        try:
            if os.name == 'nt':
                os.startfile(str(log_dir.resolve()))
            else:
                subprocess.Popen(['xdg-open', str(log_dir.resolve())])
        except Exception as e:
            QMessageBox.warning(self, "打开日志", f"打开失败：{e}")

    def _get_selected_server(self) -> Optional[str]:
        """获取选中的服务器"""
        row = self.server_list.currentRow()
        if row < 0:
            return None
        item = self.server_list.item(row, 0)
        if item:
            return item.data(Qt.ItemDataRole.UserRole)
        return None
    
    def remsh_server(self):
        """远程连接服务器"""
        # 获取选中的服务器作为默认值
        selected_server = self._get_selected_server()
        
        dialog = RemoteConnectDialog(self.config, self, initial_tab='local', console=self.console)
        # 如果有选中的服务器，预填充
        if selected_server:
            dialog.node_input.setText(selected_server)
            # 在本地列表中选中对应项
            for i in range(dialog.local_list.count()):
                item = dialog.local_list.item(i)
                if item.data(Qt.ItemDataRole.UserRole) == selected_server:
                    dialog.local_list.setCurrentItem(item)
                    break
        
        if dialog.exec() == QDialog.DialogCode.Accepted:
            node_name = dialog.node_name
            target_ip = dialog.target_ip
            cookie = dialog.cookie
            
            server_root = self.config.get('workspace', 'server_root', default='')
            cmd = build_remsh_command(node_name, cookie, target_ip, erl_path=self._get_erl_path())
            
            # 确定显示的目标节点名
            if '@' in node_name:
                target_node = node_name
            else:
                target_node = f"{node_name}@{target_ip}" if target_ip else f"{node_name}@{get_local_ip()}"
            
            remsh_title = f"REMSH {target_node}"
            launch_info = run_cmd_in_new_window(
                cmd,
                server_root,
                remsh_title,
                self._get_erl_path(),
                **get_terminal_launch_options(self.config),
            )
            register_launched_window(target_node, 'remsh', remsh_title, launch_info)
            self.console.append_output(f"[远程连接] 正在连接到 {target_node}...\n")
    
    def edit_server_config(self, server: Optional[str] = None):
        """编辑服务器配置"""
        if not isinstance(server, str):
            server = self._get_selected_server()
        if not server:
            QMessageBox.warning(self, "警告", "请先选择一个服务器")
            return
        
        server_root = self.config.get('workspace', 'server_root', default='')
        run_dir = self.config.get('workspace', 'run_dir', default='')
        
        if not run_dir and server_root:
            run_dir = str(Path(server_root) / 'run')
        
        # 检查 kv.config 是否存在
        kv_config_path = Path(run_dir) / server / 'config' / 'kv.config'
        if not kv_config_path.exists():
            QMessageBox.warning(self, "警告", f"服务器 {server} 没有 kv.config 文件\n\n该服务器可能是手动创建的，不支持编辑配置。")
            return
        
        # 从服务器目录名解析服务器类型
        server_type = self._parse_server_type(server)
        
        # 打开编辑对话框
        dialog = KvConfigEditDialog(
            kv_config_path=str(kv_config_path),
            server_type=server_type,
            server_name=server,
            server_root=server_root,
            console=self.console,
            parent=self
        )
        dialog.exec()
    
    def regenerate_server_config(self, server: Optional[str] = None):
        """重新生成服务器的 sys.config"""
        if not isinstance(server, str):
            server = self._get_selected_server()
        if not server:
            QMessageBox.warning(self, "警告", "请先选择一个服务器")
            return
        
        server_root = self.config.get('workspace', 'server_root', default='')
        run_dir = self.config.get('workspace', 'run_dir', default='')
        
        if not run_dir and server_root:
            run_dir = str(Path(server_root) / 'run')
        
        # 检查 kv.config 是否存在
        kv_config_path = Path(run_dir) / server / 'config' / 'kv.config'
        if not kv_config_path.exists():
            QMessageBox.warning(self, "警告", f"服务器 {server} 没有 kv.config 文件\n\n无法重新生成 sys.config。")
            return
        
        # 重新生成 sys.config
        merged_config = generate_start_config(server_root, server)
        if merged_config:
            config_file = merged_config.get('_config_file', '')
            self.console.append_output(f"[成功] 已重新生成: {config_file}\n")
            QMessageBox.information(self, "成功", f"sys.config 已重新生成！\n\n{config_file}")
        else:
            self.console.append_output(f"[错误] 重新生成 sys.config 失败: {server}\n")
            QMessageBox.warning(self, "警告", "重新生成 sys.config 失败，请检查配置。")

    def regenerate_all_server_configs(self):
        """重新生成全部带 kv.config 的本地服务器配置。"""
        server_root = self.config.get('workspace', 'server_root', default='')
        if not server_root:
            QMessageBox.warning(self, "警告", "请先在配置页面设置服务器根目录")
            return

        run_dir = self.config.get('workspace', 'run_dir', default='')
        if not run_dir:
            run_dir = str(Path(server_root) / 'run')
        if not run_dir or not Path(run_dir).exists():
            QMessageBox.warning(self, "警告", "请先在配置页面设置有效的运行目录")
            return

        servers = get_config_list(run_dir)
        if not servers:
            QMessageBox.information(self, "生成", "没有找到可生成配置的服务器（缺少 kv.config）")
            return

        success = []
        failed = []
        self.console.append_output(f"[生成] 开始重新生成 {len(servers)} 个服务器配置...\n")
        for server in servers:
            try:
                merged_config = generate_start_config(server_root, server)
            except Exception as e:
                logger.error("重新生成服务器配置异常: %s", server, exc_info=True)
                failed.append(server)
                self.console.append_output(f"[错误] {server}: {e}\n")
                continue

            if merged_config:
                config_file = merged_config.get('_config_file', '')
                success.append(server)
                self.console.append_output(f"[成功] {server}: {config_file}\n")
            else:
                failed.append(server)
                self.console.append_output(f"[失败] {server}: 生成 sys.config 失败\n")

        summary = f"生成完成：成功 {len(success)} 个，失败 {len(failed)} 个"
        self.console.append_output(f"[生成] {summary}\n")
        if failed:
            QMessageBox.warning(self, "生成", summary)
        else:
            QMessageBox.information(self, "生成", summary)
    
    def _parse_server_type(self, server_name: str) -> str:
        """从服务器目录名解析服务器类型"""
        name_lower = server_name.lower()
        if '_game_s' in name_lower or '_game_' in name_lower:
            return 'game'
        elif '_cross_s' in name_lower or '_cross_' in name_lower:
            return 'cross'
        elif '_login_s' in name_lower or '_login_' in name_lower:
            return 'login'
        elif '_client_s' in name_lower or '_client_' in name_lower:
            return 'client'
        elif '_center_s' in name_lower or '_center_' in name_lower:
            return 'center'
        return 'game'  # 默认为游戏服
    
    def delete_server(self):
        """删除服务器"""
        server = self._get_selected_server()
        if not server:
            QMessageBox.warning(self, "警告", "请先选择一个服务器")
            return
        
        reply = QMessageBox.question(
            self, '确认删除',
            f'确定要删除服务器 {server} 吗？此操作不可恢复！',
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        
        if reply == QMessageBox.StandardButton.Yes:
            run_dir = self.config.get('workspace', 'run_dir', default='')
            server_path = Path(run_dir) / server
            
            try:
                import shutil
                shutil.rmtree(server_path)
                self.console.append_output(f"[成功] 服务器 {server} 已删除\n")
                self.refresh_server_list()
                QMessageBox.information(self, "成功", f"服务器 {server} 已删除")
            except Exception as e:
                self.console.append_output(f"[错误] 删除服务器失败: {str(e)}\n")
                QMessageBox.critical(self, "错误", f"删除失败: {str(e)}")
