# cadastre_manager.py

import re

from qgis.PyQt.QtWidgets import QMessageBox, QProgressDialog, QApplication
from qgis.PyQt.QtCore import QCoreApplication

from qgis.core import (
    QgsField,
    Qgis,
    QgsMessageLog,
)

from qgis.PyQt import QtCore, QtGui, QtWidgets

from .utils import tr, couche_a_contenu

from .compat_qt import QVariant, WindowModal

def creer_champs_france(self, layer, remplir=False, no_section=False):
    """Crée les champs section et numero pour le cadastre français"""

    if not layer.startEditing():
        QMessageBox.warning(
            self,
            tr("Erreur"),
            tr("Impossible de passer en mode édition")
        )
        return

    noms_existants = {f.name().lower() for f in layer.fields()}
    champs_a_ajouter = []

    if "section" not in noms_existants:
        champs_a_ajouter.append(QgsField("section", QVariant.String))
    if "numero" not in noms_existants:
        champs_a_ajouter.append(QgsField("numero", QVariant.String))

    progress = QProgressDialog(tr("Ajout des champs..."), tr("Annuler"), 0, len(champs_a_ajouter), self)
    progress.setWindowTitle(tr("Traitement en cours"))
    progress.setWindowModality(WindowModal)
    progress.setMinimumDuration(0)

    success = True
    for i, field in enumerate(champs_a_ajouter):
        if not layer.dataProvider().addAttributes([field]):
            success = False
            break
        progress.setValue(i + 1)
        QApplication.processEvents()

    if not success:
        layer.rollBack()
        progress.close()
        QMessageBox.critical(
            self,
            tr("Erreur"),
            tr("Échec lors de l'ajout des champs")
        )
        return

    layer.updateFields()

    if remplir:
        idx_section = layer.fields().indexFromName("section")
        idx_numero = layer.fields().indexFromName("numero")

        feats = list(layer.getFeatures())
        total_feats = len(feats)

        progress.setLabelText(
            tr("Remplissage des champs numero...") if no_section
            else tr("Remplissage des champs section et numero...")
        )
        progress.setMaximum(total_feats)

        for i, feat in enumerate(feats):
            id_val = str(feat["id"])
            if no_section:
                match = re.match(r"^\d+[A-Za-z]{0,2}0*(\d+)$", id_val)
                if match:
                    numero = str(int(match.group(1)))
                    layer.changeAttributeValue(feat.id(), idx_numero, numero)
                    layer.changeAttributeValue(feat.id(), idx_section, "")
                else:
                    msg = tr("Format de l'identifiant invalide : {id}").format(id=id_val)
                    QgsMessageLog.logMessage(msg, "Plugin", level=Qgis.Warning)
            else:
                match = re.match(r"^\d+([A-Za-z]{1,2})0*(\d+)$", id_val)
                if match:
                    section, numero = match.groups()
                    section = section.upper()
                    numero = str(int(numero))
                    layer.changeAttributeValue(feat.id(), idx_section, section)
                    layer.changeAttributeValue(feat.id(), idx_numero, numero)
                else:
                    msg = tr("Format de l'identifiant invalide : {id}").format(id=id_val)
                    QgsMessageLog.logMessage(msg, "Plugin", level=Qgis.Warning)

            if progress.wasCanceled():
                layer.rollBack()
                progress.close()
                QMessageBox.information(
                    self,
                    tr("Annulé"),
                    tr("Opération annulée par l'utilisateur")
                )
                return

            if i % 10 == 0 or i == total_feats - 1:
                progress.setValue(i + 1)
                QApplication.processEvents()

    if not layer.commitChanges():
        QMessageBox.critical(
            self,
            tr("Erreur"),
            tr("Échec lors de l'enregistrement des modifications")
        )
    else:
        QMessageBox.information(
            self,
            tr("Succès"),
            tr("Champs créés (et remplis) avec succès")
        )

    progress.close()

