from pathlib import Path

from qgis.core import (
    Qgis,
    QgsApplication,
    QgsPostgresStringUtils,
    QgsProviderConnectionException,
    QgsProviderRegistry,
)
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtGui import QCursor, QIcon
from qgis.PyQt.QtWidgets import (
    QDialog,
    QHBoxLayout,
    QMessageBox,
    QTableWidgetItem,
    QToolButton,
    QWidget,
)

from plui_versionning.core.utils import CLASSES_ENTITE
from plui_versionning.toolbelt import PlgLogger, PlgOptionsManager


class ManageThematiquesDialog(QDialog):
    def __init__(self, parent: QWidget = None, *args, **kwds):
        """
        QDialog Gérer les thématiques
        """
        super().__init__(parent, *args, **kwds)
        self.log = PlgLogger().log

        # DB connection
        self.db_connection_uri = (
            PlgOptionsManager().get_plg_settings().db_connection_uri
        )
        self.db_schema_name = PlgOptionsManager().get_plg_settings().db_schema_name

        uic.loadUi(Path(__file__).parent / f"{Path(__file__).stem}.ui", self)

        self.wdg_thematique_details.setVisible(False)
        self.wdg_thematique_details.refreshThematique.connect(self.refresh_thematique)
        self.classe_entite = [
            classe
            for classe in CLASSES_ENTITE
            if classe["name"] == self.btn_grp_classe_entite.checkedButton().text()
        ][0]
        self.btn_grp_classe_entite.buttonClicked.connect(self.change_classe)
        self.table_thematiques.itemSelectionChanged.connect(self.load_thematique)

        self.load_thematiques()

    def change_classe(self, button):
        self.classe_entite = [
            classe for classe in CLASSES_ENTITE if classe["name"] == button.text()
        ][0]
        self.wdg_thematique_details.setVisible(False)
        self.load_thematiques()

    def list_thematiques(self):
        query = """
        select id, nom_thematique, code_cnig, version_validee from \"{}\".v_pluiv_thematiques
        where classe_entite = '{}'
        """.format(
            self.db_schema_name, self.classe_entite["code"]
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            if result:
                return result
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)

    def load_thematiques(self):
        self.table_thematiques.clearContents()
        self.table_thematiques.setRowCount(0)

        thematiques = self.list_thematiques()
        if thematiques:
            for t in thematiques:
                self.table_thematiques.insertRow(self.table_thematiques.rowCount())
                thematique_item = QTableWidgetItem(
                    f"{t[1]} ({self.classe_entite['thematique']}{t[2]})"
                )
                thematique_item.setData(Qt.UserRole, t[0])
                self.table_thematiques.setItem(
                    self.table_thematiques.rowCount() - 1, 0, thematique_item
                )
                wdg_delete = QWidget()
                hl = QHBoxLayout()
                icon_delete = QIcon(
                    QgsApplication.iconPath("mActionDeleteSelected.svg")
                )
                btn_delete = QToolButton()
                btn_delete.setIcon(icon_delete)
                if t[3]:
                    btn_delete.setToolTip(
                        "Suppression impossible. Une version validée est rattachée à la thématique."
                    )
                else:
                    btn_delete.setToolTip("Supprimer la thématique")
                btn_delete.setAutoRaise(True)
                btn_delete.setCursor(QCursor(Qt.PointingHandCursor))
                id_thematique = self.table_thematiques.item(
                    self.table_thematiques.rowCount() - 1, 0
                ).data(Qt.UserRole)
                btn_delete.clicked.connect(
                    lambda *args, id_thematique=id_thematique: self.delete_thematique(
                        id_thematique
                    )
                )
                btn_delete.setEnabled(not t[3])
                hl.addWidget(btn_delete)
                hl.setAlignment(Qt.AlignCenter)
                hl.setContentsMargins(0, 0, 0, 0)
                wdg_delete.setLayout(hl)
                self.table_thematiques.setCellWidget(
                    self.table_thematiques.rowCount() - 1, 1, wdg_delete
                )

    def load_thematique(self):
        if self.table_thematiques.selectedItems():
            id_thematique = self.table_thematiques.selectedItems()[0].data(Qt.UserRole)
            self.wdg_thematique_details.setVisible(id_thematique is not None)
            if id_thematique:
                self.wdg_thematique_details.set_thematique(id_thematique)

    def get_projets_thematique(self, id_thematique):
        query = """
            select id_proj, versions from {}.qgis_verifier_projets_thematique({})
            """.format(
            self.db_schema_name, id_thematique
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            if result:
                return result
            else:
                return []
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)

    def delete_thematique(self, id_thematique):
        thematique = self.get_nom_thematique(id_thematique)
        projets_versions = self.get_projets_thematique(id_thematique)
        projets = []
        versions = []
        for p, v in projets_versions:
            projets.append(self.get_nom_projet(p))
            for version in QgsPostgresStringUtils.parseArray(v or ""):
                versions.append(version)

        if projets_versions:
            msg_confirmation = f"""Voici la liste des projets et versions rattachés à la thématique <b>{thematique}</b>.
            <br ><br ><b>Projets :</b> {', '.join(projets)}
            <br ><b>Versions :</b> {', '.join(versions)}
            <br ><br >Confirmez-vous la suppression de cette thématique ?
            <br ><br ><i>Cette opération entrainera aussi la suppression de tous ses éléments rattachés.</i>
            """
        else:
            msg_confirmation = (
                f"Êtes-vous sûr de vouloir supprimer la thématique {thematique} ?"
            )

        response = QMessageBox().question(
            self,
            "Confirmer la suppression de la thématique",
            msg_confirmation,
        )

        if response == QMessageBox.Yes:
            query = """
                delete
                from {}.pluiv_thematiques t
                where t.id = {}
                """.format(
                self.db_schema_name, id_thematique
            )
            md = QgsProviderRegistry.instance().providerMetadata("postgres")
            conn = md.createConnection(self.db_connection_uri, {})
            try:
                conn.executeSql(query)
                self.log(
                    message=f"La thématique {thematique} a été supprimée",
                    log_level=Qgis.Success,
                    push=True,
                )
            except QgsProviderConnectionException as e:
                self.log(message=e, log_level=Qgis.Critical, push=True)
            self.wdg_thematique_details.setVisible(False)
            self.load_thematiques()

    def refresh_thematique(self, id_thematique: int):
        item_thematique = None
        for row in range(self.table_thematiques.rowCount()):
            item = self.table_thematiques.item(row, 0)
            if item.data(Qt.UserRole) == id_thematique:
                item_thematique = item
                break
        if not item_thematique:
            return
        item_thematique.setText(self.get_nom_thematique(id_thematique))

    def get_nom_thematique(self, id_thematique: int) -> str:
        """Get nom_thematique field regarding id

        Args:
            id_thematique (int): thematique id (field id in table pluiv_thematiques)

        Returns:
            nom_thematique (str): thematique name (field nom_thematique in table pluiv_thematiques)
        """
        query = """
            select t.id, t.nom_thematique, t.code_cnig from {}.pluiv_thematiques t
            WHERE t.id = {}
            """.format(
            self.db_schema_name, id_thematique
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            return f"{result[0][1]} ({self.classe_entite['thematique']}{result[0][2]})"
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)

    def get_nom_projet(self, id_projet: int) -> str:
        """Get nom_projet field regarding id

        Args:
            id_projet (int): projet id (field id in table pluiv_projets)

        Returns:
            nom_projet (str): projet name (field nom_projet in table pluiv_projets)
        """
        query = """
            (SELECT p.id, p.nom_projet FROM {}.pluiv_projets p
            WHERE p.id = {})
            """.format(
            self.db_schema_name, id_projet
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            return result[0][1]
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)
