from qgis.PyQt.QtCore import QObject, pyqtSignal
from qgis.gui import QgsMapToolEdit, QgsRubberBand
from qgis.core import (
    QgsGeometry,
    QgsFeatureRequest,
    QgsWkbTypes,
    Qgis,
)

from .compat_qt import LeftButton, RightButton, ColorRed, CrossCursor


class GroupPolygonTool(QgsMapToolEdit, QObject):
    group_finished = pyqtSignal(dict)  # émis quand sélection terminée
    group_canceled = pyqtSignal()      # émis quand sélection invalide

    def __init__(self, canvas, layer):
        super().__init__(canvas)
        self.canvas = canvas
        self.layer = layer
        self.selected_features = []

        self.rubber_band = QgsRubberBand(canvas, Qgis.GeometryType.Polygon)
        self.rubber_band.setColor(ColorRed)
        self.rubber_band.setWidth(2)

    # ---------------------------
    # Activation / désactivation
    # ---------------------------
    def activate(self):
        super().activate()
        self.canvas.setCursor(CrossCursor)

    def deactivate(self):
        super().deactivate()
        self.canvas.unsetCursor()
        self.clear()

    # ---------------------------
    # Clic carte
    # ---------------------------
    def canvasPressEvent(self, event):
        if event.button() == LeftButton:
            self.handle_left_click(event)

    def handle_left_click(self, event):
        point = self.toMapCoordinates(event.pos())

        for f in self.layer.getFeatures():
            if f.geometry().contains(point):
                self.try_add_feature(f)

                # 🔴 Remettre la dialog au premier plan
                if hasattr(self, 'dialog') and self.dialog is not None:
                    self.dialog.raise_()
                    self.dialog.activateWindow()

                return

    # ---------------------------
    # Logique de sélection
    # ---------------------------
    def try_add_feature(self, feature):
        if feature in self.selected_features:
            return

        if self.selected_features and not self._touches_existing(feature):
            self.group_canceled.emit()
            return

        self.selected_features.append(feature)
        self._update_rubber_band()

        # 🔹 Mettre à jour la liste des parcelles dans la dialog
        if hasattr(self, 'dialog') and self.dialog is not None:
            # Récupérer la liste existante
            current_text = self.dialog.ui.textEdit_list_Rgp.toPlainText().strip()

            # Construire l'identifiant de la parcelle
            section = feature['section'] if 'section' in feature.fields().names() else ''
            numero = feature['numero'] if 'numero' in feature.fields().names() else ''
            parcelle_id = f"{section}{numero}"

            # Ajouter avec " + " si nécessaire
            if current_text:
                new_text = current_text + " + " + parcelle_id
            else:
                new_text = parcelle_id

            self.dialog.ui.textEdit_list_Rgp.setPlainText(new_text)

            # 🔹 Mettre à jour l'état du bouton terminer regroupement
            self.dialog.update_finish_button_state()

            # -------------------------
            # Mise à jour automatique de la section
            # -------------------------
            sections = {f['section'] for f in self.selected_features if 'section' in f.fields().names()}

            line_section = self.dialog.ui.lineEdit_section_Rgp

            if len(sections) == 1:
                # section unique → remplir automatiquement
                only_section = sections.pop()
                line_section.setText(str(only_section))
                line_section.setReadOnly(True)
            else:
                # sections différentes → champ vide
                line_section.clear()
                line_section.setReadOnly(False)

    def _touches_existing(self, new_feat):
        for feat in self.selected_features:
            if new_feat.geometry().intersects(feat.geometry()):
                return True
        return False

    def _update_rubber_band(self):
        self.rubber_band.reset(Qgis.GeometryType.Polygon)
        for f in self.selected_features:
            self.rubber_band.addGeometry(f.geometry(), self.layer)
        self.rubber_band.show()

    # ---------------------------
    # Fin de sélection (appelé par Btn_fin_Rgp)
    # ---------------------------
    def finish_group(self):
        if len(self.selected_features) < 2:
            self.group_canceled.emit()
            return

        geom = QgsGeometry.unaryUnion([f.geometry() for f in self.selected_features])
        result = {
            "features": self.selected_features,
            "geometry": geom,
            "contenance": sum(float(f['contenance']) for f in self.selected_features),
            "prix": sum(float(f['prix']) for f in self.selected_features)
        }

        self.group_finished.emit(result)
        self.clear()

    def cancel(self, user_initiated=False):
        """Annule la sélection"""
        self.clear()
        if not user_initiated:
            # Émettre seulement si ce n’est pas un cancel volontaire de l'utilisateur
            self.group_canceled.emit()

    def clear(self):
        self.selected_features = []
        self.rubber_band.reset(Qgis.GeometryType.Polygon)
        self.canvas.refresh()