# -*- coding: utf-8 -*-
"""Dialog views for destructive actions, selection, remote connect, and KV editing."""

from util.runtime import *
from util.utils import node_host_only, _server_id_sort_key
from models.config import Config
from controllers.workers import ClearDatabaseThread, NodeStatusCheckWorker
from views.common import (
    ServerIdTableItem,
    NoWheelComboBox,
    apply_button_style,
    set_button_icon,
)

class RemoteConnectDialog(QDialog):
    """远程连接对话框 - 支持输入节点名称和IP，以及从登录服 RPC 加载远程服务器列表"""
    
    def __init__(self, config: 'Config', parent=None, initial_tab: str = 'local', remote_servers: list = None, console=None):
        """
        Args:
            config: 配置对象
            parent: 父窗口
            initial_tab: 初始显示的选项卡 ('local' 或 'remote')
            remote_servers: 外部已加载的远程服务器列表（可选）
            console: 控制台输出对象（可选，用于输出命令信息）
        """
        super().__init__(parent)
        self.config = config
        self.console = console
        self.node_name = None
        self.target_ip = None
        self.remote_servers = remote_servers or []  # 远程服务器列表
        self.remote_servers_data = remote_servers or []  # 所有远程服务器数据（用于搜索）
        self.initial_tab = initial_tab
        self.setWindowTitle("远程连接")
        self.setMinimumSize(550, 550)
        self.init_ui()
        
        # 如果有外部传入的数据，直接显示
        if remote_servers:
            self._display_remote_servers()
    
    def init_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(10)
        layout.setContentsMargins(15, 15, 15, 15)
        
        # 标题
        title = QLabel("连接到远程 Erlang 节点")
        title.setStyleSheet("font-size: 14px; font-weight: bold; color: #e8eef7;")
        layout.addWidget(title)
        
        # 输入表单
        form_layout = QFormLayout()
        form_layout.setSpacing(8)
        
        # 节点名称输入
        self.node_input = QLineEdit()
        self.node_input.setPlaceholderText("例如: ai002_game_server_s100@192.168.1.1")
        self.node_input.setMinimumWidth(350)
        form_layout.addRow("节点名称:", self.node_input)
        
        # IP地址输入（可选）
        self.ip_input = QLineEdit()
        self.ip_input.setPlaceholderText("如果节点名称已包含@IP则可留空")
        self.ip_input.setText(get_local_ip())
        form_layout.addRow("目标 IP:", self.ip_input)
        
        # Cookie 输入（kv.config > user.config > project.config > default.config）
        self.cookie_input = QLineEdit()
        default_cookie = self.config.get('server', 'cookie', default='')
        if not default_cookie:
            server_root = self.config.get('workspace', 'server_root', default='')
            if server_root:
                merged = read_merged_config(server_root)
                default_cookie = merged.get('cookie', 'ddxq2-node')
            else:
                default_cookie = 'ddxq2-node'
        self.cookie_input.setText(default_cookie)
        form_layout.addRow("Cookie:", self.cookie_input)
        
        layout.addLayout(form_layout)
        
        # 提示信息
        hint = QLabel("提示: 如果节点名称格式为 name@ip，则目标 IP 输入框将被忽略")
        hint.setStyleSheet("color: #aab4c3; font-size: 11px;")
        layout.addWidget(hint)
        
        # 服务器选择选项卡
        self.server_tabs = QTabWidget()
        self.server_tabs.setStyleSheet("""
            QTabWidget::pane {
                border: 1px solid #3a4352;
                border-radius: 8px;
                background-color: #242932;
            }
            QTabBar::tab {
                background-color: #242932;
                color: #aab4c3;
                padding: 6px 15px;
                margin-right: 2px;
                border-bottom: 2px solid transparent;
            }
            QTabBar::tab:selected {
                color: #4f8cff;
                border-bottom: 2px solid #4f8cff;
            }
            QTabBar::tab:hover:!selected {
                color: #4f8cff;
            }
        """)
        
        # === 本地服务器选项卡 ===
        local_widget = QWidget()
        local_layout = QVBoxLayout(local_widget)
        local_layout.setSpacing(8)
        local_layout.setContentsMargins(10, 10, 10, 10)
        
        # 本地服务器列表
        self.local_list = QListWidget()
        self.local_list.itemClicked.connect(self._on_local_server_clicked)
        self.local_list.itemDoubleClicked.connect(self._on_local_server_double_clicked)
        
        # 加载本地服务器列表（从缓存读取状态）
        run_dir = self.config.get('workspace', 'run_dir', default='')
        servers = get_server_list(run_dir)
        cache = get_node_status_cache()
        
        # 收集所有服务器
        all_servers = []
        for category_servers in servers.values():
            all_servers.extend(category_servers)
        
        # 如果缓存没有这些服务器的数据，先批量查询
        if all_servers and not cache.has_local_nodes(all_servers):
            cookie = self.config.get('server', 'cookie', default='ddxq2-node')
            results = check_nodes_status(all_servers, cookie, erl_path=self.config.get('erlang', 'r25_path', default=''))
            cache.batch_set(results)
            cache.set_initialized(True)
        
        for category, category_servers in servers.items():
            for server in sorted(category_servers):
                # 从缓存读取状态
                cached_status = cache.get(server)
                if cached_status is True:
                    status_icon = "🟢"
                elif cached_status is False:
                    status_icon = "⚪"
                else:
                    status_icon = "⚪"  # 未缓存
                
                item = QListWidgetItem(f"{status_icon} {server}")
                item.setData(Qt.ItemDataRole.UserRole, server)
                if cached_status is True:
                    item.setForeground(QColor("#25c889"))
                self.local_list.addItem(item)
        
        local_layout.addWidget(self.local_list)
        
        self.server_tabs.addTab(local_widget, "本地服务器")
        
        # === 远程服务器选项卡 ===
        remote_widget = QWidget()
        remote_layout = QVBoxLayout(remote_widget)
        remote_layout.setSpacing(8)
        remote_layout.setContentsMargins(10, 10, 10, 10)
        
        load_row = QHBoxLayout()
        self.load_remote_btn = QPushButton("从登录服加载")
        apply_button_style(self.load_remote_btn, "outline", compact=True)
        self.load_remote_btn.clicked.connect(self._load_remote_servers_dialog)
        load_row.addWidget(self.load_remote_btn)
        
        self.remote_load_status = QLabel("")
        self.remote_load_status.setStyleSheet("color: #aab4c3; font-size: 11px;")
        load_row.addWidget(self.remote_load_status)
        load_row.addStretch()
        
        remote_layout.addLayout(load_row)
        
        # 保存远程服务器数据
        self.dialog_remote_servers = {}
        
        # 搜索框
        search_layout = QHBoxLayout()
        search_label = QLabel("搜索:")
        search_layout.addWidget(search_label)
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("输入服务器ID、名称或节点过滤...")
        self.search_input.textChanged.connect(self._filter_remote_servers)
        search_layout.addWidget(self.search_input)
        remote_layout.addLayout(search_layout)
        
        self.remote_list = QTableWidget(0, 3)
        self.remote_list.setHorizontalHeaderLabels(["服务器ID", "服务器名称", "服务器节点"])
        self.remote_list.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents)
        self.remote_list.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
        self.remote_list.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Stretch)
        self.remote_list.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.remote_list.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
        self.remote_list.setAlternatingRowColors(False)
        self.remote_list.setSortingEnabled(True)
        self.remote_list.itemDoubleClicked.connect(self._on_remote_server_double_clicked)
        self.remote_list.itemClicked.connect(self._on_remote_server_clicked)
        remote_layout.addWidget(self.remote_list)
        
        
        self.server_tabs.addTab(remote_widget, "远程服务器")
        
        # 根据 initial_tab 设置初始选项卡
        if self.initial_tab == 'remote':
            self.server_tabs.setCurrentIndex(1)
        
        layout.addWidget(self.server_tabs)
        
        # 状态检查按钮和标签
        status_layout = QHBoxLayout()
        
        self.check_status_btn = QPushButton("检查节点状态")
        apply_button_style(self.check_status_btn, "success")
        self.check_status_btn.clicked.connect(self._check_node_status)
        status_layout.addWidget(self.check_status_btn)
        
        self.status_label = QLabel("")
        self.status_label.setStyleSheet("font-size: 12px;")
        status_layout.addWidget(self.status_label)
        status_layout.addStretch()
        
        layout.addLayout(status_layout)
        
        # 按钮
        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(10)
        
        self.connect_btn = QPushButton("连接")
        apply_button_style(self.connect_btn, "primary")
        self.connect_btn.clicked.connect(self.accept)
        btn_layout.addWidget(self.connect_btn)
        
        cancel_btn = QPushButton("取消")
        apply_button_style(cancel_btn, "neutral")
        cancel_btn.clicked.connect(self.reject)
        btn_layout.addWidget(cancel_btn)
        
        layout.addLayout(btn_layout)
    
    def _check_node_status(self):
        """检查节点是否在线"""
        from services.commands import check_node_status
        
        node_name = self.node_input.text().strip()
        if not node_name:
            self.status_label.setText("⚠️ 请先输入节点名称")
            self.status_label.setStyleSheet("color: #f5b04b;")
            return
        
        target_ip = self.ip_input.text().strip() if self.ip_input.text().strip() else None
        # 使用对话框中用户输入的 cookie，而不是配置文件中的
        cookie = self.cookie_input.text().strip()
        if not cookie:
            cookie = self.config.get('server', 'cookie', default='ddxq2-node')
        
        self.check_status_btn.setEnabled(False)
        self.status_label.setText("正在检查...")
        self.status_label.setStyleSheet("color: #aab4c3;")
        QApplication.processEvents()
        
        is_online = check_node_status(node_name, cookie, target_ip, erl_path=self.config.get('erlang', 'r25_path', default=''))
        
        # 更新全局缓存
        cache = get_node_status_cache()
        cache.set(node_name, is_online)
        
        if is_online:
            self.status_label.setText("🟢 节点在线")
            self.status_label.setStyleSheet("color: #25c889;")
            self.connect_btn.setEnabled(True)
        else:
            self.status_label.setText("⚪ 节点离线或不可达")
            self.status_label.setStyleSheet("color: #ff5c6a;")
            self.connect_btn.setEnabled(False)
        
        self.check_status_btn.setEnabled(True)
    
    def _on_local_server_clicked(self, item):
        """点击本地服务器时填充节点名称"""
        server = item.data(Qt.ItemDataRole.UserRole)
        if server:
            self.node_input.setText(server)
            self.ip_input.setText(get_local_ip())
            # 重置状态
            self.status_label.setText("")
            self.connect_btn.setEnabled(True)  # 本地服务器默认允许连接
    
    def _on_local_server_double_clicked(self, item):
        """双击本地服务器时直接连接"""
        self._on_local_server_clicked(item)
        self.accept()
    
    def _dialog_remote_node_at_row(self, row: int):
        if row < 0:
            return None
        it = self.remote_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 _dialog_remote_node_is_online(self, server_node: str) -> bool:
        """判断远程连接弹窗中的节点是否在线。"""
        data = self.dialog_remote_servers.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_dialog(self):
        """从登录服 RPC 加载远程服务器列表"""
        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.config.get('erlang', 'r25_path', default='') or '').strip() or None
        
        if not login_node:
            self.remote_load_status.setText("请先在项目设置中配置登录服节点")
            self.remote_load_status.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            return
        
        self.load_remote_btn.setEnabled(False)
        self.remote_load_status.setText("正在检测登录服节点...")
        self.remote_load_status.setStyleSheet("color: #f5b04b; font-size: 11px;")
        QApplication.processEvents()
        
        if not check_node_status(login_node, cookie, erl_path=erl_path):
            self.remote_load_status.setText("登录服节点不可达")
            self.remote_load_status.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            QMessageBox.warning(
                self,
                "无法连接登录服",
                "无法连通登录服节点（net_adm:ping 未返回 pong）。\n\n"
                "请检查：\n"
                "· 登录服节点名称是否正确（形如 name@ip）\n"
                "· Cookie 是否与登录服 erlang.cookie 一致\n"
                "· 项目设置中的 Erlang 路径、网络与防火墙",
            )
            self.load_remote_btn.setEnabled(True)
            return
        
        self.remote_load_status.setText("正在从登录服加载列表...")
        QApplication.processEvents()
        
        try:
            servers_list = query_remote_servers_from_login_rpc(
                login_node, cookie, erl_path=erl_path
            )
            servers_list = sorted(servers_list, key=lambda s: _server_id_sort_key(s.get('server_id')))
            
            self.remote_list.setSortingEnabled(False)
            self.remote_list.setRowCount(0)
            self.dialog_remote_servers = {}
            self.remote_servers_data = servers_list
            
            for server in 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_list.rowCount()
                self.remote_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_list.setItem(row, 0, c0)
                self.remote_list.setItem(row, 1, c1)
                self.remote_list.setItem(row, 2, c2)
                
                self.dialog_remote_servers[server_node] = {
                    'item': c0,
                    'server_id': server_id,
                    'server': server,
                }

            self.remote_list.setSortingEnabled(True)
            self.remote_list.sortItems(0, Qt.SortOrder.AscendingOrder)
            
            self.remote_load_status.setText(f"已加载 {len(servers_list)} 个")
            self.remote_load_status.setStyleSheet("color: #25c889; font-size: 11px;")
            self.search_input.clear()
            
        except Exception as e:
            self.remote_load_status.setText("加载失败")
            self.remote_load_status.setStyleSheet("color: #ff5c6a; font-size: 11px;")
            QMessageBox.warning(self, "从登录服加载失败", str(e))
        finally:
            self.load_remote_btn.setEnabled(True)
    
    def _display_remote_servers(self):
        """显示远程服务器列表"""
        self.remote_list.setSortingEnabled(False)
        self.remote_list.setRowCount(0)
        self.dialog_remote_servers = {}
        for server in sorted(self.remote_servers_data, key=lambda s: _server_id_sort_key(s.get('server_id'))):
            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_list.rowCount()
            self.remote_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_list.setItem(row, 0, c0)
            self.remote_list.setItem(row, 1, c1)
            self.remote_list.setItem(row, 2, c2)
            
            self.dialog_remote_servers[server_node] = {
                'item': c0,
                'server_id': server_id,
                'server': server,
            }
        
        self.remote_list.setSortingEnabled(True)
        self.remote_list.sortItems(0, Qt.SortOrder.AscendingOrder)
        self.search_input.clear()
    
    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_list.setSortingEnabled(False)
        self.remote_list.setRowCount(0)
        self.dialog_remote_servers = {}
        
        for server in sorted(self.remote_servers_data, key=lambda s: _server_id_sort_key(s.get('server_id'))):
            server_id = str(server['server_id'])
            server_name = server.get('server_name', '') or ''
            server_node = server['server_node']
            
            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_list.rowCount()
            self.remote_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_list.setItem(row, 0, c0)
            self.remote_list.setItem(row, 1, c1)
            self.remote_list.setItem(row, 2, c2)
            
            self.dialog_remote_servers[server_node] = {
                'item': c0,
                'server_id': server_id,
                'server': server,
            }

        self.remote_list.setSortingEnabled(True)
        self.remote_list.sortItems(0, Qt.SortOrder.AscendingOrder)
    
    def _on_remote_server_clicked(self, item):
        """点击远程服务器时填充节点名称"""
        server_node = self._dialog_remote_node_at_row(item.row())
        if server_node:
            self.node_input.setText(server_node)
            # 从节点名称中提取IP并显示
            if '@' in server_node:
                ip = server_node.split('@')[1]
                self.ip_input.setText(ip)
            else:
                self.ip_input.clear()
    
    def _on_remote_server_double_clicked(self, item):
        """双击在线远程服务器时直接连接，离线节点不做任何操作。"""
        server_node = self._dialog_remote_node_at_row(item.row())
        if not server_node or not self._dialog_remote_node_is_online(server_node):
            return

        self.node_input.setText(server_node)
        # 从节点名称中提取IP并显示
        if '@' in server_node:
            ip = server_node.split('@')[1]
            self.ip_input.setText(ip)
        self.accept()
    
    def accept(self):
        node = self.node_input.text().strip()
        if not node:
            QMessageBox.warning(self, "警告", "请输入节点名称")
            return
        
        target_ip = self.ip_input.text().strip() if self.ip_input.text().strip() else None
        cookie = self.cookie_input.text().strip()
        
        # 检查节点是否在线
        from services.commands import check_node_status
        
        self.connect_btn.setEnabled(False)
        self.status_label.setText("正在检查节点状态...")
        self.status_label.setStyleSheet("color: #f5b04b;")
        QApplication.processEvents()
        
        # 输出检查状态到控制台
        if self.console:
            self.console.append_output(f"[远程连接] 正在检查节点状态: {node}\n")
        
        is_online = check_node_status(node, cookie, target_ip, erl_path=self.config.get('erlang', 'r25_path', default=''))
        
        # 更新全局缓存
        cache = get_node_status_cache()
        cache.set(node, is_online)
        
        if not is_online:
            self.status_label.setText("⚪ 节点离线或不可达")
            self.status_label.setStyleSheet("color: #ff5c6a;")
            self.connect_btn.setEnabled(True)
            if self.console:
                self.console.append_output(f"[远程连接] 节点离线或不可达: {node}\n")
            QMessageBox.warning(self, "连接失败", f"节点 {node} 离线或不可达，无法连接")
            return
        
        self.status_label.setText("🟢 节点在线，正在连接...")
        self.status_label.setStyleSheet("color: #25c889;")
        
        # 输出连接命令到控制台
        if self.console:
            cmd = build_remsh_command(node, cookie, target_ip, erl_path=self.config.get('erlang', 'r25_path', default=''))
            # 确定显示的目标节点名
            if '@' in node:
                target_node = node
            else:
                target_node = f"{node}@{target_ip}" if target_ip else f"{node}@{get_local_ip()}"
            self.console.append_output(f"[远程连接] 节点在线: {target_node}\n")
            self.console.append_output(f"[命令] {cmd}\n")
        
        self.node_name = node
        self.target_ip = target_ip
        self.cookie = cookie
        super().accept()