def creer_champs_luxembourg(layer, remplir=True, parent=None):

    if remplir and not couche_a_contenu(layer):
        QMessageBox.warning(
            parent,
            tr("Table vide"),
            tr("La couche ne contient aucune donnée exploitable. Veuillez vérifier son contenu.")
        )
        return False

    # Vérification du nombre de lignes
    total_lignes = layer.featureCount()
    if total_lignes > 15000:
        QMessageBox.warning(
            parent,
            tr("Trop de données"),
            tr(f"Votre table comporte {total_lignes} lignes.\n"
               "Merci de créer une couche d'une partie (ville) avant de continuer.")
        )
        return False

    noms_existants = {f.name().lower() for f in layer.fields()}

    champs_a_ajouter = []
    if "id" not in noms_existants:
        champs_a_ajouter.append(QgsField("id", QVariant.String, len=50))
    if "section" not in noms_existants:
        champs_a_ajouter.append(QgsField("section", QVariant.String))
    if "numero" not in noms_existants:
        champs_a_ajouter.append(QgsField("numero", QVariant.String))
    if "contenance" not in noms_existants:
        champs_a_ajouter.append(QgsField("contenance", QVariant.Int))

    print("Champs dans la couche :")
    for f in layer.fields():
        print(f.name())

    if champs_a_ajouter:
        progress = QProgressDialog(tr("Ajout des champs..."), tr("Annuler"), 0, len(champs_a_ajouter), parent)
        progress.setWindowTitle(tr("Traitement en cours"))
        progress.setWindowModality(WindowModal)
        progress.setMinimumDuration(0)

        success = True
        for i, field in enumerate(champs_a_ajouter):
            if not layer.dataProvider().addAttributes([field]):
                success = False
                break
            progress.setValue(i + 1)
            QApplication.processEvents()

        if not success:
            progress.close()
            QMessageBox.critical(parent, tr("Erreur"), tr("Échec lors de l'ajout des champs"))
            return False

        layer.updateFields()
        progress.close()

    if remplir:
        print("Entrée dans le remplissage")
        if not layer.startEditing():
            QMessageBox.warning(parent, tr("Erreur"), tr("Impossible de passer en mode édition"))
            return False
        else:
            print("Mode édition activé :", layer.isEditable())

        champs_sources = {f.name().lower(): f.name() for f in layer.fields()}
        id_source = champs_sources.get("id_parcell")
        section_source = champs_sources.get("code_secti")
        numero_source = champs_sources.get("numero_sec")


        print("DEBUG - Champs sources disponibles :")
        print(champs_sources)
        print(f"id_source = {id_source}")
        print(f"section_source = {section_source}")
        print(f"numero_source = {numero_source}")


        idx_id = layer.fields().indexFromName("id")
        idx_section = layer.fields().indexFromName("section")
        idx_numero = layer.fields().indexFromName("numero")
        idx_contenance = layer.fields().indexFromName("contenance")

        print(f"Indices : id={idx_id}, section={idx_section}, numero={idx_numero}, contenance={idx_contenance}")

        feats = list(layer.getFeatures())
        total_feats = len(feats)
        progress = QProgressDialog(tr("Remplissage des champs..."), tr("Annuler"), 0, total_feats, parent)
        progress.setWindowTitle(tr("Traitement en cours"))
        progress.setWindowModality(WindowModal)
        progress.setMinimumDuration(0)
        progress.setValue(0)

        for i, feat in enumerate(feats):
            id_val = str(feat[id_source]) if id_source and feat[id_source] is not None else ""
            section_val = str(feat[section_source]) if section_source and feat[section_source] is not None else ""

            numero_val = str(feat[numero_source]) if numero_source and feat[numero_source] is not None else ""

            surface_val = int(feat.geometry().area()) if feat.geometry() else None

            layer.changeAttributeValue(feat.id(), idx_id, id_val)
            print(f"Modif id feature {feat.id()} à {id_val}")

            layer.changeAttributeValue(feat.id(), idx_section, section_val)
            layer.changeAttributeValue(feat.id(), idx_numero, numero_val)
            layer.changeAttributeValue(feat.id(), idx_contenance, surface_val)

            if progress.wasCanceled():
                layer.rollBack()
                progress.close()
                QMessageBox.information(parent, tr("Annulé"), tr("Opération annulée par l'utilisateur"))
                return False

            if i % 10 == 0 or i == total_feats - 1:
                progress.setValue(i + 1)
                QApplication.processEvents()

        if not layer.commitChanges():
            QMessageBox.critical(parent, tr("Erreur"), tr("Échec lors de l'enregistrement des modifications"))
            return False
        else:
            QMessageBox.information(parent, tr("Succès"), tr("Champs créés (et remplis) avec succès"))

            # Appel à la création des autres champs du plugin
        if hasattr(parent, "create_fields_table"):
            parent.create_fields_table(layer)
        else:
            print("DEBUG: create_fields_table non trouvée dans parent")

    return True

