import configparser
import os
import re

import psycopg2
from qgis.core import (
    Qgis,
    QgsExpressionContextUtils,
    QgsFeatureRequest,
    QgsMapLayer,
    QgsMessageLog,
    QgsProject,
    QgsRectangle,
)
from qgis.PyQt.QtWidgets import QMessageBox
from qgis.PyQt.QtXml import QDomDocument

from plui_versionning.toolbelt.log_handler import PlgLogger

#####################################################################
#               Mise en place des variables globales                #
#####################################################################

plg_logger = PlgLogger()

# Environnement applicatif de l'outil
INPUT_DIR_SCRIPT = os.path.dirname(os.path.realpath(__file__))  # Répertoire courant
config = configparser.ConfigParser()
config.read(
    os.path.join(INPUT_DIR_SCRIPT, "conf", "config.ini")
)  # Emplacement du fichier de config
service_conf = config.get(
    "ENVIRONNEMENT", "source"
)  # Récupération de la variable d'environnement applicatif

# Récupération de l'instance de projet
project = QgsProject.instance()
arbo_versionning = project.layerTreeRoot().children()[0].findGroup("VERSIONNING")
arbo_referentiel = project.layerTreeRoot().children()[0].findGroup("REFERENTIEL")

#####################################################################
#       En deux parties :                                           #
#           - capitalisation du code python (fonctions              #
#               réutilisées dans le code des actions)               #
#           - Les actions telles quelles                            #
#####################################################################


#####################################################################
#                       CAPITALISATION                              #
#####################################################################
# Permet de mémoriser pour chaque utilisateur la dernière version chargée (évite les soucis d'identifiant lors d'un copier-coller)
def func_charger_contexte(qgis, id_version):
    sql = (
        "INSERT INTO urba_plui_ecriture.v__pluiv_contexte_utilisateur (current_version, classe_entite) VALUES ('"
        + id_version
        + "', '"
        + func_recuperer_classe_entite(qgis, id_version)
        + "')"
    )

    func_executer_sql(qgis, sql, "Chargement contexte utilisateur")


# Execute la requête SQL passée en argument
def func_executer_sql(qgis, sql, msg):
    try:
        with psycopg2.connect("service=" + service_conf) as cnx:
            with cnx.cursor() as cursor:
                # QgsMessageLog.logMessage(u'Traitement de la requête : "' + msg + '"', 'Versionning PLUi', 0)
                # QgsMessageLog.logMessage('sql : ' + sql, 'Versionning PLUi', 0)
                cursor.execute(sql)

                # QgsMessageLog.logMessage('cursor.statusmessage :' +  str(cursor.statusmessage), 'Versionning PLUi', 0)

                if (
                    "SELECT" in cursor.statusmessage
                ):  # Cas où la requête renvoie un résultat
                    result = cursor.fetchall()
                    # QgsMessageLog.logMessage(u'Résultat renvoyé : ' + str(result), 'Versionning PLUi', 0)
                    return result  # Renvoie les résultats de la requête

    except Exception as e:
        raise e
        # qgis.utils.iface.messageBar().pushMessage("Erreur", u'Impossible de traiter la requête "' + msg + '" : ' + str(e), level=Qgis.Critical)


# extraction des éléments d'une version
def func_extraire_params_version(id_version):
    dict = {
        "cycle": id_version[:3],
        "num_cycle": id_version[1:3],
        "thematique": id_version[4:7],
        "classe": id_version[4],
        "cnig": id_version[5:7],
        "num_proj": id_version[8:11],
        "num_version": id_version[-2:],
    }
    return dict


# retourne la classe d'entité en fonction de la lettre de thématique de la version
def func_recuperer_classe_entite(qgis, id_version):
    classe = func_extraire_params_version(id_version)["classe"]
    # QgsMessageLog.logMessage('classe : ' + classe, 'Versionning PLUi', 0)
    if classe == "Z":
        classe_entite = "zoneurba"
    elif classe == "P":
        classe_entite = "prescription"
    elif classe == "I":
        classe_entite = "information"
    elif classe == "H":
        classe_entite = "habillage"
    else:
        # TODO stopper fonction
        plg_logger.log(
            message="Problème sur le nommage de l'identifiant de version",
            log_level=2,
            push=True,
            duration=30,
        )

    return classe_entite


