import actions_versionning as av
from qgis.core import Qgis, QgsFeatureRequest, QgsVectorLayer
from qgis.PyQt.QtCore import QDateTime, Qt
from qgis.PyQt.QtWidgets import (
    QCheckBox,
    QComboBox,
    QDateTimeEdit,
    QDialog,
    QDialogButtonBox,
    QLabel,
    QVBoxLayout,
)

# Couches du module
studies_layer = av.project.mapLayer(
    "Suivi_des_études_7f83d72f_c100_4f07_b9de_1a9f5e020bca"
)
conflicts_layer = av.project.mapLayer(
    "Tableau_des_conflits_entre_études_2ab118d0_5806_4e50_aa95_413450d56a21"
)
proc_layer = av.project.mapLayer(
    "Suivi_des_procédures_d0496d78_dfe6_4dc5_8072_182e210ec1cd"
)

#####################################################################
#                       ACTIONS COMMUNES                            #
#####################################################################


def getLayer(layername, keyname):
    layer = QgsVectorLayer(
        """
    service='{service}'
    sslmode=disable
    key='{key}'
    table="{schemaname}"."{tablename}"
    """.format(
            service=av.service_conf,
            schemaname="urba_plui_ecriture",
            tablename=layername,
            key=keyname,
        ),
        layername,
        "postgres",
    )

    return layer


#####################################################################
#                       ACTIONS ETUDES                              #
#####################################################################


def afficher_etude(qgis, feature):
    try:
        # Réinitialisation des filtres sur les couches de l'espace de versionning
        av.func_reinitialiser_filtres(
            int(av.project.customVariables()["pluiv_num_cycle"])
        )

        # Récupération de la liste des projets
        projets = feature["liste_projets"]

        print("len(projets) : ", len(projets))
        print("projets : ", projets)

        # Construction du filtre sur les versions
        if len(projets) == 1 and projets[0] == "NULL":
            msgbar = "Pas de projet associé à l'étude"
        else:
            project_filter = " AND ("  # init du filtre
            counter = 1
            for projet in projets:
                if counter > 1:
                    project_filter += " OR "
                project_filter += "id_version LIKE '" + projet + "%'"
                counter += 1

            project_filter += ")"

            msgbar = "Projets de l'étude filtrés avec succès"

            print("project_filter : " + project_filter)

            # Filtrage des tableaux de bord des versions
            #   TODO ? En fonction de la classe d'entité
            #   TODO ? En fonction du statut de la version
            for layer in av.arbo_versionning.findLayers():
                if layer.parent().name() == "Espace de travail":
                    filter = layer.layer().subsetString() + project_filter
                    print("layer name : ", layer.name())
                    print("filter : ", filter)
                    layer.layer().setSubsetString(filter)

        # Filtrage des couches d'étude sur l'étude sélectionnée
        filter = (
            studies_layer.subsetString()
            + " AND code_etude = '"
            + feature["code_etude"]
            + "'"
        )
        studies_layer.setSubsetString(filter)
        filter = (
            conflicts_layer.subsetString()
            + " AND (code_etude = '"
            + feature["code_etude"]
            + "' OR code_etude_conflit = '"
            + feature["code_etude"]
            + "')"
        )
        conflicts_layer.setSubsetString(filter)

        # Zoom sur le périmètre de l'étude
        studies_layer.selectByIds([feature["ogc_fid"]])
        box = studies_layer.boundingBoxOfSelected()
        qgis.utils.iface.mapCanvas().setExtent(box)
        studies_layer.selectByIds([])
        qgis.utils.iface.mapCanvas().refresh()

        qgis.utils.iface.messageBar().pushMessage(
            "Info", msgbar, level=Qgis.Info, duration=3
        )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur", "Impossible d'afficher l'étude : " + str(e), level=Qgis.Critical
        )


def afficher_toutes_les_etudes(qgis):
    # Suppression du filtre sur les couches d'étude
    filter = "num_cycle=" + av.project.customVariables()["pluiv_num_cycle"]
    studies_layer.setSubsetString(filter)
    filter = '"conflit_resolu" = false'
    conflicts_layer.setSubsetString(filter)

    # Réinitialisation des filtres sur les couches de l'espace de versionning
    av.func_reinitialiser_filtres(int(av.project.customVariables()["pluiv_num_cycle"]))

    # Zoom sur l'étendue des périmètres d'études
    qgis.utils.iface.mapCanvas().setExtent(studies_layer.extent())

    qgis.utils.iface.messageBar().pushMessage(
        "Info",
        "La liste des études a été mise à jour avec succès",
        level=Qgis.Info,
        duration=3,
    )