def creer_champs_belgique(layer, remplir=True, parent=None):

    if remplir and not couche_a_contenu(layer):
        QMessageBox.warning(
            parent,
            tr("Table vide"),
            tr("La couche ne contient aucune donnée exploitable. Veuillez vérifier son contenu.")
        )
        return False

    total_lignes = layer.featureCount()
    if total_lignes > 15000:
        QMessageBox.warning(
            parent,
            tr("Trop de données"),
            tr(f"Votre table comporte {total_lignes} lignes.\n"
               "Merci de créer une couche d'une partie (ville) avant de continuer.")
        )
        return False

    noms_existants = {f.name().lower() for f in layer.fields()}

    champs_a_ajouter = []
    if "reid" not in noms_existants:
        champs_a_ajouter.append(QgsField("id", QVariant.String, len=50))
    if "section" not in noms_existants:
        champs_a_ajouter.append(QgsField("section", QVariant.String))
    if "numero" not in noms_existants:
        champs_a_ajouter.append(QgsField("numero", QVariant.String))
    if "contenance" not in noms_existants:
        champs_a_ajouter.append(QgsField("contenance", QVariant.Int))

    if champs_a_ajouter:
        progress = QProgressDialog(tr("Ajout des champs..."), tr("Annuler"), 0, len(champs_a_ajouter), parent)
        progress.setWindowTitle(tr("Ajout de champs"))
        progress.setWindowModality(WindowModal)
        progress.setMinimumDuration(0)

        success = True
        for i, field in enumerate(champs_a_ajouter):
            if not layer.dataProvider().addAttributes([field]):
                success = False
                break
            progress.setValue(i + 1)
            QApplication.processEvents()

        if not success:
            progress.close()
            QMessageBox.critical(parent, tr("Erreur"), tr("Échec lors de l'ajout des champs"))
            return False

        layer.updateFields()
        progress.close()

    if remplir:
        if not layer.startEditing():
            QMessageBox.warning(parent, tr("Erreur"), tr("Impossible de passer en mode édition"))
            return False

        champs_sources = {f.name().lower(): f.name() for f in layer.fields()}
        capa_source = champs_sources.get("capakey")
        case_source = champs_sources.get("casekey")
        area_source = champs_sources.get("shape_area")

        if not capa_source or not case_source or not area_source:
            QMessageBox.critical(parent, tr("Erreur"),
                                 tr("Champs source manquants : CaPaKey, CaSeKey ou Shape_area"))
            return False

        idx_id = layer.fields().indexFromName("ReId")
        idx_section = layer.fields().indexFromName("section")
        idx_numero = layer.fields().indexFromName("numero")
        idx_contenance = layer.fields().indexFromName("contenance")

        feats = list(layer.getFeatures())
        total_feats = len(feats)
        progress = QProgressDialog(tr("Remplissage des champs..."), tr("Annuler"), 0, total_feats, parent)
        progress.setWindowTitle(tr("Traitement en cours"))
        progress.setWindowModality(WindowModal)
        progress.setMinimumDuration(0)
        progress.setValue(0)

        for i, feat in enumerate(feats):
            capa_val = str(feat[capa_source]) if feat[capa_source] else ""
            case_val = str(feat[case_source]) if feat[case_source] else ""
            area_val = feat[area_source]

            reid_val = capa_val
            section_val = case_val
            numero_val = capa_val.split("/")[0] if "/" in capa_val else ""

            try:
                contenance_val = int(float(area_val))
            except (ValueError, TypeError):
                contenance_val = None

            layer.changeAttributeValue(feat.id(), idx_id, reid_val)
            layer.changeAttributeValue(feat.id(), idx_section, section_val)
            layer.changeAttributeValue(feat.id(), idx_numero, numero_val)
            layer.changeAttributeValue(feat.id(), idx_contenance, contenance_val)

            if progress.wasCanceled():
                layer.rollBack()
                progress.close()
                QMessageBox.information(parent, tr("Annulé"), tr("Opération annulée par l'utilisateur"))
                return False

            if i % 10 == 0 or i == total_feats - 1:
                progress.setValue(i + 1)
                QApplication.processEvents()

        if not layer.commitChanges():
            QMessageBox.critical(parent, tr("Erreur"), tr("Échec lors de l'enregistrement des modifications"))
            return False
        else:
            QMessageBox.information(parent, tr("Succès"), tr("Champs créés (et remplis) avec succès"))

        if hasattr(parent, "create_fields_table"):
            parent.create_fields_table(layer)

    return True