# Réinitialise le style par défaut des prescriptions/informations
def func_reinitialiser_style(classe_entite):
    for geomtype in ["pct", "lin", "surf", "txt"]:
        current_layer = project.mapLayer(
            "v_" + classe_entite + "_" + geomtype + "_layer"
        )
        if current_layer is not None:
            # print('AVANT RESET / Styles ' + current_layer.name() + ' : ' + ', '.join(current_layer.styleManager().styles()))
            style_manager = current_layer.styleManager()
            style_manager.removeStyle(
                "plui"
            )  # Supprime l'éventuel style PLUI déjà chargé auparavant
            # print('APRES RESET / Styles ' + current_layer.name() + ' : ' + ', '.join(current_layer.styleManager().styles()))


# rafraichit le style des prescriptions / informations en fonction de la version affichée
def func_charger_style(qgis, num_cycle, classe_entite, code_cnig):
    func_reinitialiser_style(
        classe_entite
    )  # Supprime l'éventuel style PLUI déjà chargé auparavant

    sql = (
        "SELECT layerid, stylename FROM urba_plui_ecriture._pluiv_corresp_layer_styles WHERE cycle_plui = '"
        + num_cycle
        + "' AND cnig = '"
        + code_cnig
        + "' AND layerid LIKE 'v_"
        + classe_entite
        + "%'"
    )
    # QgsMessageLog.logMessage('sql : ' + sql, 'Versionning PLUi', 0)

    # Récupération des nom de styles à charger
    result = func_executer_sql(qgis, sql, "Recherche style QML")
    # QgsMessageLog.logMessage('func_charger_style result : ' + str(result), 'Versionning PLUi', 0)

    if result is not None and len(result) > 0:
        for current_style in result:
            layerid, stylename = current_style
            # QgsMessageLog.logMessage('layerid : ' + layerid + ', stylename : ' + stylename, 'Versionning PLUi', 0)

            sql = (
                "SELECT styleqml FROM public.layer_styles WHERE f_table_schema = 'urba_plui_ecriture' AND f_table_name = '"
                + layerid
                + "' AND stylename = '"
                + stylename
                + "'"
            )
            QgsMessageLog.logMessage("sql : " + sql, "Versionning PLUi", 0)
            styleqml = func_executer_sql(qgis, sql, "Chargement style QML")

            if styleqml is not None and len(styleqml) > 0:
                # QgsMessageLog.logMessage('styleqml : ' + str(styleqml), 'Versionning PLUi', 0)

                current_layer = project.mapLayer(layerid + "_layer")

                style_manager = current_layer.styleManager()
                style_manager.addStyleFromLayer(
                    "plui"
                )  # Copie le style par défaut comme sauvegarde (et permettre le chargement du style 'plui')
                style_manager.setCurrentStyle(
                    "plui"
                )  # Calage sur ce style avant mise à jour du contenu

                styledoc = QDomDocument()
                styledoc.setContent(styleqml[0][0])
                current_layer.importNamedStyle(
                    styledoc, QgsMapLayer.Symbology, QgsMapLayer.Labeling
                )

                qgis.utils.iface.messageBar().pushMessage(
                    "Info",
                    "Style mis à jour sur la couche " + layerid,
                    level=Qgis.Info,
                    duration=3,
                )

            else:
                QMessageBox.warning(
                    qgis.utils.iface.mainWindow(),
                    "Erreur(s)",
                    "Une correspondance de style a été trouvée dans la table urba_plui_ecriture._pluiv_corresp_layer_styles <br> mais le style est absent de la table public.layer_styles <br> layerid : <b>"
                    + layerid
                    + "</b>, stylename : <b>"
                    + stylename
                    + "</b>",
                )
    else:
        qgis.utils.iface.messageBar().pushMessage(
            "Info",
            "Pas de style spécifique trouvé pour cette version",
            level=Qgis.Info,
            duration=2,
        )