class EtudeDialogBox(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        # Html label for warning
        self.warninglabel = QLabel()
        self.warninglabel.setText(
            """<h3 style="text-align:center;color:red"> /!\\ Vous êtes sur le point de terminer cette étude /!\\ </h3>
                                     <p style="font:italic;">Si vous validez cette étape, l\'étude ne sera plus éditable</p>"""
        )
        layout.addWidget(self.warninglabel)

        self.datelabel = QLabel()
        self.datelabel.setText("\nVeuillez renseigner la date de fin de l'étude")
        layout.addWidget(self.datelabel)

        # nice widget for editing the date
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        self.datetime.setDisplayFormat("dd/MM/yyyy")
        layout.addWidget(self.datetime)

        self.proclabel = QLabel()
        self.proclabel.setText("\nVeuillez sélectionner la procédure cible de l'étude")
        layout.addWidget(self.proclabel)

        # combobox displaying running procedures
        self.proccombobox = QComboBox()
        self.proccombobox.addItems(self.getProcList())
        layout.addWidget(self.proccombobox)

        # Simple label for ending process
        self.conflictlabel = QLabel(
            """\nUn contrôle sera également fait sur les éventuels conflits avec d\'autres études. Si ce n\'est le cas, l\'action sera annulée"""
        )
        self.conflictlabel.setWordWrap(True)
        layout.addWidget(self.conflictlabel)

        # OK and Cancel buttons
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self
        )
        layout.addWidget(self.buttons)

        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

    # get current date and time from the dialog
    def dateTime(self):
        return self.datetime.dateTime()

    def getProcList(self):
        # layer = getLayer('_etude_suivi_procedures', 'ogc_id')

        # print('layer.fields(): '+ ','.join(layer.fields().names()))

        filter = "datefin_proc IS NULL"
        selection = proc_layer.getFeatures(
            QgsFeatureRequest().setFilterExpression(filter)
        )

        liste = []
        for proc in selection:
            liste.append(proc["intitule"])

        return liste

    def getSelectedProc(self):
        return self.proccombobox.currentText()

    # static method to create the dialog and return (date, accepted)
    @staticmethod
    def getValues(parent=None):
        dialog = EtudeDialogBox(parent)
        result = dialog.exec_()
        datefin = dialog.dateTime().date().toString("yyyy-MM-dd")
        proc = dialog.getSelectedProc()
        return (datefin, proc, result == QDialog.Accepted)


# Termine l'étude
def terminer_etude(qgis, feature):
    try:
        # Contrôle si la procédure n'est pas déjà terminée
        if str(feature["date_fin"]) != "NULL":
            qgis.utils.iface.messageBar().pushMessage(
                "Warning",
                "Cette étude a déjà été terminée et n'est donc plus éditable",
                level=Qgis.Warning,
                duration=5,
            )
        else:
            datefin, proc, ok = EtudeDialogBox.getValues()

            # Exécution de fin de procédure
            if ok:
                # print('proc: ', proc)
                # print('datefin: ', datefin)

                # Vérification des éventuels conflits non résolus de l'étude puis maj de l'étude si ok
                sql = (
                    "SELECT urba_plui_ecriture.qgis_terminer_etude('"
                    + feature["code_etude"]
                    + "');"
                )

                print("sql: ", sql)

                # TODO
                av.func_executer_sql(qgis, sql, "Terminer étude")

                # TODO : rafraichir table attributaire
                # attrib_table = qgis.utils.iface.showAttributeTable(qgis.utils.iface.activeLayer())
                # if 'attrib_table' in globals():
                # attrib_table.close()
                # del attrib_table
                # qgis.utils.iface.showAttributeTable(qgis.utils.iface.activeLayer())

                qgis.utils.iface.messageBar().pushMessage(
                    "Info",
                    "La mise à jour de l'étude s'est terminée avec succès",
                    level=Qgis.Info,
                    duration=2,
                )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur", "Impossible de terminer l'étude : " + str(e), level=Qgis.Critical
        )


#####################################################################
#                       ACTIONS PROCEDURES                          #
#####################################################################


