import os

from qgis.PyQt.QtCore import Qt, QThread, QStringListModel, QSize
from qgis.PyQt.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(['搜索出错！'])