import os
from qgis.PyQt.QtCore import Qt, QThread, QStringListModel, QSize, pyqtSignal, QVariant
from qgis.PyQt.QtGui import QColor, QIcon
from qgis.PyQt import QtWidgets, uic, QtCore
import re
from qgis.core import (
    QgsFeatureRequest, QgsSpatialIndex, QgsVectorLayer, QgsProject,
    QgsSymbol, QgsRendererCategory, QgsCategorizedSymbolRenderer,
    QgsMapLayerProxyModel, QgsVectorDataProvider, QgsExpression
)
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.iface = iface  # 保存 iface 引用，便于后续使用
        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)

        # +++ 新增：监听图层面板选择变化，同步下拉框 +++
        layer_tree_view = self.iface.layerTreeView()
        if layer_tree_view:
            layer_tree_view.selectionModel().selectionChanged.connect(
                self.on_layer_tree_selection_changed
            )
        # ------------------------------------------------

        # 缓存字段是否为文本类型（key: layer_id_fieldname）
        self.is_text_field_cache = {}
        # 缓存图层索引状态
        self.layer_index_status = {}

    # +++ 新增方法：图层面板选择变化处理 +++
    def on_layer_tree_selection_changed(self, selected, deselected):
        """当图层面板选中图层变化时，同步更新下拉框"""
        selected_layers = self.iface.layerTreeView().selectedLayers()
        if selected_layers:
            layer = selected_layers[0]
            # 设置下拉框的当前图层（会触发 currentIndexChanged，从而更新字段下拉框）
            self.mMapLayerComboBox.setLayer(layer)
    # ------------------------------------------------

    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.is_text_field_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():
                self.canvas.flashFeatureIds(
                    layer,
                    feature_id_list,
                    startColor=QColor(255, 255, 0, 255),
                    endColor=QColor(255, 255, 0, 0),
                    flashes=6,
                    duration=500
                )
            if self.radioButton_filter.isChecked():
                # 需要知道字段类型来构建子集字符串表达式
                is_text = self.is_text_field(layer, featurecolname)
                if is_text:
                    # 字符串值需转义单引号
                    escaped_value = item_text.replace("'", "''")
                    expression = f"\"{featurecolname}\" = '{escaped_value}'"
                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 is_text_field(self, layer, field_name):
        """判断字段是否为文本类型（使用 QVariant.Type）"""
        if not layer or not field_name:
            return False
        cache_key = f"{layer.id()}_{field_name}"
        if cache_key in self.is_text_field_cache:
            return self.is_text_field_cache[cache_key]

        fields = layer.fields()
        idx = fields.indexOf(field_name)
        if idx == -1:
            self.is_text_field_cache[cache_key] = False
            return False
        field_type = fields.field(idx).type()
        # QVariant.String = 10, QVariant.StringList = 11
        is_text = field_type in (QVariant.String, QVariant.StringList)
        self.is_text_field_cache[cache_key] = is_text
        return is_text

    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 = {}

        # 判断字段是否为文本类型
        is_text = self.is_text_field(layerselect, colname)

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

        # 根据查找类型和字段类型构建表达式
        if button_text == "模糊查找":
            if is_text:
                # 文本字段：LIKE 模糊匹配，需转义 % 和 _ 以防止通配符注入（可选）
                # 简单处理：直接使用 LIKE，若需要转义可增加以下两行
                # raw_value = input_value.replace('%', '\\%').replace('_', '\\_')
                # expression = f"\"{colname}\" LIKE '%{raw_value}%' ESCAPE '\\'"
                expression = f"\"{colname}\" LIKE '%{input_value}%'"
            else:
                # 非文本字段（数值等）：精确匹配
                expression = f"\"{colname}\" = {input_value}"
        else:  # 精确查找
            if is_text:
                # 文本字段：精确匹配，需转义单引号
                escaped_value = input_value.replace("'", "''")
                expression = f"\"{colname}\" = '{escaped_value}'"
            else:
                expression = f"\"{colname}\" = {input_value}"

        # 启动搜索线程，传递必要参数（表达式、图层、字段名）
        self.export_thread = ExportThread(layerselect, colname, expression, 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 = layer.crs()
        layer_type = layer.geometryType()
        new_layer = None
        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)

    def __init__(self, layerselect, colname, expression, property_dict):
        super().__init__()
        self.layerselect = layerselect
        self.colname = colname
        self.expression = expression
        self.property_dict = property_dict
        self.max_results = 1000

    def run(self):
        try:
            request = QgsFeatureRequest().setFilterExpression(self.expression)
            request.setSubsetOfAttributes([self.colname], 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)

                if name_str not in self.property_dict:
                    self.property_dict[name_str] = []

                self.property_dict[name_str].append({
                    'featureid': feature.id(),
                    'featuretype': 'String',  # 仅用于标记，实际未使用
                    'featurecolname': self.colname
                })
                result_count += 1

            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(['搜索出错！'])