import os

from PyQt5.QtCore import Qt, QThread, QStringListModel, QSize
from PyQt5.QtGui import QColor, QIcon
from qgis.PyQt import QtWidgets, uic, QtCore
from qgis.PyQt.QtCore import pyqtSignal
import re
from qgis._core import QgsFeatureRequest, QgsSpatialIndex, QgsVectorLayer, QgsProject, QgsSymbol, QgsRendererCategory, \
    QgsCategorizedSymbolRenderer, QgsMapLayerProxyModel, QgsVectorDataProvider
from qgis.utils import iface

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


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

    def __init__(self, parent=None):
        super(cyanlove_cell_nodeb_search, self).__init__(parent)
        self.search_model = None
        self.search_data = None
        self.export_thread = None
        self.canvas = iface.mapCanvas()
        self.setupUi(self)

        self.property_dict = None  # 存储搜索出来的名称，图元中心经纬度
        self.is_running = False  # 线程状态标志
        self.setWindowFlags(QtCore.Qt.Dialog)  # 使对话框始终在前
        self.btn_clear_filter.setIcon(QIcon(':/plugins/cyanlove/icon/clear_one.svg'))
        self.btn_clear_filter.clicked.connect(self.clear_filter)

        self.mFieldComboBox.setLayer(self.mMapLayerComboBox.currentLayer())
        self.mMapLayerComboBox.currentIndexChanged.connect(self.selectindexchange)
        self.mohu_btn.clicked.connect(self.layer_search)
        self.jingque_btn.clicked.connect(self.layer_search)
        self.listView_show.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)  # 设置为不可编辑
        self.search_model = QStringListModel()
        self.listView_show.setModel(self.search_model)
        # 列表连接双击信号
        self.listView_show.doubleClicked.connect(self.on_item_double_clicked)

        # 缓存字段类型信息，避免重复查询
        self.field_type_cache = {}
        # 缓存图层索引状态
        self.layer_index_status = {}

    def closeEvent(self, event):
        self.closingPlugin.emit()
        print("guan_cell")
        event.accept()

    def selectindexchange(self):
        current_layer = self.mMapLayerComboBox.currentLayer()
        self.mFieldComboBox.setLayer(current_layer)
        # 清空字段类型缓存
        self.field_type_cache = {}

    def updatelistview(self, search_data):
        self.search_model.setStringList(search_data)

    def clear_filter(self):
        # 获取当前选中的图层
        current_layer = self.mMapLayerComboBox.currentLayer()
        if current_layer:
            current_layer.setSubsetString("")
            current_layer.removeSelection()  # 清除选择
            current_layer.triggerRepaint()  # 强制刷新图层显示

    def on_thread_finished(self):
        self.is_running = False  # 线程结束时重置状态
        print("搜索完成！")

    def on_item_double_clicked(self, index):
        # 获取双击的项
        if not self.property_dict:
            return
        #  双击的文本
        item_text = self.search_model.data(index, QtCore.Qt.DisplayRole)

        # 检查是否是提示信息
        if item_text in ["搜索中...", "无数据！", "没有选择必要字段！", "（结果过多，显示前1000条）"]:
            return

        feature_id_list = []
        featurecolname = None
        featuretype = None
        # 遍历字典并提取信息
        if item_text in self.property_dict:
            feature_list = self.property_dict[item_text]
            for feature_data in feature_list:
                # 提取每个字典中的字段信息
                featureid = feature_data['featureid']
                feature_id_list.append(featureid)
                featuretype = feature_data['featuretype']
                featurecolname = feature_data['featurecolname']

            layer = self.mMapLayerComboBox.currentLayer()
            if not layer:
                return

            # 平移到位置
            self.canvas.panToFeatureIds(layer, feature_id_list)
            # 如果闪烁功能开启，则闪烁
            if self.radioButton_shanshuo.isChecked():
                # 调用 flashFeatureIds
                self.canvas.flashFeatureIds(
                    layer,  # 图层
                    feature_id_list,  # 要素ID列表
                    startColor=QColor(255, 255, 0, 255),  # 开始颜色（黄色）
                    endColor=QColor(255, 255, 0, 0),  # 结束颜色（透明）
                    flashes=6,  # 闪烁次数
                    duration=500  # 持续时间（毫秒）
                )
            # 如果过滤功能开启，则过滤
            if self.radioButton_filter.isChecked():
                # 使用更高效的子集字符串而不是选择
                if featuretype and featuretype.lower() == "string":
                    expression = f"\"{featurecolname}\" = '{item_text.replace("'", "''")}'"  # 处理单引号
                else:
                    # 对于数值类型，直接使用值
                    expression = f"\"{featurecolname}\" = {item_text}"

                layer.setSubsetString(expression)
                # 可选：同时选择要素以高亮显示
                layer.selectByIds(feature_id_list)
        else:
            print(f"Name {item_text} not found in the dictionary.")

    def get_field_type(self, layer, field_name):
        """获取字段类型并缓存结果"""
        cache_key = f"{layer.id()}_{field_name}"
        if cache_key in self.field_type_cache:
            return self.field_type_cache[cache_key]

        field_type = "String"  # 默认类型
        if layer and field_name:
            fields = layer.fields()
            field_index = fields.indexOf(field_name)
            if field_index >= 0:
                field = fields.field(field_index)
                field_type = field.typeName()

        self.field_type_cache[cache_key] = field_type
        return field_type

    def check_and_create_index(self, layer, field_name):
        """检查并创建属性索引"""
        if not layer or not field_name:
            return False

        cache_key = f"{layer.id()}_{field_name}"
        if cache_key in self.layer_index_status:
            return self.layer_index_status[cache_key]

        provider = layer.dataProvider()
        field_index = layer.fields().indexOf(field_name)

        if field_index >= 0:
            # 检查是否已有索引
            if not provider.capabilities() & QgsVectorDataProvider.CreateAttributeIndex:
                self.layer_index_status[cache_key] = False
                return False

            try:
                # 尝试创建索引
                provider.createAttributeIndex(field_index)
                self.layer_index_status[cache_key] = True
                print(f"为字段 {field_name} 创建了属性索引")
                return True
            except Exception as e:
                print(f"创建属性索引失败: {e}")
                self.layer_index_status[cache_key] = False
                return False

        self.layer_index_status[cache_key] = False
        return False

    def layer_search(self):
        if self.is_running:  # 检查线程是否在运行
            print("运行中...")
            return

        layerselect = self.mMapLayerComboBox.currentLayer()
        colname = self.mFieldComboBox.currentField()
        input_value = self.textEdit.toPlainText().strip()

        if not layerselect or not colname or not input_value:
            self.search_data = ["没有选择必要字段！"]
            self.search_model.setStringList(self.search_data)
            return

        # 创建查询表达式
        button = self.sender()  # 获取发送信号的对象
        if not button:
            return

        button_text = button.text()  # 获取按钮文本
        self.search_data = ["搜索中..."]
        self.search_model.setStringList(self.search_data)

        # 处理事件以更新界面
        QtWidgets.QApplication.processEvents()

        # 清空字典数据
        self.property_dict = {}

        # 获取字段类型（使用缓存）
        field_type = self.get_field_type(layerselect, colname)

        # 检查并创建索引
        self.check_and_create_index(layerselect, colname)

        # 构建表达式
        if button_text == "模糊查找":
            if field_type and field_type.lower() != "string":
                # 非字符串字段使用精确匹配
                expression = f"\"{colname}\" = '{input_value}'"
            else:
                # 字符串字段使用模糊匹配
                expression = f"\"{colname}\" LIKE '%{input_value}%'"
        else:
            # 精确查找
            if field_type and field_type.lower() == "string":
                expression = f"\"{colname}\" = '{input_value}'"
            else:
                expression = f"\"{colname}\" = {input_value}"

        # 启动搜索线程
        self.export_thread = ExportThread(layerselect, colname, input_value, expression, field_type, self.property_dict)
        self.export_thread.finished.connect(self.on_thread_finished)
        self.export_thread.updatelistview.connect(self.updatelistview)
        self.is_running = True
        self.export_thread.start()

    @staticmethod
    def create_templayer(layer, featuregem):
        # 获取原图层的 CRS（坐标参考系统）
        crs = layer.crs()
        # 获取原图层的类型
        layer_type = layer.geometryType()  # 0:点图层, 1:线图层, 2:面图层
        # 根据图层类型创建新的空图层
        new_layer = ""
        if layer_type == 0:
            new_layer = QgsVectorLayer('Point?crs=' + crs.toWkt(), 'templayer', 'memory')
        elif layer_type == 1:
            new_layer = QgsVectorLayer('LineString?crs=' + crs.toWkt(), 'templayer', 'memory')
        elif layer_type == 2:
            new_layer = QgsVectorLayer('Polygon?crs=' + crs.toWkt(), 'templayer', 'memory')
        else:
            print("不支持的图层类型")
            return None

        # 复制原图层的字段结构
        fields = layer.fields()
        new_layer.dataProvider().addAttributes(fields)
        new_layer.updateFields()

        # 将该要素添加到临时图层
        new_layer.startEditing()
        new_layer.addFeatures([featuregem])
        new_layer.commitChanges()

        # 添加临时图层到地图中
        QgsProject.instance().addMapLayer(new_layer)
        return new_layer