# Recale les filtres des couches du groupe "VERSIONNING" lors d'un changement de cycle ou pr l'affichage de toutes les études
def func_reinitialiser_filtres(num_cycle):
    # Tables de référence
    for layer in arbo_referentiel.findLayers():
        if layer.parent().name() == "Administration":
            filter = "lib_cycle_plui=" + str(num_cycle)
            layer.layer().setSubsetString(filter)

    for layer in arbo_versionning.findLayers():
        if layer.parent().name() == "Espace de travail":
            if layer.name() == "Versions DE REFERENCE":
                num_cycle_filter = num_cycle - 1
            else:
                num_cycle_filter = num_cycle
            filter = (
                "cycle_plui="
                + str(num_cycle_filter)
                + " AND thematique LIKE '"
                + layer.parent().parent().name()[0]
                + "%'"
            )
            layer.layer().setSubsetString(filter)
        else:  # 'Espace carto'
            layer.setName(layer.layer().id()[2:-6].replace("_", " ").upper() + ":")
            filter = "idurba is null"
            layer.layer().setSubsetString(filter)
            layer.layer().styleManager().removeStyle("plui")


#####################################################################
#                       LES ACTIONS                                 #
#####################################################################


# Permet de changer de cycle directement dans le même projet
def changer_cycle(qgis, num_cycle):
    if num_cycle == 1:
        QMessageBox.warning(
            qgis.utils.iface.mainWindow(),
            "Attention",
            "Désolé. Pas de chargement possible du cycle #1",
        )
    else:
        # Mise à jour du nom de la racine de l'arbre
        # root_gp = project.layerTreeRoot().children()[0]
        # print('root_gp: ' , type(root_gp))
        arbo_versionning.parent().setName("PLUi - Cycle #" + str(num_cycle))

        # Mise à jour des filtres SQL dans le groupe "VERSIONNING"
        func_reinitialiser_filtres(num_cycle)

        # Activation/Désactivation de l'édition selon si le cycle à charger est gelé ou non
        sql = (
            "SELECT urba_plui_ecriture.func_verifier_statut_cycle("
            + str(num_cycle)
            + ")"
        )
        cycle_actif = func_executer_sql(qgis, sql, "Vérifier statut cycle")[0][0]
        print("cycle_actif: " + str(cycle_actif))
        for layer in arbo_versionning.findLayers():
            if layer.parent().name() == "Espace de travail":
                if not cycle_actif or layer.name() == "Versions DE REFERENCE":
                    # print(str(layer.layer()) + ' : lecture seule')
                    layer.layer().setReadOnly(True)
                else:
                    # print(str(layer.layer()) + ' : couche active')
                    layer.layer().setReadOnly(False)
            else:  # 'Espace carto'
                if not cycle_actif or "SUPPR" in layer.name():
                    # print(str(layer.layer()) + ' : lecture seule')
                    layer.layer().setReadOnly(True)
                else:
                    # print(str(layer.layer()) + ' : couche active')
                    layer.layer().setReadOnly(False)

        # Mise à jour du filtre SQL pour la couche "Projets cycle courant" (si elle existe)
        projects_layer = project.mapLayer(
            "Projets_cycle_courant_628b67ba_afaa_404c_8bae_0f0f17191229"
        )
        if projects_layer is not None:
            filter = "cycle_plui=" + str(num_cycle)
            projects_layer.setSubsetString(filter)

        # Mise à jour du filtre SQL pour la couche "Suivi des études" (si elle existe)
        studies_layer = project.mapLayer(
            "Suivi_des_études_7f83d72f_c100_4f07_b9de_1a9f5e020bca"
        )
        if studies_layer is not None:
            filter = "num_cycle=" + str(num_cycle)
            studies_layer.setSubsetString(filter)

        # Chargement du thème par défaut
        # qgis.utils.iface.mapCanvas().setTheme('default') --> TODO: envoyer ticket à Oslandia
        # qgis.utils.iface.mapCanvas().refresh()

        # Suppression des éventuelles variables déjà chargées
        QgsExpressionContextUtils.removeProjectVariable(project, "pluiv_num_cycle")
        QgsExpressionContextUtils.removeProjectVariable(
            project, "pluiv_version_z_courante"
        )
        QgsExpressionContextUtils.removeProjectVariable(
            project, "pluiv_version_p_courante"
        )
        QgsExpressionContextUtils.removeProjectVariable(
            project, "pluiv_version_i_courante"
        )
        QgsExpressionContextUtils.removeProjectVariable(
            project, "pluiv_version_h_courante"
        )

        # Mise à jour de la variable pluiv_num_cycle
        QgsExpressionContextUtils.setProjectVariable(
            project, "pluiv_num_cycle", num_cycle
        )

        # Pop-up de notif
        QMessageBox.information(
            qgis.utils.iface.mainWindow(),
            "Info",
            "Le cycle #" + str(num_cycle) + " a été chargé avec succès",
        )


