/**
 * @fileoverview map-cluster-mgr.js
 * Verwaltung der Cluster-Logik. map und markers kommen aus dem Service.
 * mapState bleibt als Parameter erhalten.
 */

import { showToast, mylog } from './sc-utilities.js';
import { UpdateMarkerIcon } from './map-poi-mgr.js';
import { demarcateElement } from './map-gen-mgr.js';
import { getMap, getMarkers, mapState as globalMapState } from './map-markers-co.js';
import { removeAddressMarker } from './gui-address-co.js';
import { ScStone } from './ScStone.js';
import { getPoiData } from './poi-store.js';
import { handleClusterSelectionBs } from './bs-cluster-co.js';
import { updateSearchFieldWithAddress } from './app-shell-co.js';
import { demarcate_route } from './map-poi-navigation.js';

/**
 * Aktualisiert den Reinigungsstatus aller Stolpersteine in einem Cluster.
 */
export function handleCleaningsStatusAllCluster(cluster, backendServiceInstance, needsCleaning) {
    const markersLayer = getMarkers();
    const childMarkers = cluster.getAllChildMarkers();

    const updatePromises = childMarkers.map(marker => {
        const stoneData = marker.options.data;
        const stoneInstance = new ScStone({ gid: stoneData.gid }, backendServiceInstance);

        return stoneInstance.updateCleaningStatus(needsCleaning)
            .then(response => {
                if (!response.success) throw new Error(`Fehler bei POI ${stoneData.gid}`);
                return {
                    success: true,
                    last_cleaned: response.last_cleaned,
                    needs_cleaning: response.needs_cleaning,
                    markerInstance: marker
                };
            })
            .catch(error => {
                showToast("Fehler", `Update fehlgeschlagen: ${error.message}`, 'error');
                return { success: false };
            });
    });

    Promise.all(updatePromises).then(results => {
        const successful = results.filter(r => r.success);
        successful.forEach(u => {
            u.markerInstance.options.data.last_cleaned = u.last_cleaned;
            u.markerInstance.options.data.needs_cleaning = u.needs_cleaning;
            UpdateMarkerIcon(u.markerInstance, false, globalMapState);
        });

        if (successful.length > 0) {
            if (markersLayer?.refreshClusters) markersLayer.refreshClusters();
            showToast(`${successful.length} Stolpersteine markiert.`);
        }
    });
}

/**
 * Stellt die ursprünglichen Styles eines Cluster-Icons wieder her.
 */
export function restoreClusterOriginalStyles(clusterElement, cluster) {
    if (!cluster || !clusterElement) return;

    clusterElement.style.removeProperty('z-index');
    clusterElement.style.removeProperty('opacity');
    clusterElement.style.removeProperty('box-shadow');
    clusterElement.style.removeProperty('border');
    clusterElement.style.removeProperty('border-radius');

    if (cluster._originalStyles) delete cluster._originalStyles;
}


/**
 * Haupt-Koordinator für Cluster-Klicks.
 */
export async function handleClusterSelection(clickedCluster, bottomSheetUI, backendService, mapState) {
    // 1. Initialisierung & Bereinigung
    removeAddressMarker();

    // 2. Adresse & Koordinaten beziehen
    const childMarkers = clickedCluster.getAllChildMarkers();
    if (childMarkers.length > 0) {
        // Wir reichen die Parameter einfach einzeln weiter
        syncClusterAddressToUi(childMarkers[0], bottomSheetUI);
    }

    // 3. Delegation an Spezialisten (mit alter Signatur)
    handleClusterSelectionMap(clickedCluster, bottomSheetUI, mapState);
    handleClusterSelectionBs(clickedCluster, bottomSheetUI, backendService, mapState);
}


function handleClusterSelectionMap(clickedCluster, bottomSheetUI, mapState) {
    const map = getMap();

    const priorContext = determinePriorContext(clickedCluster, mapState);
    const activeElement = mapState.activeMarkerOrCluster;

    if (activeElement && ['OtherClusterChild', 'OtherClusterParent', 'SinglePOI', 'SameClusterChild'].includes(priorContext)) {
        demarcateElement(activeElement, mapState);
    }


    if (['OtherClusterChild', 'OtherClusterParent', 'SinglePOI'].includes(priorContext)) {
        unspiderfyCluster(mapState);
    }

    if (priorContext !== 'SameClusterParent') {
        mapState.activeMarkerOrCluster = clickedCluster;

        if (['OtherClusterChild', 'OtherClusterParent', 'SinglePOI', 'None'].includes(priorContext)) {
            if (!willClusterSpiderfy(clickedCluster)) {
                map.fitBounds(clickedCluster.getBounds());
                bottomSheetUI.close();
                mapState.activeMarkerOrCluster = null;
                return;
            }
        }

        setTimeout(() => {
            clickedCluster.spiderfy();
            mapState.currentlySpiderfiedCluster = clickedCluster;
        }, 200);
    }

    if (clickedCluster._icon) {
        highlightCluster(clickedCluster._icon, clickedCluster, mapState);
    }
}

