from pathlib import Path

from qgis.core import (
    NULL,
    Qgis,
    QgsApplication,
    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 (
    QCheckBox,
    QDialog,
    QHBoxLayout,
    QMessageBox,
    QTableWidgetItem,
    QToolButton,
    QWidget,
)

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


class ManageStylesDialog(QDialog):
    def __init__(self, parent: QWidget = None, *args, **kwds):
        """
        QDialog Gérer les styles
        """
        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.load_styles()

    def list_styles(self):
        query = """
        select id, nom_thematique, format, procedure_plui, cnig from \"{}\".v_pluiv_styles
        """.format(
            self.db_schema_name
        )
        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 get_style(self, id_style):
        query = """
        select id, nom_thematique, format, procedure_plui, cnig from \"{}\".v_pluiv_styles
        where id={}
        """.format(
            self.db_schema_name, id_style
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            if result:
                return result[0]
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)

    def load_styles(self):
        self.table_styles.clearContents()
        self.table_styles.setRowCount(0)

        styles = self.list_styles()
        if styles:
            for s in styles:
                self.table_styles.insertRow(self.table_styles.rowCount())
                thematique_item = QTableWidgetItem(s[1])
                thematique_item.setData(Qt.UserRole, s[0])
                self.table_styles.setItem(
                    self.table_styles.rowCount() - 1, 0, thematique_item
                )
                format_item = QTableWidgetItem(s[2])
                format_item.setData(Qt.UserRole, s[0])
                self.table_styles.setItem(
                    self.table_styles.rowCount() - 1, 1, format_item
                )
                procedure_item = QTableWidgetItem(s[3])
                procedure_item.setData(Qt.UserRole, s[0])
                self.table_styles.setItem(
                    self.table_styles.rowCount() - 1, 2, procedure_item
                )
                wdg_cnig = QWidget()
                hl = QHBoxLayout()
                cb_cnig = QCheckBox()
                cb_cnig.setEnabled(False)
                cb_cnig.setCheckState(Qt.Checked if s[4] else Qt.Unchecked)
                hl.addWidget(cb_cnig)
                hl.setAlignment(Qt.AlignCenter)
                hl.setContentsMargins(0, 0, 0, 0)
                wdg_cnig.setLayout(hl)
                self.table_styles.setCellWidget(
                    self.table_styles.rowCount() - 1, 3, wdg_cnig
                )

                if not s[4] and not self.is_finished_procedure(s[3]):
                    wdg_delete = QWidget()
                    hl = QHBoxLayout()
                    icon_delete = QIcon(
                        QgsApplication.iconPath("mActionDeleteSelected.svg")
                    )
                    btn_delete = QToolButton()
                    btn_delete.setIcon(icon_delete)
                    btn_delete.setToolTip("Supprimer le style")
                    btn_delete.setAutoRaise(True)
                    btn_delete.setCursor(QCursor(Qt.PointingHandCursor))
                    id_style = self.table_styles.item(
                        self.table_styles.rowCount() - 1, 1
                    ).data(Qt.UserRole)
                    btn_delete.clicked.connect(
                        lambda *args, id_style=id_style: self.delete_style(id_style)
                    )
                    hl.addWidget(btn_delete)
                    hl.setAlignment(Qt.AlignCenter)
                    hl.setContentsMargins(0, 0, 0, 0)
                    wdg_delete.setLayout(hl)
                    self.table_styles.setCellWidget(
                        self.table_styles.rowCount() - 1, 4, wdg_delete
                    )

    def delete_style(self, id_style):
        style = self.get_style(id_style)
        thematique = style[1]
        procedure = style[3]
        response = QMessageBox().question(
            self,
            "Confirmer la suppression du style",
            f"Êtes-vous sûr de vouloir supprimer le style de la thématique {thematique} pour la procédure {procedure} ?",
        )

        if response == QMessageBox.Yes:
            query = 'select "{}".qgis_supprimer_style({})'.format(
                self.db_schema_name, id_style
            )
            md = QgsProviderRegistry.instance().providerMetadata("postgres")
            conn = md.createConnection(self.db_connection_uri, {})
            try:
                conn.executeSql(query)
                self.log(
                    message=f"Le style de la thématique {thematique} pour la procédure {procedure} a été supprimé",
                    log_level=Qgis.Success,
                    push=True,
                )
                self.load_styles()
            except QgsProviderConnectionException as e:
                self.log(
                    message=catch_postgres_exception(str(e)),
                    log_level=Qgis.Critical,
                    push=True,
                )

    def is_finished_procedure(self, procedure_plui: str) -> bool:
        """Renvoie vrai si la procédure a une date de fin de procédure"""
        query = """
            (SELECT pp.id, pp.procedure_plui, pp.datefin_proc
            FROM {}.v_pluiv_procedures pp
            WHERE procedure_plui = '{}'
            )
        """.format(
            self.db_schema_name, procedure_plui
        )
        md = QgsProviderRegistry.instance().providerMetadata("postgres")
        conn = md.createConnection(self.db_connection_uri, {})
        try:
            result = conn.executeSql(query)
            if result:
                return result[0][2] != NULL
        except QgsProviderConnectionException as e:
            self.log(message=e, log_level=Qgis.Critical, push=True)
        return False
