# -*- 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 ServerManageLocalMixin:

    def refresh_server_list(self):
        """刷新服务器列表 - 显示 run 目录下的服务器"""
        self._clear_local_server_table()
        self.local_servers_data = {}  # 清空服务器数据
        self.local_status_label.setText("")
        
        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():
            self._set_local_table_message("运行目录不存在，请在配置页面设置")
            self.console.append_output(f"[警告] 运行目录不存在: {run_dir}\n")
            return
        
        self.console.append_output(f"[信息] 扫描目录: {run_dir}\n")
        
        servers = get_server_list(run_dir)
        
        # 按类型顺序显示
        categories = [
            ('游戏服务器', servers['game'], '🎮'),
            ('跨服服务器', servers['cross'], '🌐'),
            ('登录服务器', servers['login'], '🔐'),
            ('客户端服务器', servers['client'], '📱'),
            ('中心服务器', servers['center'], '🏢'),
            ('其他服务器', servers['other'], '📁')
        ]
        
        total_count = 0
        for category, server_list, icon in categories:
            if server_list:
                for server in sorted(server_list):
                    # 检查是否有 kv.config
                    kv_path = Path(run_dir) / server / 'config' / 'kv.config'
                    has_kv = kv_path.exists()
                    self._add_local_server_row(server, category, icon, has_kv)
                    total_count += 1
        
        if total_count == 0:
            self._set_local_table_message("未找到任何服务器")
            self.console.append_output("[提示] 请先创建服务器\n")
        else:
            self.console.append_output(f"[信息] 找到 {total_count} 个服务器\n")
            self.console.append_output("[提示] 🔧=有kv.config(动态生成) 📄=仅sys.config | 点击刷新状态查看运行状态\n")
            self.refresh_status_from_cache()

    def _clear_local_server_table(self):
        """清空本地服务器表格内容，保留表头。"""
        if hasattr(self.server_list, 'clearSpans'):
            self.server_list.clearSpans()
        self.server_list.setRowCount(0)

    def _set_local_table_message(self, message: str):
        """在本地服务器表格中显示空状态提示。"""
        self._clear_local_server_table()
        self.server_list.insertRow(0)
        item = QTableWidgetItem(message)
        item.setFlags(Qt.ItemFlag.NoItemFlags)
        item.setForeground(QColor("#aab4c3"))
        self.server_list.setItem(0, 0, item)
        self.server_list.setSpan(0, 0, 1, self.server_list.columnCount())

    def _make_local_table_item(self, text: str, server_name: str, color: QColor = None) -> QTableWidgetItem:
        item = QTableWidgetItem(text)
        item.setData(Qt.ItemDataRole.UserRole, server_name)
        item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)
        if color is not None:
            item.setForeground(color)
        return item

    def _make_local_action_button(self, text: str, icon_kind: str, callback, variant: str = "outline") -> QPushButton:
        btn = QPushButton(text)
        btn.setFixedSize(56, 28)
        btn.setCursor(Qt.CursorShape.PointingHandCursor)
        apply_button_style(btn, variant, compact=True)
        btn.setStyleSheet(btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
        if variant in ("primary", "success"):
            icon_color = "#242932"
        elif variant == "danger":
            icon_color = "#ff5c6a"
        else:
            icon_color = "#c6d7ef"
        set_button_icon(btn, icon_kind, icon_color, 11)
        btn.clicked.connect(callback)
        return btn

    def _make_local_action_widget(self, server_name: str, has_kv: bool):
        widget = QWidget()
        widget.setStyleSheet("background: transparent;")
        layout = QHBoxLayout(widget)
        layout.setContentsMargins(6, 5, 6, 5)
        layout.setSpacing(5)

        primary_btn = self._make_local_action_button(
            "启动",
            "play",
            lambda checked=False, s=server_name: self._run_local_primary_action(s),
            "success",
        )
        primary_btn.setToolTip("离线时快速启动（erl 模式）；在线时连接节点")
        layout.addWidget(primary_btn)

        stop_btn = self._make_local_action_button(
            "停服",
            "stop",
            lambda checked=False, s=server_name: self._stop_local_server(s),
            "danger",
        )
        stop_btn.setToolTip("停止服务器，并关闭由本工具启动的相关窗口")
        layout.addWidget(stop_btn)

        config_btn = self._make_local_action_button(
            "配置",
            "edit",
            lambda checked=False, s=server_name: self.edit_server_config(s),
            "outline",
        )
        config_btn.setEnabled(has_kv)
        layout.addWidget(config_btn)

        log_btn = self._make_local_action_button(
            "日志",
            "log",
            lambda checked=False, s=server_name: self._open_local_log_directory(s),
            "outline",
        )
        layout.addWidget(log_btn)

        layout.addStretch()
        return widget, primary_btn, stop_btn

    def _add_local_server_row(self, server_name: str, server_type: str, icon: str, has_kv: bool):
        row = self.server_list.rowCount()
        self.server_list.insertRow(row)

        name_item = self._make_local_table_item(f"{icon} {server_name}", server_name)
        type_item = self._make_local_table_item(server_type, server_name)
        status_item = self._make_local_table_item("⚪ 未检查", server_name, QColor("#aab4c3"))
        config_text = "🔧 kv.config" if has_kv else "📄 sys.config"
        config_item = self._make_local_table_item(config_text, server_name)

        self.server_list.setItem(row, 0, name_item)
        self.server_list.setItem(row, 1, type_item)
        self.server_list.setItem(row, 2, status_item)
        self.server_list.setItem(row, 3, config_item)
        action_widget, primary_btn, stop_btn = self._make_local_action_widget(server_name, has_kv)
        self.server_list.setCellWidget(row, 4, action_widget)
        self.server_list.setRowHeight(row, 52)

        self.local_servers_data[server_name] = {
            'name_item': name_item,
            'type_item': type_item,
            'status_item': status_item,
            'config_item': config_item,
            'primary_btn': primary_btn,
            'stop_btn': stop_btn,
            'online': None,
            'has_kv': has_kv,
        }
    
    def refresh_status_from_cache(self):
        """从缓存刷新服务器状态显示（不重新查询）"""
        if not self.local_servers_data:
            return
        
        cache = get_node_status_cache()
        online_count = 0
        total = len(self.local_servers_data)
        
        for server_name in self.local_servers_data:
            # 从缓存读取状态
            cached_status = cache.get(server_name)
            if cached_status is True:
                online_count += 1
            self._set_local_server_status(server_name, cached_status)
        
        self.local_status_label.setText(f"在线: {online_count}/{total}")
    
    def _refresh_server_status(self):
        """刷新本地服务器运行状态（批量检查）"""
        if not self.local_servers_data:
            self.local_status_label.setText("没有服务器")
            return
        if self._local_status_worker and self._local_status_worker.isRunning():
            self.local_status_label.setText("正在检查...")
            return
        
        cookie = self.config.get('server', 'cookie', default='ddxq2-node')
        server_names = list(self.local_servers_data.keys())
        
        self.refresh_status_btn.setEnabled(False)
        self.local_status_label.setText("正在检查...")
        worker = NodeStatusCheckWorker(
            server_names,
            cookie,
            erl_path=self._get_erl_path(),
        )
        self._local_status_worker = worker
        worker.finished_signal.connect(self._on_local_status_refresh_finished)
        worker.finished.connect(
            lambda w=worker: setattr(self, '_local_status_worker', None) if self._local_status_worker is w else None
        )
        worker.finished.connect(worker.deleteLater)
        worker.start()

    def _on_local_status_refresh_finished(self, results):
        """本地节点状态刷新完成。"""
        cache = get_node_status_cache()
        cache.batch_set(results)

        online_count = 0
        total = len(self.local_servers_data)
        for server_name in self.local_servers_data:
            is_online = results.get(server_name, False)
            if is_online:
                online_count += 1
            self._set_local_server_status(server_name, is_online)

        self.local_status_label.setText(f"在线: {online_count}/{total}")
        self.refresh_status_btn.setEnabled(True)
        self.console.append_output(f"[状态] 在线服务器: {online_count}/{total}\n")
    
    def _set_local_server_status(self, server_name: str, is_online):
        """更新本地服务器表格中的状态列和行颜色。"""
        data = self.local_servers_data.get(server_name)
        if not data:
            return

        if is_online is True:
            status_text = "🟢 在线"
            fg = QColor("#25c889")
        elif is_online is False:
            status_text = "⚪ 离线"
            fg = QColor("#aab4c3")
        else:
            status_text = "⚪ 未检查"
            fg = QColor("#aab4c3")

        status_item = data.get('status_item')
        if status_item:
            status_item.setText(status_text)
        data['online'] = is_online
        for key in ('name_item', 'type_item', 'status_item', 'config_item'):
            item = data.get(key)
            if item:
                item.setForeground(fg)
        self._sync_local_primary_button(server_name)
        self._sync_local_stop_button(server_name)

    def _sync_local_primary_button(self, server_name: str):
        """按当前状态同步本地服务器行的主操作按钮。"""
        data = self.local_servers_data.get(server_name)
        if not data:
            return
        btn = data.get('primary_btn')
        if not btn:
            return

        if data.get('online') is True:
            btn.setText("连接")
            btn.setToolTip("连接到已在线节点")
            apply_button_style(btn, "primary", compact=True)
            btn.setStyleSheet(btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
            set_button_icon(btn, "link", "#242932", 11)
        else:
            btn.setText("启动")
            btn.setToolTip("快速启动（erl 模式）")
            apply_button_style(btn, "success", compact=True)
            btn.setStyleSheet(btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
            set_button_icon(btn, "play", "#242932", 11)
        btn.setEnabled(True)

    def _sync_local_stop_button(self, server_name: str):
        """按当前状态同步本地服务器行的停服按钮。"""
        data = self.local_servers_data.get(server_name)
        if not data:
            return
        btn = data.get('stop_btn')
        if not btn:
            return
        btn.setText("停服")
        btn.setToolTip("停止服务器，并关闭由本工具启动的相关窗口")
        apply_button_style(btn, "danger", compact=True)
        btn.setStyleSheet(btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
        set_button_icon(btn, "stop", "#ff5c6a", 11)
        btn.setEnabled(data.get('online') is True)

    def _set_local_server_starting(self, server_name: str):
        """显示本地服务器启动中的状态。"""
        data = self.local_servers_data.get(server_name)
        if not data:
            return

        status_item = data.get('status_item')
        if status_item:
            status_item.setText("🟡 启动中")
        for key in ('name_item', 'type_item', 'status_item', 'config_item'):
            item = data.get(key)
            if item:
                item.setForeground(QColor("#f5b04b"))

        btn = data.get('primary_btn')
        if btn:
            btn.setText("启动")
            btn.setToolTip("正在快速启动（erl 模式）")
            apply_button_style(btn, "neutral", compact=True)
            btn.setStyleSheet(btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
            set_button_icon(btn, "refresh", "#aab4c3", 11)
            btn.setEnabled(False)

        stop_btn = data.get('stop_btn')
        if stop_btn:
            stop_btn.setEnabled(False)

    def _set_local_server_stopping(self, server_name: str):
        """显示本地服务器停止中的状态。"""
        data = self.local_servers_data.get(server_name)
        if not data:
            return

        status_item = data.get('status_item')
        if status_item:
            status_item.setText("🟡 停止中")
        for key in ('name_item', 'type_item', 'status_item', 'config_item'):
            item = data.get(key)
            if item:
                item.setForeground(QColor("#f5b04b"))

        primary_btn = data.get('primary_btn')
        if primary_btn:
            primary_btn.setEnabled(False)

        stop_btn = data.get('stop_btn')
        if stop_btn:
            stop_btn.setToolTip("正在停止服务器")
            apply_button_style(stop_btn, "neutral", compact=True)
            stop_btn.setStyleSheet(stop_btn.styleSheet() + "\nQPushButton { padding: 2px 4px; font-size: 11px; }")
            set_button_icon(stop_btn, "refresh", "#aab4c3", 11)
            stop_btn.setEnabled(False)

    def _run_local_primary_action(self, server_name: str):
        """本地服务器行主操作：在线连接，离线启动。"""
        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 True:
            self._connect_to_remote_node(server_name)
        else:
            self._start_local_server(server_name)

    def _update_server_item_status(self, server_name: str, is_online: bool):
        """更新服务器列表项的状态显示
        
        Args:
            server_name: 服务器名称
            is_online: 是否在线
        """
        if server_name not in self.local_servers_data:
            return
        self._set_local_server_status(server_name, is_online)
    
    def _schedule_status_check(self, server_name: str, cookie: str, retry_count: int = 0):
        """延迟检查服务器启动状态
        
        启动服务器后延迟几秒检查状态，并更新缓存和列表显示
        最多重试10次，每次间隔5秒
        
        Args:
            server_name: 服务器名称
            cookie: Erlang cookie
            retry_count: 当前重试次数（最多10次）
        """
        self._pending_status_checks[server_name] = {
            'cookie': cookie,
            'retry_count': retry_count,
            'due_at': time.monotonic() + 5.0,
        }
        self._restart_status_check_timer()

    def _restart_status_check_timer(self):
        """根据待检查队列重启状态检查定时器。"""
        if not self._pending_status_checks:
            self._status_check_timer.stop()
            return

        now = time.monotonic()
        next_due_at = min(
            item['due_at'] for item in self._pending_status_checks.values()
        )
        delay_ms = max(0, int((next_due_at - now) * 1000))
        self._status_check_timer.start(delay_ms)

    def _flush_scheduled_status_checks(self):
        """批量执行到期的启动状态检查。"""
        if not self._pending_status_checks:
            return
        if self._scheduled_status_worker and self._scheduled_status_worker.isRunning():
            self._restart_status_check_timer()
            return

        now = time.monotonic()
        due_checks = {}
        for server_name, info in list(self._pending_status_checks.items()):
            if info['due_at'] <= now + 0.05:
                due_checks[server_name] = self._pending_status_checks.pop(server_name)

        if not due_checks:
            self._restart_status_check_timer()
            return

        max_retries = 10
        erl_path = self._get_erl_path()
        cookie_groups = {}
        for server_name, info in due_checks.items():
            cookie_groups.setdefault(info['cookie'], []).append(server_name)

        worker = GroupedNodeStatusCheckWorker(cookie_groups, erl_path=erl_path)
        self._scheduled_status_worker = worker
        worker.finished_signal.connect(
            lambda results, checks=due_checks, retries=max_retries: self._on_scheduled_status_checks_finished(
                results, checks, retries
            )
        )
        worker.finished.connect(
            lambda w=worker: setattr(self, '_scheduled_status_worker', None) if self._scheduled_status_worker is w else None
        )
        worker.finished.connect(worker.deleteLater)
        worker.start()

    def _on_scheduled_status_checks_finished(self, results, due_checks, max_retries: int):
        """处理批量启动状态检查结果。"""
        cache = get_node_status_cache()
        for server_name, info in due_checks.items():
            is_online = results.get(server_name, False)
            retry_count = info['retry_count']

            cache.set(server_name, is_online)

            if is_online:
                self._update_server_item_status(server_name, True)
                self.console.append_output(f"[状态] 服务器 {server_name} 已启动 🟢\n")
                continue

            current_retry = retry_count + 1
            if current_retry < max_retries:
                self._set_local_server_starting(server_name)
                self.console.append_output(
                    f"[状态] 服务器 {server_name} 启动中... (检查 {current_retry}/{max_retries})\n"
                )
                self._schedule_status_check(server_name, info['cookie'], current_retry)
            else:
                self._update_server_item_status(server_name, False)
                self.console.append_output(
                    f"[状态] 服务器 {server_name} 启动超时，请检查启动日志 ⚪\n"
                )

        self._restart_status_check_timer()

    def _on_local_server_double_clicked(self, item):
        """双击本地服务器时执行主操作：在线连接，离线启动。"""
        server_name = item.data(Qt.ItemDataRole.UserRole) if item else None
        if server_name:
            self._run_local_primary_action(server_name)
