# -*- coding: utf-8 -*-
"""数据库查看器"""

from PySide6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QSplitter,
    QGroupBox, QLabel, QPushButton, QLineEdit, QPlainTextEdit,
    QTableWidget, QTableWidgetItem, QTreeWidget, QTreeWidgetItem,
    QHeaderView, QComboBox, QTabWidget, QMessageBox, QFrame
)
from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QFont

from ..workers.db_worker import DBWorker
from ..utils.config_helper import ConfigHelper


# 常用查询模板
QUERY_TEMPLATES = {
    "ODS 行数统计": """
SELECT 
    table_name,
    (xpath('/row/cnt/text()', 
        query_to_xml('SELECT COUNT(*) AS cnt FROM ' || table_schema || '.' || table_name, false, false, ''))
    )[1]::text::bigint AS row_count
FROM information_schema.tables
WHERE table_schema = 'billiards_ods'
ORDER BY table_name;
""",
    "DWD 行数统计": """
SELECT 
    table_name,
    (xpath('/row/cnt/text()', 
        query_to_xml('SELECT COUNT(*) AS cnt FROM ' || table_schema || '.' || table_name, false, false, ''))
    )[1]::text::bigint AS row_count
FROM information_schema.tables
WHERE table_schema = 'billiards_dwd'
ORDER BY table_name;
""",
    "ETL 游标状态": """
SELECT 
    task_code,
    last_start,
    last_end,
    last_run_id,
    updated_at
FROM etl_admin.etl_cursor
ORDER BY task_code;
""",
    "最近运行记录": """
SELECT 
    run_id,
    task_code,
    status,
    started_at,
    finished_at,
    EXTRACT(EPOCH FROM (finished_at - started_at))::int AS duration_sec,
    rows_affected
FROM etl_admin.run_tracker
ORDER BY started_at DESC
LIMIT 50;
""",
    "ODS 最新入库时间": """
SELECT 
    'payment_transactions' AS table_name, MAX(fetched_at) AS max_fetched_at FROM billiards_ods.payment_transactions
UNION ALL
SELECT 'member_profiles', MAX(fetched_at) FROM billiards_ods.member_profiles
UNION ALL
SELECT 'settlement_records', MAX(fetched_at) FROM billiards_ods.settlement_records
UNION ALL
SELECT 'recharge_settlements', MAX(fetched_at) FROM billiards_ods.recharge_settlements
ORDER BY table_name;
""",
}