def creer_champs_france_like(layer, remplir=True, parent=None):


    if remplir and not couche_a_contenu(layer):
        QMessageBox.warning(
            parent,
            tr("Table vide"),
            tr("La couche ne contient aucune donnée exploitable. Veuillez vérifier son contenu.")
        )
        return False


    total_lignes = layer.featureCount()
    if total_lignes > 15000:
        QMessageBox.warning(
            parent,
            tr("Trop de données"),
            tr(f"Votre table comporte {total_lignes} lignes.\n"
               "Merci de créer une couche d'une zone plus petite.")
        )
        return False

    noms_existants = {f.name().lower(): f.name() for f in layer.fields()}

    # Champs à ajouter si absents
    champs_a_ajouter = []
    if "id" not in noms_existants:
        champs_a_ajouter.append(QgsField("id", QVariant.String))
    if "section" not in noms_existants:
        champs_a_ajouter.append(QgsField("section", QVariant.String))
    if "numero" not in noms_existants:
        champs_a_ajouter.append(QgsField("numero", QVariant.String))
    if "contenance" not in noms_existants:
        champs_a_ajouter.append(QgsField("contenance", QVariant.Int))

    # Ajout des champs
    if champs_a_ajouter:
        progress = QProgressDialog(tr("Ajout des champs..."), tr("Annuler"), 0, len(champs_a_ajouter), parent)
        progress.setWindowTitle(tr("Ajout en cours"))
        progress.setWindowModality(WindowModal)

        for i, field in enumerate(champs_a_ajouter):
            layer.dataProvider().addAttributes([field])
            progress.setValue(i + 1)
            QApplication.processEvents()

        layer.updateFields()
        progress.close()

    if remplir:
        if not layer.startEditing():
            QMessageBox.warning(parent, tr("Erreur"), tr("Impossible de passer en mode édition"))
            return False

        # Correspondances automatiques avec noms de champs souples
        def champ_possible(possibles):
            for key in possibles:
                if key in noms_existants:
                    return noms_existants[key]
            return None

        id_src = champ_possible(["id", "idu", "id_parcelle", "identifiant"])
        section_src = champ_possible(["section", "sec", "code_section"])
        numero_src = champ_possible(["numero", "num", "num_parcelle", "lot"])
        contenance_src = champ_possible(["contenance", "surface", "superficie"])

        idx_id = layer.fields().indexFromName("id")
        idx_section = layer.fields().indexFromName("section")
        idx_numero = layer.fields().indexFromName("numero")
        idx_contenance = layer.fields().indexFromName("contenance")

        feats = list(layer.getFeatures())
        progress = QProgressDialog(tr("Remplissage des champs..."), tr("Annuler"), 0, len(feats), parent)
        progress.setWindowTitle(tr("Remplissage en cours"))
        progress.setWindowModality(WindowModal)

        for i, feat in enumerate(feats):
            id_val = str(feat[id_src]) if id_src and feat[id_src] else ""
            section_val = str(feat[section_src]) if section_src and feat[section_src] else ""
            numero_val = str(feat[numero_src]) if numero_src and feat[numero_src] else ""

            if contenance_src and feat[contenance_src] is not None:
                try:
                    contenance_val = int(float(feat[contenance_src]))
                except ValueError:
                    contenance_val = None
            else:
                contenance_val = int(feat.geometry().area()) if feat.geometry() else None

            layer.changeAttributeValue(feat.id(), idx_id, id_val)
            layer.changeAttributeValue(feat.id(), idx_section, section_val)
            layer.changeAttributeValue(feat.id(), idx_numero, numero_val)
            layer.changeAttributeValue(feat.id(), idx_contenance, contenance_val)

            if progress.wasCanceled():
                layer.rollBack()
                return False

            if i % 10 == 0 or i == len(feats) - 1:
                progress.setValue(i + 1)
                QApplication.processEvents()

        layer.commitChanges()
        QMessageBox.information(parent, tr("Succès"), tr("Champs créés et remplis avec succès"))

        if hasattr(parent, "create_fields_table"):
            parent.create_fields_table(layer)

    return True

