"""
PySide6 GUI界面模块
"""
from PySide6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
                                QPushButton, QSlider, QDialog, QFormLayout,
                                QLineEdit, QSpinBox, QMessageBox, QSystemTrayIcon,
                                QMenu, QTextEdit, QGroupBox, QDialogButtonBox, QCheckBox)
from PySide6.QtCore import Qt, QTimer, Signal, QPoint
from PySide6.QtGui import QFont, QColor, QPainter, QBrush, QPen, QIcon, QAction
from typing import Callable, Optional
from loguru import logger

from waveform_widget import WaveformWidget


class SentimentIndicator(QWidget):
    """情感指示灯组件"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.score = 50
        self.label_text = "中性"
        self.setMinimumSize(100, 100)

    def set_value(self, score: int, label: str = None):
        """设置数值和标签"""
        self.score = max(0, min(100, score))
        if label:
            self.label_text = label
        self.update()

    def paintEvent(self, event):
        """绘制指示灯"""
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)

        center = self.rect().center()
        radius = min(self.width(), self.height()) // 2 - 10

        # 根据分数确定颜色
        color = self._get_color(self.score)

        # 绘制外圈
        painter.setPen(QPen(QColor(100, 100, 100), 2))
        painter.setBrush(QBrush(QColor(30, 30, 30)))
        painter.drawEllipse(center, radius, radius)

        # 绘制内圈（渐变效果）
        gradient_color = QColor(color)
        painter.setPen(Qt.NoPen)
        painter.setBrush(QBrush(gradient_color))
        painter.drawEllipse(center, radius - 4, radius - 4)

        # 绘制发光效果
        for i in range(3, 0, -1):
            glow_color = QColor(color)
            glow_color.setAlpha(50 // i)
            painter.setBrush(QBrush(glow_color))
            painter.drawEllipse(center, radius - i * 5, radius - i * 5)

    def _get_color(self, score: int) -> QColor:
        """根据分数获取颜色"""
        # 45-55分区间：每1分一个颜色（从绿色到黄色渐变）
        if 45 <= score <= 55:
            # 在45-55分之间，每1分一个颜色
            ratio = (score - 45) / 10  # 0到1之间的比例
            # 从绿色(0, 200, 0)渐变到黄色(255, 255, 0)
            r = int(0 + 255 * ratio)
            g = 200 if ratio < 0.5 else int(200 + 55 * (ratio - 0.5) * 2)
            b = int(0 + 0 * ratio)
            return QColor(r, g, b)
        
        # 45分以下：每5分一个颜色（从深蓝到绿色渐变）
        elif score < 45:
            # 将分数映射到0-8的区间（0-40分，每5分一个级别）
            level = score // 5
            # 从深蓝色(0, 100, 255)渐变到绿色(0, 200, 0)
            ratio = level / 8  # 0-8对应0-40分
            r = int(0 + 0 * ratio)
            g = int(100 + 100 * ratio)
            b = int(255 - 255 * ratio)
            return QColor(r, g, b)
        
        # 55分以上：每5分一个颜色（从黄色到红色渐变）
        else:
            # 将分数映射到0-8的区间（60-100分，每5分一个级别）
            level = (score - 60) // 5
            level = max(0, min(8, level))  # 限制在0-8范围内
            # 从黄色(255, 255, 0)渐变到红色(255, 0, 0)
            ratio = level / 8
            r = 255
            g = int(255 - 255 * ratio)
            b = 0
            return QColor(r, g, b)

    def get_description(self, score: int) -> str:
        """获取描述文本"""
        if score < 20:
            return "极度看跌"
        elif score < 40:
            return "偏悲观"
        elif score < 60:
            return "中性"
        elif score < 80:
            return "偏乐观"
        else:
            return "极度看涨"


class ConfigDialog(QDialog):
    """配置对话框"""

    def __init__(self, config_manager, parent=None):
        super().__init__(parent)
        self.config_manager = config_manager
        self.setWindowTitle("配置")
        self.setMinimumWidth(400)
        self._init_ui()

    def _init_ui(self):
        layout = QFormLayout(self)

        # LLM API 配置
        llm_config = self.config_manager.llm_api_config

        self.base_url_edit = QLineEdit(llm_config.get('base_url', ''))
        self.api_key_edit = QLineEdit(llm_config.get('api_key', ''))
        self.api_key_edit.setEchoMode(QLineEdit.Password)
        self.model_edit = QLineEdit(llm_config.get('model', ''))
        self.timeout_spin = QSpinBox()
        self.timeout_spin.setRange(10, 300)
        self.timeout_spin.setValue(llm_config.get('timeout', 30))

        layout.addRow("API Base URL:", self.base_url_edit)
        layout.addRow("API Key:", self.api_key_edit)
        layout.addRow("Model:", self.model_edit)
        layout.addRow("Timeout (s):", self.timeout_spin)

        # 爬虫配置
        spider_config = self.config_manager.spider_config

        self.url_edit = QLineEdit(spider_config.get('target_url', ''))
        self.xpath_edit = QLineEdit(spider_config.get('xpath', ''))
        self.user_agent_edit = QLineEdit(spider_config.get('user_agent', ''))
        self.interval_spin = QSpinBox()
        self.interval_spin.setRange(10, 3600)
        self.interval_spin.setValue(spider_config.get('fetch_interval', 15))

        layout.addRow("目标URL:", self.url_edit)
        layout.addRow("XPath:", self.xpath_edit)
        layout.addRow("User Agent:", self.user_agent_edit)
        layout.addRow("刷新间隔(s):", self.interval_spin)

        # UI 配置
        ui_config = self.config_manager.ui_config

        self.opacity_slider = QSlider(Qt.Horizontal)
        self.opacity_slider.setRange(30, 100)
        self.opacity_slider.setValue(int(ui_config.get('opacity', 0.9) * 100))
        self.ontop_check = QCheckBox() if hasattr(self, 'QCheckBox') else None
        # 使用 QPushButton 替代 QCheckBox
        self.ontop_btn = QPushButton("置顶")
        self.ontop_btn.setCheckable(True)
        self.ontop_btn.setChecked(ui_config.get('is_on_top', True))

        layout.addRow("透明度:", self.opacity_slider)
        layout.addRow("窗口置顶:", self.ontop_btn)

        # 阈值配置
        thresholds = ui_config.get('thresholds', {})
        self.cold_spin = QSpinBox()
        self.cold_spin.setRange(0, 50)
        self.cold_spin.setValue(thresholds.get('cold', 30))
        self.warm_spin = QSpinBox()
        self.warm_spin.setRange(50, 100)
        self.warm_spin.setValue(thresholds.get('warm', 70))

        layout.addRow("寒冷阈值:", self.cold_spin)
        layout.addRow("温暖阈值:", self.warm_spin)

        # 按钮
        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        button_box.accepted.connect(self._save_config)
        button_box.rejected.connect(self.reject)
        layout.addRow(button_box)

    def _save_config(self):
        """保存配置"""
        # LLM API
        self.config_manager.update_llm_api(
            base_url=self.base_url_edit.text(),
            api_key=self.api_key_edit.text(),
            model=self.model_edit.text(),
            timeout=self.timeout_spin.value()
        )

        # 爬虫
        self.config_manager.update_spider(
            target_url=self.url_edit.text(),
            xpath=self.xpath_edit.text(),
            user_agent=self.user_agent_edit.text(),
            fetch_interval=self.interval_spin.value()
        )

        # UI
        self.config_manager.update_ui(
            opacity=self.opacity_slider.value() / 100.0,
            is_on_top=self.ontop_btn.isChecked(),
            cold_threshold=self.cold_spin.value(),
            warm_threshold=self.warm_spin.value()
        )

        self.accept()


class MainWindow(QWidget):
    """主窗口"""

    def __init__(self, config_manager, spider_manager=None, parent=None):
        super().__init__(parent)
        self.config_manager = config_manager
        self.spider_manager = spider_manager
        
        # 获取页面标题并设置窗口标题
        self._set_window_title()
        
        self._init_ui()
        self._apply_config()

        # 拖拽相关
        self.dragging = False
        self.drag_position = QPoint()

        # 系统托盘
        self._init_tray_icon()

    def _init_ui(self):
        """初始化UI"""
        layout = QVBoxLayout(self)
        layout.setContentsMargins(10, 10, 10, 10)

        # 标题
        self.title_label = QLabel("上证指数sh000001")
        self.title_label.setAlignment(Qt.AlignCenter)
        title_font = QFont()
        title_font.setPointSize(14)
        title_font.setBold(True)
        self.title_label.setFont(title_font)

        # 指示灯
        self.indicator = SentimentIndicator()
        self.score_label = QLabel("50 - 中性")
        self.score_label.setAlignment(Qt.AlignCenter)

        # 状态信息
        self.status_label = QLabel("等待数据...")
        self.status_label.setAlignment(Qt.AlignCenter)
        status_font = QFont()
        status_font.setPointSize(10)
        self.status_label.setFont(status_font)

        # 波形图组件
        self.waveform_widget = WaveformWidget()
        self.waveform_widget.setMinimumHeight(200)

        # 按钮
        btn_layout = QHBoxLayout()
        self.refresh_btn = QPushButton("刷新")
        self.config_btn = QPushButton("配置")
        self.quit_btn = QPushButton("退出")
        self.quit_btn.clicked.connect(self.quit_app)
        btn_layout.addWidget(self.refresh_btn)
        btn_layout.addWidget(self.config_btn)
        btn_layout.addWidget(self.quit_btn)

        # 添加到主布局
        layout.addWidget(self.title_label)
        layout.addWidget(self.indicator)
        layout.addWidget(self.score_label)
        layout.addWidget(self.status_label)
        layout.addWidget(self.waveform_widget)
        layout.addLayout(btn_layout)

        # 设置窗口标志（无边框、可拖拽）
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.setAttribute(Qt.WA_TranslucentBackground)

    def _set_window_title(self):
        """设置窗口标题"""
        logger.debug("设置窗口标题")
        
        # 尝试从爬虫获取页面标题
        if hasattr(self, 'spider_manager') and self.spider_manager:
            try:
                page_title = self.spider_manager.get_page_title()
                if page_title:
                    # 从页面标题中提取股票名称
                    import re
                    match = re.search(r'(上证指数sh\d+)', page_title)
                    if match:
                        stock_name = match.group(1)
                        window_title = f"冷暖值 - {stock_name}"
                        self.setWindowTitle(window_title)
                        
                        # 同时更新主标题标签（如果已初始化）
                        if hasattr(self, 'title_label'):
                            self.title_label.setText("上证指数sh000001")
                        logger.info(f"设置窗口标题: {window_title}")
                        return
            except Exception as e:
                logger.error(f"获取页面标题失败: {e}")
        
        # 如果获取失败，使用默认标题
        self.setWindowTitle("冷暖值 - 股吧人气")
        logger.info("使用默认窗口标题")

    def _init_tray_icon(self):
        """初始化系统托盘"""
        logger.debug("初始化系统托盘")
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setToolTip("股吧人气指示器")

        # 创建托盘菜单
        tray_menu = QMenu()
        show_action = QAction("显示", self)
        hide_action = QAction("隐藏", self)
        quit_action = QAction("退出", self)

        show_action.triggered.connect(self.show)
        hide_action.triggered.connect(self.hide)
        quit_action.triggered.connect(self.quit_app)

        tray_menu.addAction(show_action)
        tray_menu.addAction(hide_action)
        tray_menu.addAction(quit_action)

        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()
        logger.info("系统托盘初始化完成")

    def quit_app(self):
        """退出应用"""
        logger.info("退出应用")
        self.close()
        import sys
        sys.exit(0)

    def _apply_config(self):
        """应用配置"""
        ui_config = self.config_manager.ui_config
        self.setWindowOpacity(ui_config.get('opacity', 0.9))

        if ui_config.get('is_on_top', True):
            self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
        else:
            self.setWindowFlags(self.windowFlags() & ~Qt.WindowStaysOnTopHint)

        thresholds = ui_config.get('thresholds', {})

    def mousePressEvent(self, event):
        """鼠标按下事件"""
        if event.button() == Qt.LeftButton:
            self.dragging = True
            self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()

    def mouseMoveEvent(self, event):
        """鼠标移动事件"""
        if self.dragging:
            self.move(event.globalPosition().toPoint() - self.drag_position)

    def mouseReleaseEvent(self, event):
        """鼠标释放事件"""
        if event.button() == Qt.LeftButton:
            self.dragging = False

    def contextMenuEvent(self, event):
        """右键菜单"""
        context_menu = QMenu(self)
        config_action = QAction("配置", self)
        opacity_action = QAction("透明度", self)
        quit_action = QAction("退出", self)

        config_action.triggered.connect(self.show_config)
        quit_action.triggered.connect(self.quit_app)

        context_menu.addAction(config_action)
        context_menu.addAction(quit_action)
        context_menu.exec(event.globalPos())

    def show_config(self):
        """显示配置对话框"""
        dialog = ConfigDialog(self.config_manager, self)
        if dialog.exec() == QDialog.Accepted:
            self._apply_config()

    def update_indicator(self, score: int, label: str = None):
        """更新指示灯"""
        if label is None:
            label = self.indicator.get_description(score)
        self.indicator.set_value(score, label)
        self.score_label.setText(f"{score} - {label}")
        logger.debug(f"更新指示灯: {score}分 - {label}")

    def update_status(self, text: str):
        """更新状态"""
        self.status_label.setText(text)
        logger.debug(f"更新状态: {text}")

    def set_refresh_callback(self, callback: Callable):
        """设置刷新按钮回调"""
        self.refresh_btn.clicked.connect(callback)
        logger.debug("设置刷新按钮回调")

    def set_config_callback(self, callback: Callable):
        """设置配置按钮回调"""
        self.config_btn.clicked.connect(callback)
        logger.debug("设置配置按钮回调")

    def show_message(self, title: str, message: str):
        """显示消息"""
        logger.info(f"显示消息: {title} - {message}")
        QMessageBox.information(self, title, message)

    def add_waveform_data(self, time_str: str, value: float):
        """添加波形图数据点"""
        self.waveform_widget.add_data_point(time_str, value)
        logger.info(f"添加波形图数据点: 时间={time_str}, 值={value}")


class QCheckBox(QPushButton):
    """自定义复选框"""
    def __init__(self, text=""):
        super().__init__(text)
        self.setCheckable(True)
        self.setChecked(False)
