import csv
import hashlib
import json
import math
import os
import time
import urllib
import sqlite3
from datetime import datetime

import requests
from qgis.PyQt.QtCore import QVariant, QThread, pyqtSignal
from qgis.PyQt import uic
from qgis.core import QgsFillSymbol, QgsVectorLayer, QgsProject, QgsFields, \
    QgsField, QgsGeometry, QgsPointXY, QgsFeature, QgsSingleSymbolRenderer, \
    QgsMapLayerStyle
from qgis.utils import iface
from qgis.PyQt import QtCore, QtWidgets
from qgis.PyQt.QtWidgets import QMessageBox, QInputDialog, QDialog, QVBoxLayout, \
    QLineEdit, QTextEdit, QPushButton, QHBoxLayout, QLabel, QCheckBox, QDialogButtonBox, \
    QComboBox

from .cyanlove_config_read_intfile import readconfig
from .cyanlove_transform_gps_to_gps import Mecator_to_gps

FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'cyanlove_style_set_base.ui'))


class cyanlove_style_set(QtWidgets.QDockWidget, FORM_CLASS):
    closingPlugin = pyqtSignal()

    def __init__(self, parent=None):
        super(cyanlove_style_set, self).__init__(parent)

        self.export_thread = None
        self.iface = iface
        self.canvas = iface.mapCanvas()
        self.setupUi(self)
        # 设置按钮布局的拉伸因子
        if hasattr(self, 'horizontalLayout'):
            self.horizontalLayout.setStretch(0, 2)  # 加载样式
            self.horizontalLayout.setStretch(1, 1)  # 清空样式
            self.horizontalLayout.setStretch(2, 1)  # 保存样式
            self.horizontalLayout.setStretch(3, 1)  # 删除样式
        self.setFloating(True)
        self.layer = None
        self.setWindowFlags(QtCore.Qt.Dialog)

        # 连接信号槽
        self.btn_save_style.clicked.connect(self.save_style_to_database)
        self.btn_load_style.clicked.connect(self.load_style_from_database)
        self.btn_delete_style.clicked.connect(self.delete_style_from_database)
        self.btn_clear_style.clicked.connect(self.clear_style_from_layer)
        self.mMapLayerComboBox.layerChanged.connect(self.on_layer_changed)

        # 监听图层面板选择变化
        layer_tree_view = self.iface.layerTreeView()
        if layer_tree_view:
            layer_tree_view.selectionModel().selectionChanged.connect(
                self.on_layer_tree_selection_changed
            )

        # 初始化数据库（采用标准表结构）
        self.init_database()

        # 初始化时加载样式列表
        self.on_layer_changed(self.mMapLayerComboBox.currentLayer())

        # 设置表格可选择整行
        self.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)

        # 添加右键菜单
        self.tableWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
        self.tableWidget.customContextMenuRequested.connect(self.show_context_menu)

    def on_layer_tree_selection_changed(self, selected, deselected):
        """当图层面板选中图层变化时，同步更新下拉框"""
        selected_layers = self.iface.layerTreeView().selectedLayers()
        if selected_layers:
            layer = selected_layers[0]
            self.mMapLayerComboBox.setLayer(layer)

    # ---------- 初始化数据库（标准表结构）----------
    def init_database(self):
        """
        初始化数据库，采用 QGIS 标准 layer_styles 表结构。
        """
        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            QMessageBox.warning(self, "警告", "未找到数据库路径配置")
            return

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            # 标准 QGIS layer_styles 表结构（无扩展字段）
            cursor.execute('''
                CREATE TABLE IF NOT EXISTS layer_styles (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    f_table_catalog TEXT,
                    f_table_schema TEXT,
                    f_table_name TEXT NOT NULL,
                    f_geometry_column TEXT,
                    styleName TEXT NOT NULL,
                    styleQML TEXT,
                    styleSLD TEXT,
                    useAsDefault BOOLEAN NOT NULL DEFAULT 0,
                    description TEXT,
                    owner TEXT,
                    ui TEXT,
                    update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                )
            ''')

            # 创建索引
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_f_table_name ON layer_styles(f_table_name)')
            cursor.execute('CREATE INDEX IF NOT EXISTS idx_styleName ON layer_styles(styleName)')

            conn.commit()
            conn.close()

        except Exception as e:
            QMessageBox.critical(self, "错误", f"初始化数据库失败：{str(e)}")

    def on_layer_changed(self, layer):
        """当图层选择改变时触发"""
        self.layer = layer
        self.load_all_styles_from_database()

    # ---------- 加载所有样式列表（不含扩展字段）----------
    def load_all_styles_from_database(self):
        """从数据库加载所有样式列表到表格"""
        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            return

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            # 查询标准字段（使用 update_time 作为时间显示）
            cursor.execute('''
                SELECT id, styleName, description, 
                       useAsDefault, update_time
                FROM layer_styles
                ORDER BY update_time DESC
            ''')

            styles = cursor.fetchall()
            conn.close()

            # 更新表格显示
            self.tableWidget.clear()
            self.tableWidget.setColumnCount(5)
            self.tableWidget.setHorizontalHeaderLabels([
                'ID', '样式名称', '描述', '默认', '更新时间'
            ])

            # 隐藏ID列
            self.tableWidget.setColumnHidden(0, True)

            self.tableWidget.setRowCount(len(styles))
            for row, style in enumerate(styles):
                (style_id, style_name, description,
                 is_default, update_time) = style
                self.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem(str(style_id)))
                self.tableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem(style_name))
                self.tableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem(description or ''))
                self.tableWidget.setItem(row, 3, QtWidgets.QTableWidgetItem('是' if is_default else '否'))
                self.tableWidget.setItem(row, 4, QtWidgets.QTableWidgetItem(str(update_time)))

            # 调整列宽
            header = self.tableWidget.horizontalHeader()
            header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)  # 样式名称
            header.setSectionResizeMode(2, QtWidgets.QHeaderView.Stretch)          # 描述
            header.setSectionResizeMode(3, QtWidgets.QHeaderView.ResizeToContents) # 默认
            header.setSectionResizeMode(4, QtWidgets.QHeaderView.ResizeToContents) # 更新时间

            # 更新说明
            if self.layer:
                self.label_show.setText(f'说明：共 {len(styles)} 个样式，当前图层: {self.layer.name()}')
            else:
                self.label_show.setText(f'说明：共 {len(styles)} 个样式')
            self.label_show.setStyleSheet('color: rgb(0, 170, 0);')

        except Exception as e:
            self.label_show.setText(f'说明：加载样式失败 - {str(e)}')
            self.label_show.setStyleSheet('color: rgb(255, 0, 0);')

    def get_selected_style_id(self):
        """获取当前选中的样式ID"""
        current_row = self.tableWidget.currentRow()
        if current_row < 0:
            QMessageBox.warning(self, "警告", "请先选择一行样式")
            return None

        id_item = self.tableWidget.item(current_row, 0)
        if not id_item:
            QMessageBox.warning(self, "警告", "无法获取样式ID")
            return None

        try:
            return int(id_item.text())
        except:
            QMessageBox.warning(self, "警告", "样式ID无效")
            return None

    # ---------- 保存样式（标准字段）----------
    def save_style_to_database(self):
        """保存当前图层样式到数据库（使用标准字段）"""
        if not self.layer:
            QMessageBox.warning(self, "警告", "请先选择一个图层")
            return

        style_manager = self.layer.styleManager()
        if not style_manager:
            QMessageBox.warning(self, "警告", "图层不支持样式管理")
            return

        current_style = style_manager.currentStyle()

        # 获取样式XML
        try:
            style_qml = self.layer.styleManager().style(current_style).export()
        except:
            try:
                style_qml = self.layer.styleManager().style(current_style).xmlData()
            except:
                QMessageBox.critical(self, "错误", "无法获取图层样式")
                return

        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            QMessageBox.warning(self, "警告", "未找到数据库路径配置")
            return

        # 弹出对话框让用户输入样式信息
        dialog = QDialog(self)
        dialog.setWindowTitle("保存样式到数据库")
        dialog.setMinimumWidth(400)

        layout = QVBoxLayout()

        info_label = QLabel(f"当前图层: {self.layer.name()}")
        info_label.setStyleSheet("font-weight: bold; color: blue;")
        layout.addWidget(info_label)

        name_label = QLabel("样式名称：")
        name_edit = QLineEdit()
        name_edit.setText(f"{self.layer.name()}_style")

        desc_label = QLabel("描述：")
        desc_edit = QTextEdit()
        desc_edit.setMaximumHeight(100)

        default_check = QCheckBox("设为默认样式")

        layout.addWidget(name_label)
        layout.addWidget(name_edit)
        layout.addWidget(desc_label)
        layout.addWidget(desc_edit)
        layout.addWidget(default_check)

        button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        layout.addWidget(button_box)

        dialog.setLayout(layout)

        button_box.accepted.connect(dialog.accept)
        button_box.rejected.connect(dialog.reject)

        if dialog.exec_() != QDialog.Accepted:
            return

        style_name = name_edit.text().strip()
        description = desc_edit.toPlainText().strip()
        use_as_default = 1 if default_check.isChecked() else 0

        if not style_name:
            QMessageBox.warning(self, "警告", "样式名称不能为空")
            return

        layer_name = self.layer.name()
        # 标准字段中没有 layer_source，此处不再保存

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            # 检查是否已存在同名样式（按 f_table_name 和 styleName）
            cursor.execute(
                "SELECT id FROM layer_styles WHERE f_table_name = ? AND styleName = ?",
                (layer_name, style_name)
            )
            existing = cursor.fetchone()

            if existing:
                # 更新现有样式
                cursor.execute('''
                    UPDATE layer_styles 
                    SET styleQML = ?,
                        description = ?,
                        useAsDefault = ?,
                        update_time = CURRENT_TIMESTAMP
                    WHERE id = ?
                ''', (style_qml, description, use_as_default, existing[0]))
                message = f"样式 '{style_name}' 已更新"
            else:
                # 插入新样式（标准字段，其他标准字段设为 NULL 或默认）
                cursor.execute('''
                    INSERT INTO layer_styles (
                        f_table_name,
                        f_geometry_column,
                        styleName,
                        styleQML,
                        description,
                        useAsDefault,
                        f_table_catalog,
                        f_table_schema,
                        styleSLD,
                        owner,
                        ui,
                        update_time
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    layer_name,
                    'geometry',
                    style_name,
                    style_qml,
                    description,
                    use_as_default,
                    None,   # f_table_catalog
                    None,   # f_table_schema
                    None,   # styleSLD
                    None,   # owner
                    None,   # ui
                    datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                ))
                message = f"样式 '{style_name}' 已保存"

            # 如果设为默认样式，取消同一图层的其他默认样式
            if use_as_default:
                cursor.execute('''
                    UPDATE layer_styles 
                    SET useAsDefault = 0 
                    WHERE f_table_name = ? AND styleName != ?
                ''', (layer_name, style_name))

            conn.commit()
            conn.close()

            QMessageBox.information(self, "成功", message)

            # 刷新样式列表
            self.load_all_styles_from_database()

        except Exception as e:
            QMessageBox.critical(self, "错误", f"保存样式到数据库失败：{str(e)}")

    # ---------- 加载样式（标准字段）----------
    def load_style_from_database(self):
        """从数据库加载选中的样式到当前图层"""
        if not self.layer:
            QMessageBox.warning(self, "警告", "请先选择一个图层")
            return

        style_id = self.get_selected_style_id()
        if not style_id:
            return

        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            QMessageBox.warning(self, "警告", "未找到数据库路径配置")
            return

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            cursor.execute('''
                SELECT styleName, styleQML, description, f_table_name
                FROM layer_styles
                WHERE id = ?
            ''', (style_id,))

            result = cursor.fetchone()
            conn.close()

            if not result:
                QMessageBox.warning(self, "警告", "未找到样式数据")
                return

            style_name, style_qml, description, original_layer_name = result

            # 确认应用样式
            reply = QMessageBox.question(
                self,
                "确认应用样式",
                f"样式名称: {style_name}\n"
                f"原始图层: {original_layer_name}\n"
                f"当前图层: {self.layer.name()}\n\n"
                f"确定要应用此样式到当前图层吗？",
                QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes
            )

            if reply != QMessageBox.Yes:
                return

            # 应用样式
            try:
                style_manager = self.layer.styleManager()

                if style_name in style_manager.styles():
                    style_manager.removeStyle(style_name)

                style_manager.addStyle(style_name, QgsMapLayerStyle(style_qml))
                style_manager.setCurrentStyle(style_name)

                self.layer.triggerRepaint()
                self.canvas.refresh()

                self.label_show.setText(f'说明：已加载样式 "{style_name}" 到 {self.layer.name()}')
                self.label_show.setStyleSheet('color: rgb(0, 170, 0);')

            except Exception as e:
                QMessageBox.critical(self, "错误", f"应用样式到图层失败：{str(e)}")

        except Exception as e:
            QMessageBox.critical(self, "错误", f"从数据库加载样式失败：{str(e)}")

    # ---------- 删除样式 ----------
    def delete_style_from_database(self):
        """从数据库删除选中的样式"""
        style_id = self.get_selected_style_id()
        if not style_id:
            return

        reply = QMessageBox.question(
            self,
            "确认删除",
            "确定要删除选中的样式吗？此操作不可恢复！",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )

        if reply != QMessageBox.Yes:
            return

        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            QMessageBox.warning(self, "警告", "未找到数据库路径配置")
            return

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            cursor.execute('SELECT styleName FROM layer_styles WHERE id = ?', (style_id,))
            result = cursor.fetchone()
            style_name = result[0] if result else '未知'

            cursor.execute('DELETE FROM layer_styles WHERE id = ?', (style_id,))
            conn.commit()
            conn.close()

            QMessageBox.information(self, "成功", f"样式 '{style_name}' 已删除")

            self.load_all_styles_from_database()

        except Exception as e:
            QMessageBox.critical(self, "错误", f"删除样式失败：{str(e)}")

    # ---------- 右键菜单 ----------
    def show_context_menu(self, position):
        menu = QtWidgets.QMenu()

        apply_action = menu.addAction("应用到当前图层")
        apply_action.triggered.connect(self.load_style_from_database)

        detail_action = menu.addAction("查看详情")
        detail_action.triggered.connect(self.show_style_detail)

        copy_action = menu.addAction("复制样式名称")
        copy_action.triggered.connect(self.copy_style_name)

        menu.exec_(self.tableWidget.viewport().mapToGlobal(position))

    # ---------- 样式详情（标准字段）----------
    def show_style_detail(self):
        """显示样式详情（使用标准字段）"""
        style_id = self.get_selected_style_id()
        if not style_id:
            return

        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        if not db_path:
            return

        try:
            conn = sqlite3.connect(db_path)
            cursor = conn.cursor()

            cursor.execute('''
                SELECT styleName, description, f_table_name, 
                       useAsDefault, update_time
                FROM layer_styles
                WHERE id = ?
            ''', (style_id,))

            result = cursor.fetchone()
            conn.close()

            if not result:
                return

            (style_name, description, f_table_name,
             is_default, update_time) = result

            msg = f"""样式详情：

样式名称: {style_name}
描述: {description or '无'}
原始图层: {f_table_name or '无'}
是否默认: {'是' if is_default else '否'}
更新时间: {update_time}
"""
            QMessageBox.information(self, "样式详情", msg)

        except Exception as e:
            QMessageBox.critical(self, "错误", f"获取样式详情失败：{str(e)}")

    def copy_style_name(self):
        """复制样式名称到剪贴板"""
        current_row = self.tableWidget.currentRow()
        if current_row < 0:
            return

        name_item = self.tableWidget.item(current_row, 1)
        if name_item:
            clipboard = QtWidgets.QApplication.clipboard()
            clipboard.setText(name_item.text())
            QMessageBox.information(self, "成功", "样式名称已复制到剪贴板")

    # ---------- 清空样式 ----------
    def clear_style_from_layer(self):
        """清空当前图层的所有样式"""
        if not self.layer:
            QMessageBox.warning(self, "警告", "请先选择一个图层")
            return

        style_manager = self.layer.styleManager()
        if not style_manager:
            QMessageBox.warning(self, "警告", "图层不支持样式管理")
            return

        styles = style_manager.styles()
        if not styles:
            QMessageBox.information(self, "提示", "当前图层没有样式")
            return

        reply = QMessageBox.question(
            self,
            "确认清空样式",
            f"确定要清空图层 '{self.layer.name()}' 的所有样式吗？\n"
            f"共 {len(styles)} 个样式将被删除。\n\n"
            "此操作不可恢复！",
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )

        if reply != QMessageBox.Yes:
            return

        try:
            for style_name in styles:
                style_manager.removeStyle(style_name)

            # 添加一个默认空样式
            style_manager.addStyle("default", QgsMapLayerStyle())
            style_manager.setCurrentStyle("default")

            self.layer.triggerRepaint()
            self.canvas.refresh()

            QMessageBox.information(
                self,
                "成功",
                f"已清空图层 '{self.layer.name()}' 的所有样式"
            )

            self.label_show.setText(f'说明：已清空图层 "{self.layer.name()}" 的所有样式')
            self.label_show.setStyleSheet('color: rgb(255, 165, 0);')

        except Exception as e:
            QMessageBox.critical(self, "错误", f"清空样式失败：{str(e)}")

    def closeEvent(self, event):
        """关闭窗口事件"""
        self.closingPlugin.emit()
        event.accept()