import os
import pathlib
import re


import pandas as pd
from PyQt5.QtCore import QThread

from qgis.PyQt.QtCore import QVariant
from qgis.PyQt import QtWidgets, uic, QtCore
from qgis.PyQt.QtCore import pyqtSignal

from qgis._core import QgsProject, QgsVectorLayer, QgsGeometry, QgsFeature, QgsField, QgsFields
from qgis.utils import iface
from qgis.core import Qgis
from datetime import datetime

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


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

    def __init__(self, parent=None):
        super(cyanlove_updatecolumnattribute_layer, self).__init__(parent)
        self.export_thread = None
        self.setupUi(self)
        self.setFloating(True)
        self.setWindowFlags(QtCore.Qt.Dialog)

        # 初始化进度条
        self.progressBar.setValue(0)
        self.progressBar.setVisible(False)

        # 连接信号
        self.jingque_btn.clicked.connect(self.update_column_attribute)

        # 当图层选择改变时，更新字段列表
        self.mMapLayerComboBox.layerChanged.connect(self.update_field_combo_box)

        # 初始化字段下拉框
        self.initialize_field_combo_box()

    def closeEvent(self, event):
        if self.export_thread and self.export_thread.isRunning():
            self.export_thread.stop()
            self.export_thread.wait(2000)  # 等待2秒让线程结束
        self.closingPlugin.emit()
        event.accept()

    def initialize_field_combo_box(self):
        """初始化字段下拉框"""
        current_layer = self.mMapLayerComboBox.currentLayer()
        if current_layer:
            self.mFieldComboBox.setLayer(current_layer)

    def update_field_combo_box(self):
        """当图层改变时更新字段下拉框"""
        current_layer = self.mMapLayerComboBox.currentLayer()
        if current_layer:
            self.mFieldComboBox.setLayer(current_layer)

    def update_column_attribute(self):
        """创建新图层并将选定列的数据转换为double类型"""
        try:
            # 获取用户输入
            current_layer = self.mMapLayerComboBox.currentLayer()
            selected_field = self.mFieldComboBox.currentField()
            new_column_name = self.textEdit_new_column.toPlainText().strip()

            # 验证输入
            if not current_layer:
                iface.messageBar().pushMessage("错误", "请选择图层", level=Qgis.Warning, duration=3)
                return

            if not selected_field:
                iface.messageBar().pushMessage("错误", "请选择要转换的字段", level=Qgis.Warning, duration=3)
                return

            if not new_column_name:
                iface.messageBar().pushMessage("错误", "请输入新列名称", level=Qgis.Warning, duration=3)
                return

            # 重置进度条
            self.progressBar.setValue(0)
            self.progressBar.setVisible(True)
            self.jingque_btn.setEnabled(False)

            # 启动处理线程
            self.export_thread = ColumnUpdateThread(current_layer, selected_field, new_column_name)
            self.export_thread.update_progress.connect(self.update_progress_bar)
            self.export_thread.finished_successfully.connect(self.on_process_finished)
            self.export_thread.layer_created.connect(self.on_layer_created)
            self.export_thread.start()

        except Exception as e:
            iface.messageBar().pushMessage("错误", f"初始化转换过程时出错: {str(e)}", level=Qgis.Critical, duration=5)
            self.progressBar.setVisible(False)
            self.jingque_btn.setEnabled(True)

    def update_progress_bar(self, progress):
        """更新进度条"""
        self.progressBar.setValue(progress)

    def on_layer_created(self, layer):
        """新图层创建成功回调"""
        # 将新图层添加到项目
        QgsProject.instance().addMapLayer(layer)
        iface.messageBar().pushMessage("成功", f"新图层 '{layer.name()}' 已创建并添加到项目", level=Qgis.Success,
                                       duration=5)

    def on_process_finished(self, success_count, error_count):
        """处理完成回调"""
        # 隐藏进度条并启用按钮
        self.progressBar.setVisible(False)
        self.jingque_btn.setEnabled(True)

        if success_count > 0:
            message = f"转换完成！成功转换 {success_count} 条记录"
            if error_count > 0:
                message += f"，{error_count} 条记录转换失败"
            iface.messageBar().pushMessage("成功", message, level=Qgis.Success, duration=5)
        else:
            iface.messageBar().pushMessage("警告", "没有成功转换任何记录", level=Qgis.Warning, duration=3)


