import os
import pathlib
import re

import chardet
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