class ProcDialogBox(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)

        layout = QVBoxLayout(self)

        # Html label for warning
        self.warninglabel = QLabel()
        self.warninglabel.setText(
            """<h3 style="text-align:center;color:red"> /!\\ Vous êtes sur le point de terminer cette procédure /!\\ </h3>
                                     <p style="font:italic;">Si vous validez cette étape, la procédure ne sera plus éditable</p>"""
        )
        layout.addWidget(self.warninglabel)

        self.datelabel = QLabel()
        self.datelabel.setText("\nVeuillez renseigner la date de fin de la procédure")
        layout.addWidget(self.datelabel)

        # nice widget for editing the date
        self.datetime = QDateTimeEdit(self)
        self.datetime.setCalendarPopup(True)
        self.datetime.setDateTime(QDateTime.currentDateTime())
        self.datetime.setDisplayFormat("dd/MM/yyyy")
        layout.addWidget(self.datetime)

        # Simple label for ending process
        self.freezecyclelabel = QLabel("\nCocher cette case pour terminer le cycle")
        layout.addWidget(self.freezecyclelabel)

        # checkbox to freeze cycle
        self.checkbox = QCheckBox()
        layout.addWidget(self.checkbox)

        # Simple label for info about ending cycle
        self.infocyclelabel = QLabel(
            '<p style="font:italic;">Si vous cochez cette case, les versions validées partiront en qualif</p>'
        )
        layout.addWidget(self.infocyclelabel)

        # OK and Cancel buttons
        self.buttons = QDialogButtonBox(
            QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self
        )
        layout.addWidget(self.buttons)

        self.buttons.accepted.connect(self.accept)
        self.buttons.rejected.connect(self.reject)

    # get current date and time from the dialog
    def dateTime(self):
        return self.datetime.dateTime()

    # get current date and time from the dialog
    def checkBoxState(self):
        return self.checkbox.isChecked()

    # static method to create the dialog and return (date, accepted)
    @staticmethod
    def getValues(parent=None):
        dialog = ProcDialogBox(parent)
        result = dialog.exec_()
        datefin = dialog.dateTime().date()  # .toString('yyyy-MM-dd')
        freezecycle = dialog.checkBoxState()
        return (datefin, freezecycle, result == QDialog.Accepted)


# Termine la procédure en gelant si nécessaire le cycle courant
def terminer_procedure(qgis, feature):
    try:
        # Contrôle si la procédure n'est pas déjà terminée
        if str(feature["datefin_proc"]) != "NULL":
            qgis.utils.iface.messageBar().pushMessage(
                "Warning",
                "Cette procédure a déjà été terminée et n'est donc plus éditable",
                level=Qgis.Warning,
                duration=5,
            )
        else:
            datefin, freezecycle, ok = ProcDialogBox.getValues()

            # Exécution de fin de procédure
            if ok:
                # print('datefin: ', datefin)
                # print('freezecycle: ', freezecycle)

                # Fin de la procédure
                sql = (
                    "SELECT urba_plui_ecriture.qgis_terminer_procedure('"
                    + str(feature["ogc_fid"])
                    + "', '"
                    + datefin.toString("yyyy-MM-dd")
                    + "');"
                )
                av.func_executer_sql(qgis, sql, "Terminer procédure")

                # Gel du cycle et copie des versions validées en qualif
                if freezecycle:
                    sql = "SELECT urba_plui_ecriture.qgis_geler_cycle();"
                    num_cycle = av.func_executer_sql(qgis, sql, "Geler cycle")[0][0]

                    sql = (
                        "SELECT urba_plui_ecriture.admin_migrer_vers_qualif("
                        + str(num_cycle)
                        + ", '"
                        + str(feature["code_proc"])
                        + "', '"
                        + datefin.toString("yyyyMMdd")
                        + "');"
                    )
                    # av.func_executer_sql(qgis, sql, 'Migrer vers qualif')

                # TODO : rafraichir table attributaire
                # qgis.utils.iface.openFeatureForm(getLayer('v__etude_suivi_procedures','ogc_fid'), feature, False)
                # attribtable = qgis.utils.iface.showAttributeTable(getLayer('v__etude_suivi_procedures','ogc_fid'))

                # print('globals()', globals())
                # if 'attribtable' in globals():
                # print('on y est')
                # attrib_table.close()
                # del attrib_table
                qgis.utils.iface.showAttributeTable(
                    getLayer("v__etude_suivi_procedures", "ogc_fid")
                )

                qgis.utils.iface.messageBar().pushMessage(
                    "Info",
                    "La mise à jour de la procédure s'est terminée avec succès",
                    level=Qgis.Info,
                    duration=2,
                )

    except Exception as e:
        qgis.utils.iface.messageBar().pushMessage(
            "Erreur",
            "Impossible de terminer la procédure : " + str(e),
            level=Qgis.Critical,
        )