class ColumnUpdateThread(QThread):
    update_progress = pyqtSignal(int)  # 改为发射进度百分比
    finished_successfully = pyqtSignal(int, int)  # success_count, error_count
    layer_created = pyqtSignal(object)  # 新图层创建信号

    def __init__(self, layer, source_field, new_field_name):
        super().__init__()
        self.layer = layer
        self.source_field = source_field
        self.new_field_name = new_field_name
        self.is_running = True

    def run(self):
        try:
            if not self.is_running:
                return

            # 检查源字段是否存在
            if self.source_field not in [field.name() for field in self.layer.fields()]:
                self.update_progress.emit(0)
                self.finished_successfully.emit(0, 0)
                return

            self.update_progress.emit(5)  # 5% - 开始创建新图层

            # 创建新图层
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            new_layer_name = f"{self.layer.name()}_converted_{timestamp}"

            # 根据原始图层类型创建新图层
            geometry_type = self.layer.geometryType()
            crs = self.layer.crs()

            if geometry_type == 0:  # 点图层
                new_layer = QgsVectorLayer(f"Point?crs={crs.authid()}", new_layer_name, "memory")
            elif geometry_type == 1:  # 线图层
                new_layer = QgsVectorLayer(f"LineString?crs={crs.authid()}", new_layer_name, "memory")
            elif geometry_type == 2:  # 面图层
                new_layer = QgsVectorLayer(f"Polygon?crs={crs.authid()}", new_layer_name, "memory")
            else:
                self.update_progress.emit(0)
                self.finished_successfully.emit(0, 0)
                return

            # 复制原始图层的字段结构
            provider = new_layer.dataProvider()
            fields = self.layer.fields()

            # 添加所有原始字段
            provider.addAttributes(fields.toList())

            # 添加新的double类型字段
            new_field = QgsField(self.new_field_name, QVariant.Double)
            provider.addAttributes([new_field])

            new_layer.updateFields()

            self.update_progress.emit(10)  # 10% - 新图层创建完成

            # 获取字段索引
            source_field_index = self.layer.fields().indexFromName(self.source_field)
            new_field_index = new_layer.fields().indexFromName(self.new_field_name)

            if source_field_index == -1 or new_field_index == -1:
                self.update_progress.emit(0)
                self.finished_successfully.emit(0, 0)
                return

            success_count = 0
            error_count = 0
            total_features = self.layer.featureCount()

            if total_features == 0:
                self.update_progress.emit(100)
                self.layer_created.emit(new_layer)
                self.finished_successfully.emit(0, 0)
                return

            # 开始编辑新图层
            if not new_layer.startEditing():
                self.update_progress.emit(0)
                self.finished_successfully.emit(0, 0)
                return

            # 分批处理要素，避免内存问题
            batch_size = 100
            features_to_add = []

            for i, feature in enumerate(self.layer.getFeatures()):
                if not self.is_running:
                    new_layer.rollBack()
                    self.update_progress.emit(0)
                    return

                try:
                    # 创建新要素
                    new_feature = QgsFeature(new_layer.fields())

                    # 复制几何
                    new_feature.setGeometry(feature.geometry())

                    # 复制所有属性
                    for j, field in enumerate(self.layer.fields()):
                        if j < len(new_layer.fields()) - 1:  # 排除新添加的字段
                            new_feature.setAttribute(j, feature.attribute(j))

                    # 获取原始值并转换为double
                    original_value = feature.attribute(source_field_index)
                    double_value = self.convert_to_double(original_value)

                    # 设置新字段的值
                    new_feature.setAttribute(new_field_index, double_value)

                    features_to_add.append(new_feature)
                    success_count += 1

                except Exception as e:
                    error_count += 1
                    # 记录错误但继续处理其他要素

                # 每处理一批要素就添加到图层
                if len(features_to_add) >= batch_size:
                    if not new_layer.addFeatures(features_to_add):
                        error_count += len(features_to_add)
                        success_count -= len(features_to_add)
                    features_to_add = []  # 清空批次

                    # 更新进度 (10% - 90% 用于数据处理)
                    progress = 10 + int((i + 1) / total_features * 80)
                    self.update_progress.emit(min(progress, 90))

            # 处理剩余要素
            if features_to_add:
                if not new_layer.addFeatures(features_to_add):
                    error_count += len(features_to_add)
                    success_count -= len(features_to_add)

            self.update_progress.emit(95)  # 95% - 数据处理完成，准备提交

            # 提交更改到新图层
            if not self.is_running:
                new_layer.rollBack()
                self.update_progress.emit(0)
                return

            if not new_layer.commitChanges():
                self.update_progress.emit(0)
                self.finished_successfully.emit(0, error_count)
                return

            # 更新图层的范围
            new_layer.updateExtents()

            self.update_progress.emit(100)  # 100% - 完成

            # 发出图层创建信号
            self.layer_created.emit(new_layer)
            self.finished_successfully.emit(success_count, error_count)

        except Exception as e:
            self.update_progress.emit(0)
            self.finished_successfully.emit(0, 0)

    def convert_to_double(self, value):
        """
        将值转换为double类型
        对于无法转换的数据，返回-9999
        """
        # 处理空值
        if value is None:
            return -9999

        # 处理空字符串
        if isinstance(value, str) and not value.strip():
            return -9999

        # 如果已经是数字类型
        if isinstance(value, (int, float)):
            return float(value)

        # 尝试转换字符串
        if isinstance(value, str):
            try:
                # 移除可能的空格
                cleaned_value = value.strip()

                # 处理空字符串
                if not cleaned_value:
                    return -9999

                # 尝试直接转换
                return float(cleaned_value)
            except (ValueError, TypeError):
                # 如果直接转换失败，尝试处理特殊情况
                try:
                    # 处理科学计数法
                    if 'e' in cleaned_value.lower():
                        return float(cleaned_value)

                    # 处理百分比
                    if '%' in cleaned_value:
                        num_part = cleaned_value.replace('%', '').strip()
                        return float(num_part) / 100.0

                    # 处理逗号分隔的数字（如1,000.50）
                    if ',' in cleaned_value:
                        # 假设逗号是千位分隔符
                        cleaned_value = cleaned_value.replace(',', '')
                        return float(cleaned_value)

                    # 如果包含非数字字符，尝试提取数字部分
                    numbers = re.findall(r"[-+]?\d*\.\d+|\d+", cleaned_value)
                    if numbers:
                        return float(numbers[0])
                    else:
                        return -9999
                except (ValueError, TypeError):
                    return -9999

        # 其他无法处理的类型
        return -9999

    def stop(self):
        """停止线程"""
        self.is_running = False