/**
 * @fileoverview map-cluster-mgr.js
 * Verwaltung der Karten-Logik für Cluster (Highlighting, Spiderfy, Selektion).
 */

import { appEvents, mylog } from './utilities.js';

import { L,     mapState, getMarkers, setMap, setMarkers } from './map-service.js';
import { getPoiData } from './poi-store.js';
/**
 * Berechnet, ob ein Cluster aufgrund seiner Ausdehnung "spiderfied" werden soll.
 * Wichtig als Gatekeeper vor der Selektion.
 */
export function willClusterSpiderfy(cluster) {
    const childMarkers = cluster.getAllChildMarkers();
    if (childMarkers.length < 50 && childMarkers.length > 1) {
        const bounds = cluster.getBounds();
        // Wenn die Marker extrem nah beieinander liegen (< 5m), immer Spiderfy
        return bounds.getNorthWest().distanceTo(bounds.getSouthEast()) <= 5;
    }
    return childMarkers.length < 50;
}


/**
 * Verarbeitet die Cluster-Selektion über das globale Event-System,
 * um direkte Abhängigkeiten zur Kartensteuerung zu vermeiden.
 */
export function handleClusterSelectionMap(clickedCluster, bottomSheetUI, mapState, origin) {
    mylog(`[Cluster-Map] Selektion getriggert für ID: ${clickedCluster._leaflet_id} | Origin: ${origin}`);

    return new Promise((resolve) => {
        appEvents.dispatchEvent(new CustomEvent('cluster:executeNavigation', {
            detail: {
                cluster: clickedCluster,
                origin,
                resolve
            }
        }));
    });
}

/**
 * Initialisiert die Event-Listener (Spiderfy & ClusterClick).
 */
export function setupClusterEventListeners() {
    const markers = getMarkers();
    if (!markers) return;

    markers.on('clusterclick', (event) => {
        L.DomEvent.stopPropagation(event);
        appEvents.dispatchEvent(new CustomEvent('cluster:requestSelection', {
            detail: {
                cluster: event.layer,
                firstGid: event.layer.getAllChildMarkers()[0]?.options.gid,
                    origin: 'click'
            }
        }));
    });
}


/**
 * Aktualisiert das visuelle Erscheinungsbild eines Clusters.
 * @param {L.MarkerCluster} cluster - Das Leaflet Cluster-Objekt
 * @param {boolean} isHighlighted - Soll das Cluster hervorgehoben werden?
 */
/**
 * Aktualisiert das visuelle Erscheinungsbild eines Clusters mit einem satten blauen Ring.
 */
/**
 * Aktualisiert das visuelle Erscheinungsbild eines Clusters.
 * Nutzt die zentrale isSquareType-Logik für konsistente Formen.
 */
/**
 * Aktualisiert das visuelle Erscheinungsbild eines Clusters.
 */
export function updateClusterIcon(cluster, isHighlighted) {
    if (!cluster || !cluster._icon) return;

    const container = cluster._icon;
    // Wir suchen das Div mit dem Ring
    const inner = container.querySelector('.cluster-ring-outline') || container.querySelector('div') || container;

    // 1. Form bestimmen: Nur noch über die CSS-Klasse 'is-square'
    const isSquare = inner.classList.contains('is-square');
    const radius = isSquare ? '3px' : '50%';

    if (isHighlighted) {
        cluster.setZIndexOffset(5000);
        container.style.setProperty('opacity', '1', 'important');
        container.style.setProperty('overflow', 'visible', 'important');
        
        // Blaue Selektion (Schatten folgt dem Radius -> Quadrat bleibt Quadrat)
        inner.style.setProperty('border-radius', radius, 'important');
        inner.style.setProperty('box-shadow', '0 0 0 2px #ffffff, 0 0 0 6px #007AFF', 'important');
        inner.style.setProperty('opacity', '1', 'important');
    } else {
        cluster.setZIndexOffset(0);
        container.style.removeProperty('opacity');
        
        // Reset: Blauen Ring weg, Form (Radius) bleibt
        inner.style.removeProperty('box-shadow');
        inner.style.setProperty('border-radius', radius, 'important');
    }
}
/**
 * Prüft anhand der Koordinaten und GIDs, ob ein Element (Cluster oder Marker) 
 * als Quadrat (Adresse) dargestellt werden soll.
 */
/**
 * Prüft via POI-Store, ob ein Element (Cluster oder Marker) eine Adresse (Quadrat) ist.
 */
export function isSquareType(latlng, childMarkers = []) {
    // 1. GIDs sammeln
    let gids = [];
    if (childMarkers.length > 0) {
        gids = childMarkers.map(m => parseInt(m.options.gid)).filter(Number);
    } else {
        // Falls nur ein einzelner LatLng übergeben wurde (Einzel-POI)
        // nutzen wir deine existierende Funktion, um die GIDs an dieser Stelle zu finden
        gids = getNearbyGids(latlng);
    }

    if (gids.length < 2) return false;

    // 2. Daten aus dem Store holen (Single Source of Truth)
    const storePositions = gids.map(gid => {
        const data = getPoiData(gid); // Muss importiert sein!
        return data ? L.latLng(data.lat, data.lng) : null;
    }).filter(pos => pos !== null);

    if (storePositions.length < 2) return false;

    // 3. Der Check: Sind die Original-Koordinaten im Store identisch/nah?
    const firstPos = storePositions[0];
    const isActuallySameAddress = storePositions.every(pos => 
        pos.distanceTo(firstPos) < 1 // Weniger als 1 Meter Abweichung im Store
    );

    return isActuallySameAddress;
}

/**
 * Aktualisiert die Cluster-Farben auf allen Ebenen.
 * @param {L.Marker} marker - Der betroffene Leaflet-Marker.
 */
export function updateClusterIconColor(marker) {
    if (!marker) return;

    // Referenz auf das übergeordnete Cluster (versionsabhängig __parent oder _parent)
    let parent = marker.__parent || marker._parent;

    while (parent) {
        
        // Weg A: Direktes Update des Cluster-Icons (für geschlossene Cluster).
        if (typeof parent.refreshIcon === 'function') {
            parent.refreshIcon();
        } 
        
        // Weg B: Logische Synchronisation mit der Cluster-Gruppe.
        // Markiert das Cluster innerhalb der Gruppe als zu aktualisierend. 
        // Dies stellt sicher, dass die Änderung auch dann übernommen wird, wenn das Cluster 
        // gerade im Spiderfy-Modus (auseinandergezogen) ist oder neu berechnet wird.
        if (parent._group && typeof parent._group.refreshClusters === 'function') {
            parent._group.refreshClusters(parent);
        }

        // Rekursiver Aufstieg zur nächsten Cluster-Ebene
        parent = parent.__parent || parent._parent;
    }
}