# Permet d'initier un nouveau cycle
def initier_nouveau_cycle(qgis, trigramme_epci):
    try:
        # Vérification d'un éventuel cycle déjà en cours
        if len(trigramme_epci) != 3:
            raise Exception(
                "Le trigramme EPCI doit obligatoirement être de 3 caractères. Se reporter à la variable projet <i>project_trigramme_epci</i>"
            )

        # TODO : pourquoi upper (le trigramme est déjà en majuscule) ?
        # Ajouter le num cycle ref dans la fonction

        # sql = 'SELECT urba_plui_ecriture.admin_initier_nouvelle_procedure(\'' + trigramme_epci + '\')'
        # func_executer_sql(qgis, sql, 'Initier nouvelle procedure')

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible d'initier une nouvelle procédure : " + str(e),
            level=Qgis.Critical,
        )


# Récupère la version sélectionnée
def charger_entite(layer_id, feature_id):
    # récupération des données depuis la ligne cliquée
    layer = project.mapLayer(layer_id)
    request = QgsFeatureRequest().setFilterFid(feature_id)
    feature = next(layer.getFeatures(request))

    return feature


# Verifie si des entites n'ont pas de geometrie
def verifier_geometries(qgis, feature):
    try:
        # récupération des attributs de la version cliquée
        id_version = feature["id_version"]

        # requete SQL
        sql = (
            "SELECT urba_plui_ecriture.qgis_verifier_geometries('" + id_version + "');"
        )
        result = func_executer_sql(qgis, sql, "Vérifier les géométries")

        if result[0][0] == "OK":
            QMessageBox.information(
                qgis.utils.iface.mainWindow(), "Info", "Tout est OK !"
            )
        else:
            QMessageBox.warning(
                qgis.utils.iface.mainWindow(), "Erreur(s)", result[0][0]
            )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de vérifier les géométries : " + str(e),
            level=Qgis.Critical,
        )


