from qgis.core import (
    QgsVectorLayer, 
    QgsProject, 
    QgsGeometry,
    QgsPointXY,
    QgsCoordinateReferenceSystem,
    QgsCoordinateTransform,
    QgsFillSymbol,
    Qgis
)
from qgis.gui import QgsMapToolEmitPoint
from qgis.utils import iface
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import QMessageBox, QApplication

import json, os
from datetime import datetime

# ============================================================================
# KONFIGURATION
# ============================================================================

# Pfad zur Konfigurationsdatei (im gleichen Verzeichnis wie das Skript)
CONFIG_FILE = os.path.join(os.path.dirname(__file__), "bundeslaender_config.json")

# Name des Bundesländer-Layers in QGIS
BUNDESLAENDER_LAYER_NAME = "laender"

# Feldname im Layer der den Bundesland-Namen enthält
BUNDESLAND_NAME_FIELD = "gen"  

# Buffer und Distanz-Einstellungen
SEARCH_BUFFER = 50  # Meter
MAX_NEARBY_DISTANCE = 50  # Meter


class FluerstueckMapTool(QgsMapToolEmitPoint):
    def __init__(self, canvas, config):
        super().__init__(canvas)
        self.canvas = canvas
        self.config = config
        self.setCursor(Qt.CursorShape.CrossCursor)
        print("FluerstueckMapTool initialisiert!")
        print(f"Konfigurierte Bundesländer: {len(config)}")
        
    def canvasReleaseEvent(self, event):
        """Wird bei Mausklick aufgerufen"""
        print("\n" + "="*70)
        print("KLICK REGISTRIERT!")
        print("="*70)
        
        iface.messageBar().pushMessage("Info", "Klick registriert! Suche Flurstück...", level=Qgis.MessageLevel.Info, duration=3)
        QApplication.processEvents()
        
        try:
            point = self.toMapCoordinates(event.pos())
            print(f"Klickposition - Karte: x={point.x():.2f}, y={point.y():.2f}")
            print(f"Canvas CRS: {self.canvas.mapSettings().destinationCrs().authid()}")
            
            self.find_flurstueck(point)
            
        except Exception as e:
            print(f"FEHLER im canvasReleaseEvent: {e}")
            import traceback
            traceback.print_exc()
            QMessageBox.critical(None, "Fehler", f"Fehler beim Verarbeiten des Klicks:\n{e}")
    
    def get_bundeslaender_layer(self):
        """Holt den Bundesländer-Layer aus dem QGIS-Projekt"""
       #layers = QgsProject.instance().mapLayersByName(BUNDESLAENDER_LAYER_NAME)
       #
       #if not layers:
       #    print(f"! Layer '{BUNDESLAENDER_LAYER_NAME}' nicht im Projekt gefunden!")
       #    return None
       #
       #layer = layers[0]
        
        ####bundesland layer in plugin ordner gelegt abfragen ....
        plugin_dir = os.path.dirname(__file__)
        layer_path = os.path.join(plugin_dir, "data", "bundeslaender.gpkg")

        # Layer laden (OHNE addMapLayer!)
        layer = QgsVectorLayer(layer_path, "bundeslaender", "ogr")
        
        if not layer.isValid():
            print(f"! Layer '{BUNDESLAENDER_LAYER_NAME}' ist nicht valide!")
            return None
        
        print(f"✓ Bundesländer-Layer gefunden: {layer.featureCount()} Features")
        return layer
    
    def detect_bundesland(self, point, canvas_crs):
        """Erkennt Bundesland über QGIS-Layer"""
        print(f"\nErkenne Bundesland über Layer '{BUNDESLAENDER_LAYER_NAME}'...")
        
        layer = self.get_bundeslaender_layer()
        if not layer:
            QMessageBox.warning(None, "Layer fehlt", 
                f"Der Layer '{BUNDESLAENDER_LAYER_NAME}' wurde nicht im Projekt gefunden.\n\n"
                f"Bitte füge einen Bundesländer-Layer mit diesem Namen hinzu.")
            return None
        
        # Transformiere Punkt in CRS des Bundesländer-Layers
        layer_crs = layer.crs()
        print(f"Layer CRS: {layer_crs.authid()}")
        print(f"Canvas CRS: {canvas_crs.authid()}")
        
        point_transformed = point
        if canvas_crs != layer_crs:
            transform = QgsCoordinateTransform(canvas_crs, layer_crs, QgsProject.instance())
            point_transformed = transform.transform(point)
            print(f"Punkt transformiert: {canvas_crs.authid()} → {layer_crs.authid()}")
            print(f"  Vorher: {point.x():.1f}, {point.y():.1f}")
            print(f"  Nachher: {point_transformed.x():.1f}, {point_transformed.y():.1f}")
        else:
            print(f"Keine Transformation nötig")
        
        point_geom = QgsGeometry.fromPointXY(point_transformed)
        
        # Suche Bundesland das den Punkt enthält
        for feature in layer.getFeatures():
            if feature.geometry().contains(point_geom):
                bundesland_name = feature[BUNDESLAND_NAME_FIELD]
                print(f"✓ Bundesland erkannt: {bundesland_name}")
                
                ######bayern sonderfall
                if bundesland_name == 'Bayern':
                    print('Achtung Sonderfall detektiert!')
                    """Zeigt ZUGRIFF VERWEIGERT Dialog"""
                    # Erstelle custom MessageBox mit rotem Kreuz
                    

                    msg = QMessageBox()
                    msg.setIcon(QMessageBox.Icon.Critical)
                    msg.setWindowTitle("ACHTUNG!")

                    msg.setText("ZUGRIFF VERWEIGERT")
                    msg.setInformativeText(
                        "Bayern ist ein flurstücksfreies Bundesland.\n\n"
                        "Bitte versuchen Sie es in einem anderen Bundesland."
                    )
                    msg.setStyleSheet("""
                        QMessageBox {
                            background-color: #ffcccc;
                        }
                        QLabel {
                            color: #cc0000;
                            font-size: 14pt;
                            font-weight: bold;
                        }
                    """)
                    msg.setStandardButtons(QMessageBox.StandardButton.Ok)
                    msg.exec()
                    
                
                # Suche in Config nach passendem Namen (case-insensitive)
                for config_name in self.config.keys():
                    if config_name.lower() == bundesland_name.lower():
                        return config_name
                
                # Fuzzy Match
                for config_name in self.config.keys():
                    if config_name.lower() in bundesland_name.lower() or bundesland_name.lower() in config_name.lower():
                        print(f"  (Fuzzy Match: {bundesland_name} → {config_name})")
                        return config_name
                
                print(f"! Bundesland '{bundesland_name}' in Config nicht gefunden")
                return bundesland_name  # Gebe trotzdem den Namen zurück
        
        print("! Kein Bundesland gefunden")
        return None
    
    def find_flurstueck(self, point):
        """Findet und zeigt das Flurstück am Klickpunkt"""
        try:
            # Koordinatentransformation
            canvas_crs = self.canvas.mapSettings().destinationCrs()
            target_crs = QgsCoordinateReferenceSystem("EPSG:25833")
            
            print(f"\n=== Koordinaten-Management ===")
            print(f"Canvas CRS: {canvas_crs.authid()}")
            print(f"Klickpunkt in Canvas CRS: X={point.x():.2f}, Y={point.y():.2f}")
            
            # 1. Bundesland erkennen (mit Original Canvas CRS und Punkt)
            bundesland = self.detect_bundesland(point, canvas_crs)
            print(bundesland)
            if bundesland == 'Bayern':
                return 
                
            if not bundesland:
                QMessageBox.information(None, "Achtung", 
                    "Diese Funktion ist nur innerhalb Deutschlands verfügbar.\n"
                    )
                return
            
            # 2. Prüfe ob Bundesland in Config
            if bundesland not in self.config:
                QMessageBox.warning(None, "Bundesland nicht konfiguriert", 
                    f"Das Bundesland '{bundesland}' wurde erkannt, ist aber nicht in der Konfiguration.\n\n"
                    f"Bitte ergänze die Konfiguration in:\n{CONFIG_FILE}")
                return
            
            # 3. Transformiere Punkt für WFS-Abfrage nach EPSG:25832
            bl_config = self.config[bundesland]
            wfs_crs_str = bl_config.get("crs", "EPSG:25833")
            wfs_crs = QgsCoordinateReferenceSystem(wfs_crs_str)
            
            print(f"\n=== WFS-Abfrage Vorbereitung ===")
            print(f"WFS CRS: {wfs_crs.authid()}")
            
            point_wfs = point
            if canvas_crs != wfs_crs:
                transform = QgsCoordinateTransform(canvas_crs, wfs_crs, QgsProject.instance())
                point_wfs = transform.transform(point)
                print(f"Punkt transformiert für WFS: {canvas_crs.authid()} → {wfs_crs.authid()}")
                print(f"  Vorher: X={point.x():.2f}, Y={point.y():.2f}")
                print(f"  Nachher: X={point_wfs.x():.2f}, Y={point_wfs.y():.2f}")
            else:
                print(f"Keine Transformation für WFS nötig")
            
            print(f"\n>>> Suche Flurstück in {bundesland} <<<")
            result = self.query_wfs(point_wfs, bundesland, bl_config, wfs_crs)
            
            if not result:
                QMessageBox.information(None, "Kein Flurstück", 
                    f"Kein Flurstück in {bundesland} an dieser Position gefunden.")
        
        except Exception as e:
            print(f"\nEXCEPTION in find_flurstueck: {e}")
            import traceback
            traceback.print_exc()
            QMessageBox.critical(None, "Fehler", f"Fehler:\n{e}")
    
    def query_wfs(self, point, bundesland, config, target_crs):
        """Fragt WFS für ein bestimmtes Bundesland ab"""
        try:
            wfs_url = config["wfs_url"]
            typenames = config["typenames"]
            wfs_crs = config.get("crs", "EPSG:25833")
            
            print(f"\nWFS-Abfrage für {bundesland}:")
            print(f"URL: {wfs_url}")
            print(f"CRS: {wfs_crs}")
            
            # BBOX um Klickpunkt
            buffer = SEARCH_BUFFER
            bbox_minx = point.x() - buffer
            bbox_miny = point.y() - buffer
            bbox_maxx = point.x() + buffer
            bbox_maxy = point.y() + buffer
            
            print(f"BBOX: {bbox_minx:.1f},{bbox_miny:.1f},{bbox_maxx:.1f},{bbox_maxy:.1f}")
            
            # Verschiedene BBOX-Formate
            bbox_formats = [
                f"{bbox_minx},{bbox_miny},{bbox_maxx},{bbox_maxy},{wfs_crs}",
                f"{bbox_minx},{bbox_miny},{bbox_maxx},{bbox_maxy}",
                f"{bbox_miny},{bbox_minx},{bbox_maxy},{bbox_maxx},{wfs_crs}",
                f"{bbox_miny},{bbox_minx},{bbox_maxy},{bbox_maxx}"
            ]
            
            # Versuche alle konfigurierten TypeNames
            for typename in typenames:
                print(f"\n  Versuche TypeName: {typename}")
                
                # Versuche verschiedene BBOX-Formate
                for bbox_idx, bbox_str in enumerate(bbox_formats):
                    if bbox_idx > 0:
                        print(f"    Versuche BBOX-Format {bbox_idx + 1}...")
                    
                    params = [
                        "SERVICE=WFS",
                        "VERSION=2.0.0",
                        "REQUEST=GetFeature",
                        f"TYPENAMES={typename}",
                        f"BBOX={bbox_str}",
                        f"SRSNAME={wfs_crs}"
                    ]
                    
                    full_url = wfs_url + "?" + "&".join(params)
                    
                    if bbox_idx == 0:
                        print(f"  URL: {full_url}")
                    
                    layer = QgsVectorLayer(full_url, f"temp_{typename}", "ogr")
                    
                    if layer.isValid():
                        feature_count = layer.featureCount()
                        print(f"    ✓ Layer valide! Features: {feature_count}")
                        
                        if feature_count > 0:
                            print(f"  *** ERFOLG mit {typename} und BBOX-Format {bbox_idx + 1} in {bundesland} ***")
                            return self.process_features(layer, point, bundesland, target_crs)
                        elif bbox_idx == 0:
                            print(f"    Keine Features, versuche andere BBOX-Formate...")
                    else:
                        error_msg = layer.error().message()
                        if bbox_idx == 0:
                            print(f"    ✗ Layer nicht valide: {error_msg}")
                        continue
                
                print(f"  Alle BBOX-Formate fehlgeschlagen für {typename}")
            
            print(f"\nKeine Features in {bundesland} gefunden")
            return False
            
        except Exception as e:
            print(f"Fehler bei WFS-Abfrage für {bundesland}: {e}")
            return False
    
    def process_features(self, layer, point, bundesland, target_crs):
        """Verarbeitet gefundene Features"""
        try:
            point_geom = QgsGeometry.fromPointXY(point)
            
            found_feature = None
            min_distance = float('inf')
            closest_feature = None
            
            print(f"\nDurchsuche {layer.featureCount()} Feature(s)...")
            
            for i, feature in enumerate(layer.getFeatures()):
                geom = feature.geometry()
                
                if geom.contains(point_geom):
                    print(f"✓✓✓ Feature {i+1} enthält den Punkt!")
                    found_feature = feature
                    break
                
                distance = geom.distance(point_geom)
                if distance < min_distance:
                    min_distance = distance
                    closest_feature = feature
            
            if found_feature:
                print(f"\n*** FLURSTÜCK GEFUNDEN in {bundesland}! ***")
                self.display_flurstueck(found_feature, bundesland, target_crs)
                return True
            elif closest_feature and min_distance < MAX_NEARBY_DISTANCE:
                print(f"\nNächstes Flurstück ist {min_distance:.1f}m entfernt")
                
                reply = QMessageBox.question(None, "Flurstück in der Nähe", 
                    f"Kein Flurstück direkt am Klickpunkt in {bundesland}.\n\n"
                    f"Das nächste Flurstück ist {min_distance:.1f}m entfernt.\n\n"
                    f"Möchtest du es anzeigen?",
                    QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
                
                if reply == QMessageBox.StandardButton.Yes:
                    self.display_flurstueck(closest_feature, bundesland, target_crs)
                    return True
            
            return False
            
        except Exception as e:
            print(f"Fehler bei Feature-Verarbeitung: {e}")
            return False
    
    def display_flurstueck(self, feature, bundesland, crs):
        """Zeigt das gefundene Flurstück in der Karte an"""
        try:
            print("\n--- Display Flurstück ---")
            print(f"Feature CRS: {crs.authid()}")
            
            # Zeitstempel erstellen
            timestamp = datetime.now().strftime("%H:%M:%S")
            layer_name = f"Gefundenes Flurstück ({timestamp})"
            
            # Alten Layer entfernen - WICHTIG: Muster anpassen!
            #existing_layers = [l for l in QgsProject.instance().mapLayers().values() 
            #                  if l.name().startswith("Gefundenes Flurstück")]
            #for old_layer in existing_layers:
             #   QgsProject.instance().removeMapLayer(old_layer.id())
            
            # Memory-Layer erstellen mit neuem Namen
            memory_layer = QgsVectorLayer(
                f"Polygon?crs={crs.authid()}",
                layer_name,  # <-- Hier der neue Name mit Uhrzeit
                "memory"
            )
            
            provider = memory_layer.dataProvider()
            provider.addAttributes(feature.fields())
            memory_layer.updateFields()
            provider.addFeature(feature)
            memory_layer.updateExtents()
            
            print(f"Memory-Layer erstellt mit CRS: {memory_layer.crs().authid()}")
            
            # Styling
            symbol = QgsFillSymbol.createSimple({
                'color': '0,0,255,80',
                'outline_color': 'blue',
                'outline_width': '1.0',
                'outline_style': 'solid'
            })
            memory_layer.renderer().setSymbol(symbol)
            
            features = list(memory_layer.getFeatures())
            if features:
                ##### probiere verschiedene vorkommende attributnamen ###
                try:
                    neuer_name = features[0]['flstkennz']
                except (KeyError, AttributeError):
                    try:
                        neuer_name = features[0]['flurstueckskennzeichen'] ###bw
                    except (KeyError, AttributeError):
                        try:
                            neuer_name = features[0]['nationalCadastralReference'] ###sh
                        except (KeyError, AttributeError):
                            neuer_name = features[0]['fsko'] ###berlin
                memory_layer.setName(str(neuer_name))

            # Layer hinzufügen
            QgsProject.instance().addMapLayer(memory_layer)
            
            # Zoomen - QGIS transformiert automatisch in Canvas CRS
            extent = feature.geometry().boundingBox()
            
            # Transformiere Extent in Canvas CRS falls nötig
            canvas_crs = self.canvas.mapSettings().destinationCrs()
            if crs != canvas_crs:
                transform = QgsCoordinateTransform(crs, canvas_crs, QgsProject.instance())
                extent = transform.transformBoundingBox(extent)
                print(f"Extent transformiert: {crs.authid()} → {canvas_crs.authid()}")
            
            extent.scale(1.5)
            iface.mapCanvas().setExtent(extent)
            iface.mapCanvas().refresh()
            
            print("Layer angezeigt und gezoomt")
            
            # Info ausgeben
            info = f"✓ Flurstück gefunden!\n"
            info += f"Bundesland: {bundesland}\n\n"
            
            for field in feature.fields():
                value = feature[field.name()]
                if value is not None and str(value).strip() != '':
                    info += f"{field.name()}: {value}\n"
            
            #print(f"\n{info}")
            
        except Exception as e:
            print(f"FEHLER in display_flurstueck: {e}")
            import traceback
            traceback.print_exc()


def load_config():
    """Lädt die Bundesländer-Konfiguration aus JSON-Datei"""
    print(f"\nLade Konfiguration von: {CONFIG_FILE}")
    
    if not os.path.exists(CONFIG_FILE):
        print(f"! Konfigurationsdatei nicht gefunden!")
        

    try:
        with open(CONFIG_FILE, 'r', encoding='utf-8') as f:
            config = json.load(f)
        print(f"✓ Konfiguration geladen: {len(config)} Bundesländer")
        for bl in config.keys():
            print(f"  • {bl}")
        return config
    except Exception as e:
        print(f"Fehler beim Laden der Config: {e}")
        QMessageBox.critical(None, "Konfigurationsfehler", 
            f"Fehler beim Laden der Konfiguration:\n{e}\n\n"
            f"Datei: {CONFIG_FILE}")
        return {}


# Globale Variable
current_tool = None

def karten_suche():
    """Startet das Flurstück-Auswahl-Tool"""
    global current_tool
    
    # Konfiguration laden
    config = load_config()
    if not config:
        QMessageBox.warning(None, "Keine Konfiguration", 
            "Keine gültige Konfiguration gefunden.\n\n"
            f"Bitte erstelle: {CONFIG_FILE}")
        return
    
    canvas = iface.mapCanvas()
    
    # CRS prüfen
    canvas_crs = canvas.mapSettings().destinationCrs()
    #if not canvas_crs.isValid():
     #   QMessageBox.warning(None, "Warnung", 
      #      "Kein gültiges Koordinatensystem!\n\n"
      #      "Bitte setze ein CRS für dein Projekt")
     #   return
    
    print(f"Canvas CRS: {canvas_crs.authid()}")
    
    # Tool aktivieren
    current_tool = FluerstueckMapTool(canvas, config)
    canvas.setMapTool(current_tool)
    
    iface.messageBar().pushMessage(
        "Flurstück-Finder aktiv", 
        f"Klicke in die Karte. {len(config)} Bundesländer konfiguriert!",
        level=Qgis.MessageLevel.Info,
        duration=5
    )

# Tool starten
#karten_suche()