class ExportThread(QThread):
    updatelistview = pyqtSignal(list)  # 声明一个更新listview新增信号

    def __init__(self, layerselect, colname, input_value, expression, field_type, property_dict):
        super().__init__()
        self.layerselect = layerselect
        self.colname = colname
        self.input_value = input_value
        self.field_type = field_type
        self.expression = expression
        self.property_dict = property_dict
        self.max_results = 1000  # 限制最大结果数量

    def run(self):
        try:
            # 使用更高效的查询方式
            request = QgsFeatureRequest().setFilterExpression(self.expression)

            # 设置只请求需要的字段，减少数据传输
            fields_to_fetch = [self.colname] if self.colname else []
            request.setSubsetOfAttributes(fields_to_fetch, self.layerselect.fields())

            # 禁用几何获取（如果不需要几何信息）
            # request.setFlags(QgsFeatureRequest.NoGeometry)

            # 执行请求并获取特征
            features = self.layerselect.getFeatures(request)

            print(f"搜索表达式: {self.expression}")
            result_count = 0

            for feature in features:
                if result_count >= self.max_results:
                    # 结果过多，添加提示
                    if "（结果过多，显示前1000条）" not in self.property_dict:
                        self.property_dict["（结果过多，显示前1000条）"] = []
                    break

                name = feature[self.colname]
                name_str = str(name)

                # 如果键已经存在，则将 feature 添加到列表中
                if name_str not in self.property_dict:
                    self.property_dict[name_str] = []

                # 将新的 feature 添加到对应键的列表中
                self.property_dict[name_str].append({
                    'featureid': feature.id(),
                    'featuretype': self.field_type,
                    'featurecolname': self.colname
                })

                result_count += 1

            # 更新listview
            if len(self.property_dict) > 0:
                result_list = list(self.property_dict.keys())
                # 移除提示条目（如果存在）以便正确排序
                if "（结果过多，显示前1000条）" in result_list:
                    result_list.remove("（结果过多，显示前1000条）")
                    result_list.append("（结果过多，显示前1000条）")
                self.updatelistview.emit(result_list)
            else:
                self.updatelistview.emit(['无数据！'])

            print(f'搜索完成，找到 {result_count} 个结果')

        except Exception as e:
            print(f"搜索过程中出错: {e}")
            self.updatelistview.emit(['搜索出错！'])