# Affiche la version sélectionnée
def afficher_version(qgis, classe_entite, feature):
    # récupération des données
    id_version = feature["id_version"]
    version_params = func_extraire_params_version(id_version)

    # Chargement de la variable de version sélectionnée
    QgsExpressionContextUtils.setProjectVariable(
        project,
        "pluiv_version_" + version_params["classe"].lower() + "_courante",
        id_version,
    )

    # Chargement du contexte utilisateur
    func_charger_contexte(qgis, id_version)

    # Chargement des couches (sélection, zoom et renommage)
    filter = "/*&*/idurba is null/*&*/"
    extent = QgsRectangle()
    extent.setMinimal()

    if classe_entite == "zoneurba":
        current_layer = project.mapLayer("v_" + classe_entite + "_layer")
        version_filter = re.sub(
            "&.*&", "&*/idurba='" + id_version + "'/*&", filter, flags=re.DOTALL
        )
        current_layer.setSubsetString(version_filter)
        current_layer.setName("ZONAGE:" + id_version)

        # Coche la couche pour être visible
        project.layerTreeRoot().findLayer(current_layer).setItemVisibilityChecked(True)
        # Zoome sur la couche
        qgis.utils.iface.mapCanvas().setExtent(current_layer.extent())

        current_layer = project.mapLayer("v_" + classe_entite + "_suppr_layer")
        current_layer.setSubsetString(version_filter)
        current_layer.setName("ZONAGE *suppr*:" + id_version)

    elif classe_entite in ("prescription", "information"):
        for geomtype in ["pct", "lin", "surf"]:
            current_layer = project.mapLayer(
                "v_" + classe_entite + "_" + geomtype + "_layer"
            )
            version_filter = re.sub(
                "&.*&",
                "&*/idurba='" + id_version + "' AND geom_" + geomtype + " <> ''/*&",
                filter,
                flags=re.DOTALL,
            )
            current_layer.setSubsetString(version_filter)
            current_layer.setName(
                classe_entite.upper() + " " + geomtype.upper() + ":" + id_version
            )

            # Coche la couche comme visible
            project.layerTreeRoot().findLayer(current_layer).setItemVisibilityChecked(
                True
            )

            # print('nb objets : ' + str(current_layer.featureCount ()))
            if (
                current_layer.featureCount() > 0
            ):  # zoom sur l'étendue de la couche (si elle contient des objets)
                extent.combineExtentWith(current_layer.extent())

            # Couches de entités supprimées...
            current_layer = project.mapLayer(
                "v_" + classe_entite + "_" + geomtype + "_suppr_layer"
            )
            current_layer.setSubsetString(version_filter)
            current_layer.setName(
                classe_entite.upper()
                + " "
                + geomtype.upper()
                + " *suppr*:"
                + id_version
            )

    # TODO : utile ?
    else:  # Habillage
        for geomtype in ["pct", "lin", "surf", "txt"]:
            current_layer = project.mapLayer(
                "v_" + classe_entite + "_" + geomtype + "_layer"
            )
            version_filter = re.sub(
                "&.*&",
                "&*/idurba='" + id_version + "' AND geom_" + geomtype + " <> ''/*&",
                filter,
                flags=re.DOTALL,
            )
            current_layer.setSubsetString(version_filter)
            current_layer.setName(
                classe_entite.upper() + " " + geomtype.upper() + ":" + id_version
            )

            # Coche la couche comme visible
            project.layerTreeRoot().findLayer(current_layer).setItemVisibilityChecked(
                True
            )
            # Zoome sur la couche
            qgis.utils.iface.mapCanvas().setExtent(current_layer.extent())

            current_layer = project.mapLayer(
                "v_" + classe_entite + "_" + geomtype + "_suppr_layer"
            )
            current_layer.setSubsetString(version_filter)
            current_layer.setName(
                classe_entite.upper()
                + " "
                + geomtype.upper()
                + " *suppr*:"
                + version_params["thematique"]
                + "_P:"
                + version_params["num_proj"]
                + "_V:"
                + version_params["num_version"]
            )

    # Zoom sur les objets (s'ils existent), sur l'étendue du territoire sinon
    if extent.isNull():  # zoom sur l'étendue du territoire
        qgis.utils.iface.mapCanvas().setExtent(
            project.mapLayer("v_limites_communales").extent()
        )
    else:  # zoom sur l'étendue de la couche (si elle contient des objets)
        qgis.utils.iface.mapCanvas().setExtent(extent)

    # Rafraichissement du style des couches du projet depuis la table layer_styles (seulement pour prescriptions et informations)
    if (
        int(version_params["num_cycle"]) == 1 and int(version_params["num_proj"]) < 400
    ) or (int(version_params["num_cycle"]) > 1 and version_params["classe"] == "Z"):
        pass
        # qgis.utils.iface.messageBar().pushMessage("Info", u'Pas de style spécifique à charger pour cette version', level=Qgis.Info)
    elif (
        int(version_params["num_cycle"]) == 1
        and 400 <= int(version_params["num_proj"]) < 800
    ) or (int(version_params["num_cycle"]) > 1 and version_params["classe"] == "P"):
        func_charger_style(
            qgis, version_params["num_cycle"], "prescription", version_params["cnig"]
        )
    elif (
        int(version_params["num_cycle"]) == 1 and int(version_params["num_proj"]) >= 800
    ) or (int(version_params["num_cycle"]) > 1 and version_params["classe"] == "I"):
        func_charger_style(
            qgis, version_params["num_cycle"], "information", version_params["cnig"]
        )
    else:
        QMessageBox.warning(
            qgis.utils.iface.mainWindow(),
            "Erreur(s)",
            "Cas non géré. Chargement du style impossible !",
        )