class DBViewer(QWidget):
    """数据库查看器"""
    
    # 信号
    connection_changed = Signal(bool, str)  # 连接状态变化
    
    def __init__(self, parent=None):
        super().__init__(parent)
        self.config_helper = ConfigHelper()
        self.db_worker = DBWorker(self)
        self._connected = False
        
        self._init_ui()
        self._connect_signals()
        self._load_dsn_from_env()
    
    def _init_ui(self):
        """初始化界面"""
        layout = QVBoxLayout(self)
        layout.setContentsMargins(16, 16, 16, 16)
        layout.setSpacing(16)
        
        # 标题
        title = QLabel("数据库查看器")
        title.setProperty("heading", True)
        layout.addWidget(title)
        
        # 连接配置
        conn_group = QGroupBox("数据库连接")
        conn_layout = QHBoxLayout(conn_group)
        
        conn_layout.addWidget(QLabel("DSN:"))
        self.dsn_edit = QLineEdit()
        self.dsn_edit.setPlaceholderText("postgresql://user:password@host:5432/dbname")
        self.dsn_edit.setEchoMode(QLineEdit.Password)
        conn_layout.addWidget(self.dsn_edit, 1)
        
        self.show_dsn_btn = QPushButton("显示")
        self.show_dsn_btn.setProperty("secondary", True)
        self.show_dsn_btn.setCheckable(True)
        self.show_dsn_btn.setFixedWidth(60)
        conn_layout.addWidget(self.show_dsn_btn)
        
        self.connect_btn = QPushButton("连接")
        self.connect_btn.setFixedWidth(80)
        conn_layout.addWidget(self.connect_btn)
        
        self.disconnect_btn = QPushButton("断开")
        self.disconnect_btn.setProperty("secondary", True)
        self.disconnect_btn.setFixedWidth(80)
        self.disconnect_btn.setEnabled(False)
        conn_layout.addWidget(self.disconnect_btn)
        
        layout.addWidget(conn_group)
        
        # 主分割器
        main_splitter = QSplitter(Qt.Horizontal)
        layout.addWidget(main_splitter, 1)
        
        # 左侧：表浏览器
        left_widget = self._create_table_browser()
        main_splitter.addWidget(left_widget)
        
        # 右侧：查询和结果
        right_widget = self._create_query_area()
        main_splitter.addWidget(right_widget)
        
        # 设置分割比例
        main_splitter.setSizes([300, 700])
    
    def _create_table_browser(self) -> QWidget:
        """创建表浏览器"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(0, 0, 8, 0)
        
        # 标题和刷新按钮
        header_layout = QHBoxLayout()
        header_layout.addWidget(QLabel("表结构"))
        self.refresh_tables_btn = QPushButton("刷新")
        self.refresh_tables_btn.setProperty("secondary", True)
        self.refresh_tables_btn.setEnabled(False)
        header_layout.addWidget(self.refresh_tables_btn)
        layout.addLayout(header_layout)
        
        # 表树形视图
        self.table_tree = QTreeWidget()
        self.table_tree.setHeaderLabels(["名称", "行数", "最后更新"])
        self.table_tree.header().setSectionResizeMode(0, QHeaderView.Stretch)
        self.table_tree.setColumnWidth(1, 80)
        self.table_tree.setColumnWidth(2, 130)
        layout.addWidget(self.table_tree, 1)
        
        return widget
    
    def _create_query_area(self) -> QWidget:
        """创建查询区域"""
        widget = QWidget()
        layout = QVBoxLayout(widget)
        layout.setContentsMargins(8, 0, 0, 0)
        
        # 查询输入区
        query_group = QGroupBox("SQL 查询")
        query_layout = QVBoxLayout(query_group)
        
        # 模板选择
        template_layout = QHBoxLayout()
        template_layout.addWidget(QLabel("常用查询:"))
        self.template_combo = QComboBox()
        self.template_combo.addItem("-- 选择模板 --")
        for name in QUERY_TEMPLATES.keys():
            self.template_combo.addItem(name)
        template_layout.addWidget(self.template_combo, 1)
        query_layout.addLayout(template_layout)
        
        # SQL 编辑器
        self.sql_editor = QPlainTextEdit()
        self.sql_editor.setObjectName("sqlEditor")
        self.sql_editor.setPlaceholderText("输入 SQL 查询语句...")
        self.sql_editor.setFont(QFont("Consolas", 11))
        self.sql_editor.setMaximumHeight(150)
        query_layout.addWidget(self.sql_editor)
        
        # 执行按钮
        exec_layout = QHBoxLayout()
        exec_layout.addStretch()
        
        self.exec_btn = QPushButton("执行查询 (Ctrl+Enter)")
        self.exec_btn.setEnabled(False)
        exec_layout.addWidget(self.exec_btn)
        
        query_layout.addLayout(exec_layout)
        layout.addWidget(query_group)
        
        # 结果区域
        result_group = QGroupBox("查询结果")
        result_layout = QVBoxLayout(result_group)
        
        # 结果表格
        self.result_table = QTableWidget()
        self.result_table.setAlternatingRowColors(True)
        self.result_table.horizontalHeader().setStretchLastSection(True)
        result_layout.addWidget(self.result_table, 1)
        
        # 结果统计
        self.result_label = QLabel("就绪")
        self.result_label.setProperty("subheading", True)
        result_layout.addWidget(self.result_label)
        
        layout.addWidget(result_group, 1)
        
        return widget
    
    def _connect_signals(self):
        """连接信号"""
        # 连接按钮
        self.show_dsn_btn.toggled.connect(self._toggle_dsn_visibility)
        self.connect_btn.clicked.connect(self._connect_db)
        self.disconnect_btn.clicked.connect(self._disconnect_db)
        self.refresh_tables_btn.clicked.connect(self._refresh_tables)
        
        # 模板选择
        self.template_combo.currentIndexChanged.connect(self._on_template_selected)
        
        # 执行查询
        self.exec_btn.clicked.connect(self._execute_query)
        
        # 表双击
        self.table_tree.itemDoubleClicked.connect(self._on_table_double_clicked)
        
        # 工作线程信号
        self.db_worker.connection_status.connect(self._on_connection_status)
        self.db_worker.tables_loaded.connect(self._on_tables_loaded)
        self.db_worker.query_finished.connect(self._on_query_finished)
        self.db_worker.query_error.connect(self._on_query_error)
    
    def _load_dsn_from_env(self):
        """从环境变量加载 DSN"""
        env_vars = self.config_helper.load_env()
        dsn = env_vars.get("PG_DSN", "")
        if dsn:
            self.dsn_edit.setText(dsn)
    
    def _toggle_dsn_visibility(self, checked: bool):
        """切换 DSN 可见性"""
        self.dsn_edit.setEchoMode(
            QLineEdit.Normal if checked else QLineEdit.Password
        )
        self.show_dsn_btn.setText("隐藏" if checked else "显示")
    
    def _connect_db(self):
        """连接数据库"""
        dsn = self.dsn_edit.text().strip()
        if not dsn:
            QMessageBox.warning(self, "提示", "请输入数据库连接字符串")
            return
        
        self.connect_btn.setEnabled(False)
        self.connect_btn.setText("连接中...")
        self.db_worker.connect_db(dsn)
    
    def _disconnect_db(self):
        """断开数据库连接"""
        self.db_worker.disconnect_db()
    
    def _refresh_tables(self):
        """刷新表列表"""
        self.db_worker.load_tables()
    
    def _on_connection_status(self, connected: bool, message: str):
        """处理连接状态变化"""
        self._connected = connected
        self.connect_btn.setEnabled(not connected)
        self.connect_btn.setText("连接")
        self.disconnect_btn.setEnabled(connected)
        self.refresh_tables_btn.setEnabled(connected)
        self.exec_btn.setEnabled(connected)
        
        self.connection_changed.emit(connected, message)
        
        if connected:
            # 自动加载表列表
            self._refresh_tables()
    
    def _on_tables_loaded(self, tables_dict: dict):
        """处理表列表加载完成"""
        self.table_tree.clear()
        
        for schema, tables in tables_dict.items():
            schema_item = QTreeWidgetItem([schema, "", ""])
            schema_item.setExpanded(True)
            
            for table_name, row_count, updated_at in tables:
                table_item = QTreeWidgetItem([table_name, str(row_count), updated_at])
                table_item.setData(0, Qt.UserRole, f"{schema}.{table_name}")
                schema_item.addChild(table_item)
            
            self.table_tree.addTopLevelItem(schema_item)
    
    def _on_template_selected(self, index: int):
        """模板选择变化"""
        if index <= 0:
            return
        
        template_name = self.template_combo.currentText()
        if template_name in QUERY_TEMPLATES:
            self.sql_editor.setPlainText(QUERY_TEMPLATES[template_name].strip())
        
        # 重置选择
        self.template_combo.setCurrentIndex(0)
    
    def _on_table_double_clicked(self, item: QTreeWidgetItem, column: int):
        """表双击事件"""
        full_name = item.data(0, Qt.UserRole)
        if full_name:
            # 生成预览查询
            sql = f"SELECT * FROM {full_name} LIMIT 100;"
            self.sql_editor.setPlainText(sql)
            self._execute_query()
    
    def _execute_query(self):
        """执行查询"""
        sql = self.sql_editor.toPlainText().strip()
        if not sql:
            QMessageBox.warning(self, "提示", "请输入 SQL 语句")
            return
        
        self.exec_btn.setEnabled(False)
        self.exec_btn.setText("执行中...")
        self.result_label.setText("正在查询...")
        
        self.db_worker.execute_query(sql)
    
    def _on_query_finished(self, columns: list, rows: list):
        """查询完成"""
        self.exec_btn.setEnabled(True)
        self.exec_btn.setText("执行查询 (Ctrl+Enter)")
        
        # 更新结果表格
        self.result_table.clear()
        self.result_table.setColumnCount(len(columns))
        self.result_table.setRowCount(len(rows))
        self.result_table.setHorizontalHeaderLabels(columns)
        
        for row_idx, row_data in enumerate(rows):
            for col_idx, col_name in enumerate(columns):
                value = row_data.get(col_name, "")
                item = QTableWidgetItem(str(value) if value is not None else "NULL")
                if value is None:
                    item.setForeground(Qt.gray)
                self.result_table.setItem(row_idx, col_idx, item)
        
        # 更新统计
        self.result_label.setText(f"返回 {len(rows)} 行, {len(columns)} 列")
    
    def _on_query_error(self, error: str):
        """查询错误"""
        self.exec_btn.setEnabled(True)
        self.exec_btn.setText("执行查询 (Ctrl+Enter)")
        self.result_label.setText(f"错误: {error}")
        QMessageBox.critical(self, "查询错误", error)
    
    def close_connection(self):
        """关闭连接"""
        if self._connected:
            self.db_worker.disconnect_db()
    
    def keyPressEvent(self, event):
        """键盘事件"""
        # Ctrl+Enter 执行查询
        if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_Return:
            if self._connected:
                self._execute_query()
        else:
            super().keyPressEvent(event)
