# -*- 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 KvConfigEditDialog(QDialog):
    """kv.config 编辑对话框"""

    BOOL_CONFIG_KEYS = {'auto_reload', 'is_develop', 'is_inner', 'gm_auth'}
    
    def __init__(self, kv_config_path: str, server_type: str, server_name: str, 
                 server_root: str, console, parent=None):
        super().__init__(parent)
        self.kv_config_path = kv_config_path
        self.server_type = server_type
        self.server_name = server_name
        self.server_root = server_root
        self.console = console
        self.config_widgets = {}  # key -> editor widget
        # 从模板文件动态读取可配置的参数列表
        self.allowed_keys = get_template_config_keys(server_root, server_type)
        
        self.setWindowTitle(f"编辑配置 - {server_name}")
        self.setMinimumSize(600, 500)
        self.init_ui()
        self.load_config()
    
    def init_ui(self):
        layout = QVBoxLayout(self)
        layout.setSpacing(10)
        layout.setContentsMargins(15, 15, 15, 15)
        
        # 标题
        title_label = QLabel(f"服务器: {self.server_name} ({get_server_type_name(self.server_type)})")
        title_label.setStyleSheet("font-size: 14px; font-weight: bold; color: #25c889;")
        layout.addWidget(title_label)
        
        # 提示
        hint_label = QLabel("修改配置后点击保存，然后重新启动服务器生效")
        hint_label.setStyleSheet("color: #aab4c3; font-size: 11px;")
        layout.addWidget(hint_label)
        
        # 滚动区域
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll.setStyleSheet("QScrollArea { border: none; }")
        
        scroll_widget = QWidget()
        scroll_layout = QVBoxLayout(scroll_widget)
        scroll_layout.setSpacing(5)
        
        # 当前配置区域
        current_group = QGroupBox("当前配置")
        current_layout = QFormLayout(current_group)
        current_layout.setSpacing(8)
        current_layout.setContentsMargins(15, 20, 15, 15)
        
        self.config_form = current_layout
        scroll_layout.addWidget(current_group)
        
        # 添加新配置区域
        add_group = QGroupBox("添加配置项")
        add_layout = QHBoxLayout(add_group)
        add_layout.setSpacing(10)
        add_layout.setContentsMargins(15, 20, 15, 15)
        
        self.new_key_combo = NoWheelComboBox()
        self.new_key_combo.setMinimumWidth(200)
        add_layout.addWidget(QLabel("选择配置:"))
        add_layout.addWidget(self.new_key_combo, 1)
        
        add_btn = QPushButton("添加")
        add_btn.clicked.connect(self.add_config_item)
        apply_button_style(add_btn, "outline")
        set_button_icon(add_btn, "plus", "#4f8cff", 16)
        add_layout.addWidget(add_btn)
        
        scroll_layout.addWidget(add_group)
        scroll_layout.addStretch()
        
        scroll.setWidget(scroll_widget)
        layout.addWidget(scroll, 1)
        
        # 按钮区域
        btn_layout = QHBoxLayout()
        btn_layout.setSpacing(10)
        
        save_btn = QPushButton("保存配置")
        save_btn.setMinimumHeight(40)
        save_btn.clicked.connect(self.save_config)
        apply_button_style(save_btn, "primary")
        set_button_icon(save_btn, "save", "#242932", 16)
        btn_layout.addWidget(save_btn)
        
        cancel_btn = QPushButton("关闭")
        cancel_btn.setMinimumHeight(40)
        cancel_btn.clicked.connect(self.reject)
        apply_button_style(cancel_btn, "neutral")
        set_button_icon(cancel_btn, "external", "#aab4c3", 16)
        btn_layout.addWidget(cancel_btn)
        
        layout.addLayout(btn_layout)
    
    def load_config(self):
        """加载当前 kv.config 配置"""
        config = read_config_file(self.kv_config_path)

        if 'auto_reload' not in config:
            config['auto_reload'] = self._get_smart_default_value('auto_reload')
        
        # 清空现有表单
        while self.config_form.rowCount() > 0:
            self.config_form.removeRow(0)
        self.config_widgets.clear()
        
        # 添加现有配置项
        for key, value in config.items():
            self._add_config_row(key, value)
        
        # 更新可添加的配置项下拉框
        self._update_add_combo(config)
    
    def _add_config_row(self, key: str, value: str):
        """添加一行配置"""
        # 获取必须的配置项
        required_keys = get_required_keys(self.server_type, self.server_root)
        is_required = key in required_keys
        
        label_text = key
        if key in self.allowed_keys:
            label_text = self.allowed_keys[key]
        
        # 必须项显示标记
        if is_required:
            label_text = "* " + label_text
        
        row_widget = QWidget()
        row_layout = QHBoxLayout(row_widget)
        row_layout.setContentsMargins(0, 0, 0, 0)
        row_layout.setSpacing(5)
        
        editor = self._create_config_editor(key, value)
        row_layout.addWidget(editor, 1)
        
        # 删除按钮（必须项不显示删除按钮）
        if not is_required:
            del_btn = QPushButton("×")
            del_btn.setFixedSize(25, 25)
            apply_button_style(del_btn, "danger", compact=True)
            set_button_icon(del_btn, "trash", "#ff5c6a", 14)
            del_btn.clicked.connect(lambda checked, k=key: self._remove_config_row(k))
            row_layout.addWidget(del_btn)
        else:
            # 添加占位符保持布局一致
            placeholder = QWidget()
            placeholder.setFixedSize(25, 25)
            row_layout.addWidget(placeholder)
        
        self.config_form.addRow(label_text + ":", row_widget)
        self.config_widgets[key] = editor

    def _create_config_editor(self, key: str, value: str) -> QWidget:
        """根据配置项类型创建编辑控件"""
        if key in self.BOOL_CONFIG_KEYS:
            checkbox = QCheckBox("启用")
            checkbox.setChecked(str(value).strip().lower() == 'true')
            checkbox.setMinimumHeight(30)
            return checkbox

        edit = QLineEdit(value)
        edit.setMinimumWidth(300)
        return edit

    def _get_widget_value(self, key: str, widget: QWidget) -> str:
        """读取编辑控件的当前值"""
        if key in self.BOOL_CONFIG_KEYS and isinstance(widget, QCheckBox):
            return 'true' if widget.isChecked() else 'false'
        if isinstance(widget, QLineEdit):
            return widget.text()
        return ''
    
    def _remove_config_row(self, key: str):
        """删除配置行"""
        if key in self.config_widgets:
            # 找到并移除行
            for i in range(self.config_form.rowCount()):
                label_item = self.config_form.itemAt(i, QFormLayout.ItemRole.LabelRole)
                if label_item and label_item.widget():
                    label_text = label_item.widget().text()
                    # 匹配 "key (xxx):" 或 "* key (xxx):" 格式
                    if label_text.startswith(key + " ") or label_text.startswith("* " + key + " ") or label_text == key + ":":
                        self.config_form.removeRow(i)
                        break
            del self.config_widgets[key]
            self._update_add_combo({k: self._get_widget_value(k, w) for k, w in self.config_widgets.items()})
    
    def _update_add_combo(self, current_config: dict):
        """更新可添加的配置项下拉框"""
        self.new_key_combo.clear()
        
        # 只显示允许的、当前不存在的配置项
        for key, desc in sorted(self.allowed_keys.items(), key=lambda x: x[1]):
            if key not in current_config:
                self.new_key_combo.addItem(f"{desc} ({key})", key)
    
    def add_config_item(self):
        """添加新配置项"""
        key = self.new_key_combo.currentData()
        if not key:
            QMessageBox.warning(self, "提示", "请选择要添加的配置项")
            return
        
        if key in self.config_widgets:
            QMessageBox.warning(self, "提示", f"配置项 {key} 已存在")
            return
        
        # 获取默认值
        default_value = self._get_smart_default_value(key)
        
        self._add_config_row(key, default_value)
        self._update_add_combo({k: self._get_widget_value(k, w) for k, w in self.config_widgets.items()})
    
    def _get_smart_default_value(self, key: str) -> str:
        """获取智能默认值，根据配置项类型和服务器信息生成"""
        # 特殊配置项的智能默认值
        if key == 'log_dir':
            # 日志目录使用完整路径格式 run/{server_dir}/log
            return f'run/{self.server_name}/log'

        if key == 'role_log':
            # 角色日志目录，默认与 log_dir 同路径
            return f'run/{self.server_name}/log'

        if key == 'auto_reload':
            merged = read_merged_config(self.server_root)
            return merged.get('auto_reload', 'true')
        
        if key == 'ip' or key == 'game_host':
            return get_local_ip()
        if key == 'login_host':
            merged = read_merged_config(self.server_root)
            return node_host_only(merged.get('login_host')) or get_local_ip()
        
        if key == 'server_name':
            # 服务器名称从服务器目录名生成
            # 格式: prefix_type_sID -> prefix_ID
            parts = self.server_name.split('_')
            if len(parts) >= 3 and parts[-1].startswith('s'):
                try:
                    server_id = parts[-1][1:]  # 去掉 's' 前缀
                    prefix = parts[0]
                    return f'{prefix}_{server_id}'
                except:
                    pass
            return self.server_name
        
        if key == 'tcp_port':
            # TCP 端口根据 server_id 计算
            parts = self.server_name.split('_s')
            if len(parts) >= 2:
                try:
                    server_id = int(parts[-1])
                    return str(18000 + server_id)
                except:
                    pass
            return '18001'
        
        if key == 'http_port':
            # HTTP 端口根据 server_id 计算
            parts = self.server_name.split('_s')
            if len(parts) >= 2:
                try:
                    server_id = int(parts[-1])
                    return str(19000 + server_id)
                except:
                    pass
            return '19001'
        
        if key == 'game_tcp_port':
            # 游戏服 TCP 端口
            parts = self.server_name.split('_s')
            if len(parts) >= 2:
                try:
                    server_id = int(parts[-1])
                    return str(18000 + server_id)
                except:
                    pass
            return '18001'
        
        # 其他配置项从合并配置读取（kv.config > user.config > project.config > default.config）
        merged = read_merged_config(self.server_root)
        return merged.get(key, '')
    
    def save_config(self):
        """保存配置并自动重新生成 sys.config"""
        config = {}
        for key, widget in self.config_widgets.items():
            config[key] = self._get_widget_value(key, widget)
        
        try:
            write_config_file(self.kv_config_path, config)
            self.console.append_output(f"[成功] 配置已保存: {self.kv_config_path}\n")
            
            # 自动重新生成 sys.config
            merged_config = generate_start_config(self.server_root, self.server_name)
            if merged_config:
                self.console.append_output(f"[成功] 已重新生成: {merged_config.get('_config_file', '')}\n")
                QMessageBox.information(self, "成功", "配置已保存并重新生成 sys.config！\n\n重新启动服务器后生效。")
            else:
                self.console.append_output(f"[警告] 重新生成 sys.config 失败\n")
                QMessageBox.warning(self, "警告", "配置已保存，但重新生成 sys.config 失败，请检查配置。")
        except Exception as e:
            self.console.append_output(f"[错误] 保存配置失败: {str(e)}\n")
            QMessageBox.critical(self, "错误", f"保存配置失败: {str(e)}")
