import os
import sys
import sqlite3
import time
from pathlib import Path

from qgis.PyQt.QtCore import QThread, pyqtSignal, Qt, QSettings, QTimer
from qgis.PyQt.QtWidgets import QFileDialog, QMessageBox, QApplication, QDockWidget
from qgis.PyQt import uic, QtWidgets, QtCore
from qgis.utils import iface
from qgis.core import QgsApplication
from .cyanlove_config_read_intfile import readconfig

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


def register_spatialite_connection(db_path):
    """将 SpatiaLite 数据库注册到 QGIS 浏览器（如果连接不存在），并强制刷新"""
    base_name = os.path.splitext(os.path.basename(db_path))[0]
    conn_name = base_name  # 不再添加时间戳

    settings = QSettings()
    settings.beginGroup("SpatiaLite/connections")

    # 检查连接是否已存在
    existing_conns = settings.childGroups()
    if conn_name in existing_conns:
        # 连接已存在，不重复创建，但仍刷新浏览器
        settings.endGroup()
        # 刷新浏览器
        _force_refresh_browser()
        return

    # 创建新连接
    settings.beginGroup(conn_name)
    settings.setValue("sqlitepath", db_path)
    settings.setValue("geometryColumns", "geometry_columns")
    settings.setValue("public", False)
    settings.setValue("saveUsername", False)
    settings.setValue("savePassword", False)
    settings.endGroup()
    settings.endGroup()
    settings.sync()

    # 刷新浏览器
    _force_refresh_browser()


def _force_refresh_browser():
    """强制刷新浏览器面板（内部函数）"""
    from qgis.PyQt.QtCore import QTimer
    def force_refresh():
        if not iface:
            return
        browser_dock = iface.mainWindow().findChild(QtWidgets.QDockWidget, "Browser")
        if browser_dock:
            refresh_btn = browser_dock.findChild(QtWidgets.QToolButton, "mRefreshButton")
            if not refresh_btn:
                for child in browser_dock.findChildren(QtWidgets.QToolButton):
                    if child.text() in ("刷新", "Refresh") or "refresh" in child.toolTip().lower():
                        refresh_btn = child
                        break
            if refresh_btn:
                refresh_btn.click()
            else:
                model = QgsApplication.browserModel()
                if model and hasattr(model, 'reload'):
                    model.reload()

    QTimer.singleShot(300, force_refresh)


class CreateSpatiaLiteThread(QThread):
    """后台创建 SpatiaLite 数据库的线程"""
    finished = pyqtSignal(bool, str, str)

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

    def run(self):
        try:
            conn = sqlite3.connect(self.db_path)
            conn.enable_load_extension(True)

            # Windows 环境下直接使用 mod_spatialite.dll
            # 如果用户将 mod_spatialite.dll 放在了系统路径或程序目录下，可以直接加载
            try:
                conn.load_extension('mod_spatialite')
            except Exception as e:
                # 如果加载失败，尝试使用完整名称
                try:
                    conn.load_extension('mod_spatialite.dll')
                except Exception:
                    raise Exception(
                        "无法加载 SpatiaLite 扩展 (mod_spatialite.dll)"
                    )

            cursor = conn.cursor()
            cursor.execute("SELECT InitSpatialMetadata(1)")
            conn.commit()
            conn.close()
            self.finished.emit(True, "SpatiaLite 数据库创建成功！", self.db_path)
        except Exception as e:
            self.finished.emit(False, f"创建失败: {str(e)}", "")


class cyanlove_sqliteset(QDockWidget, FORM_CLASS):
    def __init__(self, parent=None):
        super(cyanlove_sqliteset, self).__init__(parent)
        self.setupUi(self)
        self.setWindowFlags(QtCore.Qt.Dialog)
        self.setWindowModality(QtCore.Qt.ApplicationModal)

        self.toolButton.clicked.connect(self.open_file_dialog)
        self.toolButton_2.clicked.connect(self.write_sqlite_shangefenxi)
        self.toolButton_3.clicked.connect(self.read_sqlite_shangefenxi)
        self.toolButton_4.clicked.connect(self.crete_sqlite_shangefenxi)

        self.create_thread = None
        self.raise_()
        print(os.path.dirname(__file__))

    def open_file_dialog(self):
        options = QFileDialog.Options()
        options |= QFileDialog.ReadOnly
        file_name, _ = QFileDialog.getOpenFileName(
            self,
            "选择文件",
            "",
            "SQLite文件 (*.db);;所有文件 (*)",
            options=options
        )
        if file_name:
            self.textEdit.setText(file_name)
        else:
            print("用户取消了文件选择")

    def crete_sqlite_shangefenxi(self):
        """创建数据库：仅创建文件，不注册到浏览器"""
        options = QFileDialog.Options()
        options |= QFileDialog.ReadOnly
        file_name, _ = QFileDialog.getSaveFileName(
            self,
            "选择文件",
            "",
            "SpatiaLite文件 (*.db);;所有文件 (*)",
            options=options
        )
        if not file_name:
            self.label_2.setText("用户取消操作")
            return

        QApplication.setOverrideCursor(Qt.WaitCursor)
        self.toolButton_4.setEnabled(False)
        self.label_2.setText("正在创建数据库，请稍候...")

        self.create_thread = CreateSpatiaLiteThread(file_name)
        self.create_thread.finished.connect(self.on_create_finished)
        self.create_thread.start()

    def on_create_finished(self, success, message, db_path):
        QApplication.restoreOverrideCursor()
        self.toolButton_4.setEnabled(True)
        self.label_2.setText(message)
        if success:
            self.textEdit.setText(db_path)
            # 创建成功时不注册到浏览器，只提示
            QMessageBox.information(self, "提示", "数据库创建成功！\n如需在浏览器中显示，请点击「配置数据库」按钮。")

    def write_sqlite_shangefenxi(self):
        """写入配置：将当前数据库路径保存到ini，并注册到浏览器"""
        pathstr = self.textEdit.toPlainText()
        path = Path(pathstr)
        reply = QMessageBox.question(
            self, '确认配置',
            '确定要配置Sqlite数据库路径为当前显示的路径吗？\n配置后会自动添加到浏览器。',
            QMessageBox.Yes | QMessageBox.No,
            QMessageBox.No
        )
        if reply == QMessageBox.Yes:
            if path.is_file():
                # 写入ini配置
                readconfig.write_ini_file('Settings', 'sqlite_栅格分析', pathstr)
                # 注册到浏览器并刷新
                register_spatialite_connection(pathstr)
                self.label_2.setText('配置成功，已添加到浏览器！')
            else:
                self.label_2.setText('不是文件路径，请检查!')

    def read_sqlite_shangefenxi(self):
        """读取配置：从ini读取路径并显示，但不自动注册"""
        db_path = readconfig.read_ini_file('Settings', 'sqlite_栅格分析')
        self.textEdit.setText(db_path)
        if db_path and Path(db_path).is_file():
            self.label_2.setText('已读取配置，如需添加到浏览器请点击「配置数据库」按钮。')
        else:
            self.label_2.setText('配置路径无效或未配置。')