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

    def _remote_table_node_at_row(self, row: int):
        """从远程服务器表格行解析 Erlang 节点名（第三列）。"""
        if row < 0:
            return None
        it = self.remote_server_list.item(row, 2)
        if not it:
            return None
        node = it.data(Qt.ItemDataRole.UserRole)
        return node if node else it.text().strip() or None

    def _remote_node_is_online(self, server_node: str) -> bool:
        """判断主界面远程列表中的节点是否在线。"""
        data = self.remote_servers_data.get(server_node) if server_node else None
        if not data:
            return False
        server = data.get('server') or {}
        return server.get('running') is True
    
    def _load_remote_servers(self):
        """通过 rpc:call 从登录服加载远程服务器列表"""
        login_node = (self.config.get('server', 'login_server_node', default='') or '').strip()
        cookie = (self.config.get('server', 'cookie', default='') or 'ddxq2-node').strip()
        erl_path = (self._get_erl_path() or '').strip() or None
        
        if not login_node:
            self.remote_status_label.setText("请先在项目设置中配置登录服节点")
            self.remote_status_label.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            return
        
        self.remote_status_label.setText("正在检测登录服节点...")
        self.remote_status_label.setStyleSheet("color: #f5b04b; font-size: 11px;")
        QApplication.processEvents()
        
        if not check_node_status(login_node, cookie, erl_path=erl_path):
            self.remote_status_label.setText("登录服节点不可达")
            self.remote_status_label.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            QMessageBox.warning(
                self,
                "无法连接登录服",
                "无法连通登录服节点（net_adm:ping 未返回 pong）。\n\n"
                "请检查：\n"
                "· 登录服节点名称是否正确（形如 name@ip）\n"
                "· Cookie 是否与登录服 erlang.cookie 一致\n"
                "· 项目设置中的 Erlang 路径、网络与防火墙",
            )
            return
        
        self.remote_status_label.setText(f"正在从登录服加载列表 {login_node} ...")
        self.remote_status_label.setStyleSheet("color: #f5b04b; font-size: 11px;")
        QApplication.processEvents()
        
        try:
            remote_servers_list = query_remote_servers_from_login_rpc(
                login_node, cookie, erl_path=erl_path
            )
            remote_servers_list = sorted(remote_servers_list, key=lambda s: _server_id_sort_key(s.get('server_id')))
            
            self.remote_server_list.setSortingEnabled(False)
            self.remote_server_list.setRowCount(0)
            self.remote_servers_data = {}
            
            for server in remote_servers_list:
                server_id = server['server_id']
                server_name = server.get('server_name', '') or ''
                server_node = server['server_node']
                running = server.get('running', False)
                status_icon = "🟢" if running else "⚪"
                
                row = self.remote_server_list.rowCount()
                self.remote_server_list.insertRow(row)
                c0 = ServerIdTableItem(status_icon, server_id)
                c1 = QTableWidgetItem(server_name)
                c2 = QTableWidgetItem(server_node)
                c2.setData(Qt.ItemDataRole.UserRole, server_node)
                self.remote_server_list.setItem(row, 0, c0)
                self.remote_server_list.setItem(row, 1, c1)
                self.remote_server_list.setItem(row, 2, c2)
                
                self.remote_servers_data[server_node] = {
                    'item': c0,
                    'server_id': server_id,
                    'server': server,
                }

            self.remote_server_list.setSortingEnabled(True)
            self.remote_server_list.sortItems(0, Qt.SortOrder.AscendingOrder)
            
            self.remote_status_label.setText(f"已加载 {len(self.remote_servers_data)} 个服务器")
            self.remote_status_label.setStyleSheet("color: #25c889; font-size: 11px;")
            self.console.append_output(
                f"[远程] 从登录服 {login_node} 加载了 {len(self.remote_servers_data)} 个远程服务器\n"
            )
            
            self.remote_search_input.clear()
            QTimer.singleShot(0, self._refresh_remote_server_status)
            
        except ValueError as e:
            self.remote_status_label.setText(str(e))
            self.remote_status_label.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            self.console.append_output(f"[错误] {str(e)}\n")
        except Exception as e:
            self.remote_status_label.setText("加载失败")
            self.remote_status_label.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            self.console.append_output(f"[错误] 加载远程服务器失败: {str(e)}\n")
            QMessageBox.warning(self, "从登录服加载失败", str(e))
    
    def _refresh_remote_server_status(self):
        """刷新远程服务器运行状态（批量检查当前表格中的节点）"""
        if not self.remote_servers_data:
            self.remote_status_label.setText("请先加载服务器列表")
            return
        if self._remote_status_worker and self._remote_status_worker.isRunning():
            return
        
        cookie = self.config.get('server', 'cookie', default='ddxq2-node')
        
        display_nodes = []
        seen_nodes = set()
        for i in range(self.remote_server_list.rowCount()):
            node = self._remote_table_node_at_row(i)
            if node and node not in seen_nodes:
                display_nodes.append(node)
                seen_nodes.add(node)
        
        if not display_nodes:
            self.remote_status_label.setText("列表为空")
            return
        
        total = len(self.remote_servers_data)
        check_count = len(display_nodes)
        
        self.refresh_remote_status_btn.setEnabled(False)
        self.remote_status_label.setText(f"正在批量检查 {check_count} 个...")
        self.remote_status_label.setStyleSheet("color: #f5b04b; font-size: 11px;")
        worker = NodeStatusCheckWorker(
            display_nodes,
            cookie,
            erl_path=self._get_erl_path(),
        )
        self._remote_status_worker = worker
        worker.finished_signal.connect(
            lambda results, total_count=total, current_count=check_count: self._on_remote_status_refresh_finished(
                results, total_count, current_count
            )
        )
        worker.finished.connect(
            lambda w=worker: setattr(self, '_remote_status_worker', None) if self._remote_status_worker is w else None
        )
        worker.finished.connect(worker.deleteLater)
        worker.start()

    def _on_remote_status_refresh_finished(self, results, total: int, check_count: int):
        """远程节点状态刷新完成。"""
        cache = get_node_status_cache()
        cache.batch_set(results)

        online_count = 0
        for row in range(self.remote_server_list.rowCount()):
            server_node = self._remote_table_node_at_row(row)
            if not server_node:
                continue

            data = self.remote_servers_data.get(server_node)
            if not data:
                continue

            item = self.remote_server_list.item(row, 0)
            server_id = data['server_id']
            is_online = results.get(server_node, False)
            data['server']['running'] = is_online

            if is_online:
                status_icon = "🟢"
                fg = QColor("#25c889")
                online_count += 1
            else:
                status_icon = "⚪"
                fg = QColor("#aab4c3")

            if item:
                item.setText(f"{status_icon} {server_id}")
            for col in range(3):
                it = self.remote_server_list.item(row, col)
                if it:
                    it.setForeground(fg)

        if check_count == total:
            status_text = f"在线: {online_count}/{check_count}"
        else:
            status_text = f"当前显示在线: {online_count}/{check_count} | 总数: {total}"
        self.remote_status_label.setText(status_text)
        self.remote_status_label.setStyleSheet("color: #25c889; font-size: 11px;")
        self.refresh_remote_status_btn.setEnabled(True)
        self.console.append_output(f"[远程状态] 批量检查 {check_count} 个节点，在线: {online_count}\n")
    
    def _filter_remote_servers(self, text: str):
        """根据搜索文本过滤远程服务器列表"""
        if not hasattr(self, 'remote_servers_data') or not self.remote_servers_data:
            return
        
        search_text = text.strip().lower()
        self.remote_server_list.setSortingEnabled(False)
        self.remote_server_list.setRowCount(0)
        
        filtered_count = 0
        for server_node, data in sorted(
            self.remote_servers_data.items(),
            key=lambda item: _server_id_sort_key(item[1].get('server_id')),
        ):
            server_id = str(data['server_id'])
            server = data['server']
            server_name = server.get('server_name', '') or ''
            
            if search_text:
                hay = (server_id + " " + server_name + " " + server_node).lower()
                if search_text not in hay:
                    continue
            
            running = server.get('running', False)
            status_icon = "🟢" if running else "⚪"
            row = self.remote_server_list.rowCount()
            self.remote_server_list.insertRow(row)
            c0 = ServerIdTableItem(status_icon, server_id)
            c1 = QTableWidgetItem(server_name)
            c2 = QTableWidgetItem(server_node)
            c2.setData(Qt.ItemDataRole.UserRole, server_node)
            self.remote_server_list.setItem(row, 0, c0)
            self.remote_server_list.setItem(row, 1, c1)
            self.remote_server_list.setItem(row, 2, c2)
            
            data['item'] = c0
            filtered_count += 1

        self.remote_server_list.setSortingEnabled(True)
        self.remote_server_list.sortItems(0, Qt.SortOrder.AscendingOrder)
        
        total_count = len(self.remote_servers_data)
        if search_text:
            self.remote_status_label.setText(f"显示 {filtered_count}/{total_count} 个服务器")
        else:
            self.remote_status_label.setText(f"已加载 {total_count} 个服务器")
        self.remote_status_label.setStyleSheet("color: #25c889; font-size: 11px;")
    
    def _on_remote_server_double_clicked(self, item):
        """双击在线远程服务器时连接，离线节点不做任何操作。"""
        server_node = self._remote_table_node_at_row(item.row())
        if server_node and self._remote_node_is_online(server_node):
            self._connect_to_remote_node(server_node)

    def _on_tab_changed(self, index):
        """选项卡切换时更新操作按钮"""
        if index == 0:  # 本地服务器
            self.local_ops_group.show()
            self.remote_ops_group.hide()
        else:  # 远程服务器
            self.local_ops_group.hide()
            self.remote_ops_group.show()
    
    def _remsh_remote_server(self):
        """远程连接远程服务器 - 打开对话框并默认显示远程服务器列表"""
        current = self.remote_server_list.currentItem()
        selected_node = self._remote_table_node_at_row(current.row()) if current else None
        
        remote_data = None
        if hasattr(self, 'remote_servers_data') and self.remote_servers_data:
            remote_data = []
            for server_node, data in self.remote_servers_data.items():
                server_info = data.get('server', {})
                remote_data.append({
                    'server_id': data.get('server_id', ''),
                    'server_node': server_node,
                    'server_name': server_info.get('server_name', ''),
                    'running': server_info.get('running', False)
                })
        
        dialog = RemoteConnectDialog(self.config, self, initial_tab='remote', remote_servers=remote_data, console=self.console)
        
        # 如果已有选中的远程服务器，预填充
        if selected_node:
            dialog.node_input.setText(selected_node)
            # 提取 IP
            if '@' in selected_node:
                ip_part = selected_node.split('@')[-1]
                dialog.ip_input.setText(ip_part)
        
        if dialog.exec() == QDialog.DialogCode.Accepted:
            node_name = dialog.node_name
            target_ip = dialog.target_ip
            cookie = dialog.cookie
            
            if node_name:
                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 _connect_to_remote_node(self, server_node: str):
        """连接到远程节点"""
        # 读取 cookie（kv.config > user.config > project.config > default.config）
        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')
        
        cmd = build_remsh_command(server_node, cookie, erl_path=self._get_erl_path())
        self.console.append_output(f"[命令] {cmd}\n")
        remsh_title = f"REMSH {server_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(server_node, 'remsh', remsh_title, launch_info)
        self.console.append_output(f"[远程] 正在连接到 {server_node}...\n")