# Affiche la version mère
def afficher_version_mere(qgis, classe_entite, feature):
    # QgsMessageLog.logMessage('feature type : ' + type(feature), 'Versionning PLUi', 0)

    if feature["version_mere"] in (None, ""):
        qgis.utils.iface.messageBar().pushMessage(
            "Alerte", "Aucune version mère pour cette version", level=Qgis.Warning
        )
    else:
        feature["id_version"] = feature["version_mere"]
        afficher_version(qgis, classe_entite, feature)


# Met à jour le statut de version en fonction de l'opération renseignée
def modifier_statut_version(qgis, feature, operation):
    try:
        # récupération des données
        id_version = feature["id_version"]

        reply = QMessageBox.question(
            qgis.utils.iface.mainWindow(),
            "ATTENTION",
            "Etes-vous sûr de vouloir <b>"
            + operation.upper()
            + "</b> la version '"
            + feature["id_version"]
            + " ?",
            QMessageBox.Yes,
            QMessageBox.No,
        )

        if reply == QMessageBox.Yes:
            # requete SQL
            sql = (
                "SELECT urba_plui_ecriture.qgis_"
                + operation
                + "_version('"
                + id_version
                + "');"
            )

            result = func_executer_sql(qgis, sql, operation + " la version")
            QgsMessageLog.logMessage("result : " + str(result), "Versionning PLUi", 0)

            if result is not None and all(
                result[0]
            ):  # Cas spécifique de la restauration de version
                qgis.utils.iface.messageBar().pushMessage(
                    "Info",
                    "Version "
                    + id_version
                    + " restaurée dans le tableau des versions "
                    + result[0][0],
                    level=Qgis.Info,
                )
            else:
                qgis.utils.iface.messageBar().pushMessage(
                    "Info",
                    "Action sur la version " + id_version + " terminée avec succès",
                    level=Qgis.Info,
                )  # Autres cas

        else:
            qgis.utils.iface.messageBar().pushMessage(
                "Info", "Action annulée", level=Qgis.Info, duration=2
            )
    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de modifier le statut de la version : " + str(e),
            level=Qgis.Critical,
        )


# Duplique la version sélectionnée
def dupliquer_version(qgis, feature):
    try:
        id_version = feature["id_version"]

        # QgsMessageLog.logMessage('id_version : ' + id_version, 'Versionning PLUi', 0)
        reply = QMessageBox.question(
            qgis.utils.iface.mainWindow(),
            "ATTENTION",
            "Etes-vous sûr de vouloir <b>DUPLIQUER</b> la version '"
            + id_version
            + "' ?",
            QMessageBox.Yes,
            QMessageBox.No,
        )

        if reply == QMessageBox.Yes:
            func_extraire_params_version(id_version)

            # Duplication de la version et récupération du nouvel identifiant de version
            sql = (
                "SELECT urba_plui_ecriture.qgis_dupliquer_version('" + id_version + "')"
            )
            result = func_executer_sql(qgis, sql, "Dupliquer la version")
            # QgsMessageLog.logMessage('new_version : ' + result[0][0], 'Versionning PLUi', 0)

            if result[0][0] == "error_validation":
                raise Exception(
                    "Action impossible ! Ce projet comporte une version <b>déjà validée</b> !"
                )

            feature["id_version"] = result[0][0]  # On remplace par la nouvelle version

            # Récupération de la classe d'entité
            classe_entite = func_recuperer_classe_entite(qgis, feature["id_version"])
            # QgsMessageLog.logMessage('classe_entite : ' + classe_entite, 'Versionning PLUi', 0)

            # Affichage de la nouvelle version
            afficher_version(qgis, classe_entite, feature)

            qgis.utils.iface.messageBar().pushMessage(
                "Info",
                "Nouvelle version générée : " + feature["id_version"],
                level=Qgis.Info,
            )

        else:
            qgis.utils.iface.messageBar().pushMessage(
                "Info", "Action annulée", level=Qgis.Info, duration=2
            )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de créer une nouvelle version : " + str(e),
            level=Qgis.Critical,
        )