def creer_champs_suisse(layer, remplir=True, parent=None):

    if remplir and not couche_a_contenu(layer):
        QMessageBox.warning(
            parent,
            tr("Table vide"),
            tr("La couche ne contient aucune donnée exploitable. Veuillez vérifier son contenu.")
        )
        return False

    noms_existants = {f.name().lower(): f.name() for f in layer.fields()}
    champs_a_ajouter = []

    if "id" not in noms_existants:
        champs_a_ajouter.append(QgsField("id", QVariant.String))
    if "section" not in noms_existants:
        champs_a_ajouter.append(QgsField("section", QVariant.String))
    if "numero" not in noms_existants:
        champs_a_ajouter.append(QgsField("numero", QVariant.String))
    if "contenance" not in noms_existants:
        champs_a_ajouter.append(QgsField("contenance", QVariant.Int))

    if champs_a_ajouter:
        layer.dataProvider().addAttributes(champs_a_ajouter)
        layer.updateFields()

    if remplir:
        if not layer.startEditing():
            QMessageBox.warning(parent, tr("Erreur"), tr("Impossible de passer en mode édition"))
            return False

        champs_sources = noms_existants
        id_src = champs_sources.get("egrid")
        numero_src = champs_sources.get("parcelnumber")
        contenance_src = champs_sources.get("area_m2")

        idx_id = layer.fields().indexFromName("id")
        idx_section = layer.fields().indexFromName("section")
        idx_numero = layer.fields().indexFromName("numero")
        idx_contenance = layer.fields().indexFromName("contenance")

        feats = list(layer.getFeatures())
        for feat in feats:
            id_val = str(feat[id_src]) if id_src and feat[id_src] else ""
            numero_val = str(feat[numero_src]) if numero_src and feat[numero_src] else ""
            try:
                contenance_val = int(float(feat[contenance_src])) if contenance_src else int(feat.geometry().area())
            except Exception:
                contenance_val = None

            layer.changeAttributeValue(feat.id(), idx_id, id_val)
            layer.changeAttributeValue(feat.id(), idx_numero, numero_val)
            layer.changeAttributeValue(feat.id(), idx_contenance, contenance_val)
            layer.changeAttributeValue(feat.id(), idx_section, "")  # champ vide

        if not layer.commitChanges():
            QMessageBox.critical(parent, tr("Erreur"), tr("Échec lors de l'enregistrement"))
            return False
        else:
            QMessageBox.information(parent, tr("Succès"), tr("Champs ajoutés avec succès"))

        if hasattr(parent, "create_fields_table"):
            parent.create_fields_table(layer)

    return True