function syncClusterAddressToUi(referenceMarker, bottomSheetUI) {
    // Strikter Zugriff auf options.gid
    const gid = referenceMarker.options.gid;

    if (!gid) {
        console.warn("syncClusterAddressToUi: Keine GID in options gefunden.");
        return;
    }

    const poiData = getPoiData(gid);
    if (poiData) {
        bottomSheetUI.updateAddress(poiData.street, poiData.house_no, poiData.localdistrict);
        bottomSheetUI.setCoords({ lat: poiData.lat, lng: poiData.lng });

        if (typeof updateSearchFieldWithAddress === 'function') {
            updateSearchFieldWithAddress(bottomSheetUI.currentAddress);
        }
    } else {
        console.warn(`POI Daten für GID ${gid} nicht im Store gefunden.`);
    }
}

/**
 * Setup der Listener.
 */
export function setupClusterEventListeners(bottomSheetUI, backendService) {
    const markers = getMarkers();

    markers.on('spiderfied', (event) => {
        const cluster = event.cluster;
        const childMarkers = cluster.getAllChildMarkers();

        if (globalMapState.activeMarkerOrCluster) {
            demarcateElement(globalMapState.activeMarkerOrCluster, globalMapState);
        }

        const foundMarker = childMarkers.find(m => m.options.data?.gid === globalMapState.activeMarkerOrClusterGID);

        if (foundMarker) {
            UpdateMarkerIcon(foundMarker, true, globalMapState);
            globalMapState.activeMarkerOrCluster = foundMarker;
        } else if (cluster._icon) {
            highlightCluster(cluster._icon, cluster, globalMapState);
            globalMapState.activeMarkerOrCluster = cluster;
            globalMapState.activeMarkerOrClusterGID = cluster._leaflet_id;
        }

        cluster._isUserSpiderfied = true;
        globalMapState.currentlySpiderfiedCluster = cluster;
    });

    markers.on('unspiderfied', (event) => {
        const cluster = event.cluster;
        if (cluster._icon) restoreClusterOriginalStyles(cluster._icon, cluster);
        cluster._isUserSpiderfied = false;
        if (globalMapState.currentlySpiderfiedCluster === cluster) globalMapState.currentlySpiderfiedCluster = null;
    });

    markers.on('clusterclick', async (event) => {
            // Karte aufräumen 
    removeAddressMarker();
 //   demarcate_route(map);

        demarcate_route(getMap());


        await handleClusterSelection(event.layer, bottomSheetUI, backendService, globalMapState);
    });

    bottomSheetUI.onClose(() => {
        if (globalMapState.activeMarkerOrCluster) demarcateElement(globalMapState.activeMarkerOrCluster, globalMapState);
        globalMapState.activeMarkerOrCluster = null;
        globalMapState.activeMarkerOrClusterGID = null;
        globalMapState.currentlySpiderfiedCluster = null;
    });
}

/**
 * Interne Hilfsfunktionen -> in map-gen-mgr
 */
export function determinePriorContext(clickedCluster, state) {
    const activeElement = state.activeMarkerOrCluster;
    if (!activeElement) return 'None';
    if (activeElement === clickedCluster) return 'SameClusterParent';

    const isCluster = typeof clickedCluster.getAllChildMarkers === 'function';

    if (activeElement.getAllChildMarkers && isCluster) return 'OtherClusterParent';
    if (activeElement instanceof L.Marker) {
        const activeGID = activeElement.options.gid;
        const isSame = isCluster && clickedCluster.getAllChildMarkers().some(m => m.options.gid === activeGID);
        return isSame ? 'SameClusterChild' : 'SinglePOI';
    }
    return 'None';
}

export function willClusterSpiderfy(cluster) {
    const childMarkers = cluster.getAllChildMarkers();
    if (childMarkers.length < 50 && childMarkers.length > 1) {
        const bounds = cluster.getBounds();
        return bounds.getNorthWest().distanceTo(bounds.getSouthEast()) <= 5;
    }
    return childMarkers.length < 50;
}

export function unspiderfyCluster(mapState) {
    const markers = getMarkers();
    if (mapState.currentlySpiderfiedCluster) {
        markers.unspiderfy();
        mapState.currentlySpiderfiedCluster = null;
    }
}

export function highlightCluster(clusterElement, cluster, mapState) {
    if (!cluster._originalStyles) {
        cluster._originalStyles = {
            zIndex: clusterElement.style.zIndex,
            opacity: clusterElement.style.opacity,
            boxShadow: clusterElement.style.boxShadow,
            border: clusterElement.style.border,
            borderRadius: clusterElement.style.borderRadius
        };
    }
    clusterElement.style.zIndex = '1000';
    clusterElement.style.opacity = '1';
    clusterElement.style.boxShadow = '0 0 20px rgba(0,0,0,0.7)';
    clusterElement.style.border = '5px solid black';
    clusterElement.style.borderRadius = '50%';
}