# Duplique la version sélectionnée en lui affectant un nouveau n° projet
def dupliquer_projet(qgis, feature):
    try:
        id_version = feature["id_version"]

        # QgsMessageLog.logMessage('version : ' + version, 'Versionning PLUi', 0)
        reply = QMessageBox.question(
            qgis.utils.iface.mainWindow(),
            "ATTENTION",
            "Etes-vous sûr de vouloir <b>DUPLIQUER</b> le projet '"
            + id_version
            + "' ?",
            QMessageBox.Yes,
            QMessageBox.No,
        )

        if reply == QMessageBox.Yes:
            func_extraire_params_version(id_version)

            # Duplication de la version et récupération du nouvel identifiant de version
            sql = (
                "SELECT urba_plui_ecriture.qgis_dupliquer_projet('" + id_version + "')"
            )
            result = func_executer_sql(qgis, sql, "Dupliquer le projet")
            # QgsMessageLog.logMessage('new_version : ' + result[0][0], 'Versionning PLUi', 0)
            feature["id_version"] = result[0][0]  # On remplace par la nouvelle version

            # Récupération de la classe d'entité
            classe_entite = func_recuperer_classe_entite(qgis, feature["id_version"])
            # QgsMessageLog.logMessage('classe_entite : ' + classe_entite, 'Versionning PLUi', 0)

            # Affichage de la nouvelle version
            afficher_version(qgis, classe_entite, feature)

            qgis.utils.iface.messageBar().pushMessage(
                "Info",
                "Nouvelle version générée : " + feature["id_version"],
                level=Qgis.Info,
            )

        else:
            qgis.utils.iface.messageBar().pushMessage(
                "Info", "Action annulée", level=Qgis.Info, duration=2
            )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de dupliquer le projet : " + str(e),
            level=Qgis.Critical,
        )


# Supprime la version
def supprimer_version(qgis, feature):
    try:
        id_version = feature["id_version"]
        # QgsMessageLog.logMessage('version :' + version, 'Python')

        reply = QMessageBox.question(
            qgis.utils.iface.mainWindow(),
            "ATTENTION",
            "Etes-vous sûr de vouloir <b>SUPPRIMER DEFINITIVEMENT</b> la version '"
            + id_version
            + "' ?",
            QMessageBox.Yes,
            QMessageBox.No,
        )

        if reply == QMessageBox.Yes:
            # requete SQL
            sql = (
                "SELECT urba_plui_ecriture.qgis_supprimer_version('"
                + id_version
                + "');"
            )
            result = func_executer_sql(qgis, sql, "Supprimer la version")

            if result[0][0] == "error_link":
                raise Exception(
                    "celle-ci est liée à une réunion ou a depuis été dupliquée. Elle ne peut donc être supprimée."
                )

            qgis.utils.iface.messageBar().pushMessage(
                "Info",
                "Action sur la version " + id_version + " terminée avec succès",
                level=Qgis.Info,
            )

            # TODO : Réinitialiser les alias des couches géographiques

        else:
            qgis.utils.iface.messageBar().pushMessage(
                "Info", "Action annulée", level=Qgis.Info, duration=2
            )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de supprimer cette version : " + str(e),
            level=Qgis.Critical,
        )
