/**
 * @fileoverview map-poi-mgr.js
 * Verwaltet die Erstellung, Optik und Events von POI-Markern auf der Karte.
 */

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

    fitMapToTarget
} from './map-gen-mgr.js';
import { L,     mapState,getMap, getMarkers} from './map-service.js';

import { getPoiStore, getPoiData, updatePoiStore , updateSinglePoiInStore} from './poi-store.js';
import { Poi } from './poi.js';
import { mylog, showToast, wait, getMarkerIcon, getColorCodeAndText } from './utilities.js';
// import { fetchCoordForAddress } from './validate_address.js';


let tempMarker;

export function isMarkerHighlighted(gid, mapState) {
    return (gid === mapState.activeMarkerOrClusterGID);
}

/**
 * Aktualisiert das Icon eines poi-Markers basierend auf Status und Highlight-Zustand. Blauer ring
 */


export function UpdateMarkerIcon(marker, isHighlighted) {
    const markerData = getPoiData(marker.options.gid);
    if (!markerData) return;

    const { colorCode } = getColorCodeAndText(markerData.last_cleaned);
    let iconHtml = getMarkerIcon(markerData.caretaker, colorCode);

    const size = 50;

    if (isHighlighted) {
        // 1. Der äußere Kreis (Blau)
        const wrapperStyle = [
            `width: ${size}px`,
            `height: ${size}px`,
            `display: flex`,
            `align-items: center`,
            `justify-content: center`,
            `border-radius: 50%`,
            `outline: 4px solid #007AFF`,
            `outline-offset: 1px`,
            `background: transparent`,
            `box-sizing: border-box`,
            `margin-top: 5px`,   // Schiebt den blauen Kreis nach unten
            `border: none`,      // Entfernt mögliche Standard-Ränder (der "zweite Kreis")
            `box-shadow: none`   // Entfernt Schatten, die den Geister-Effekt erzeugen
        ].join(';');

        // 2. Das Dreieck (hochgezogen mit deinen Werten)
        const iconCorrectionStyle = `position: relative; top: -5px; display: block;`;

        iconHtml = `
            <div style="${wrapperStyle}">
                <div style="${iconCorrectionStyle}">${iconHtml}</div>
            </div>`;
    }

    const newIcon = L.divIcon({
        className: 'poi-icon ' + colorCode, // Behält die Farbe bei
        html: iconHtml,
        iconSize: [size, size],
        iconAnchor: [size / 2, size / 2] // Anker mittig lassen
    });

    marker.setIcon(newIcon);

    // WICHTIG: Den Leaflet-Standard-Container bereinigen
    const el = marker.getElement();
    if (el) {
        el.style.background = 'none';
        el.style.border = 'none';
        el.style.shadow = 'none';
    }

    marker.setZIndexOffset(isHighlighted ? 1000 : 0);
}


export function handlePoiSelectionMap(gid, origin) {
    const map = getMap();
    const marker = findMarkerByGid(gid);

    if (!marker) return;

    const markersGroup = getMarkers();
    let cluster = null;
    if (markersGroup) {
        const visibleParent = markersGroup.getVisibleParent(marker);
        if (visibleParent && visibleParent !== marker) {
            cluster = visibleParent;
        }
    }

    demarcatePriorContext(marker, mapState);

    // --- VERWANDLUNG: origin -> Navigations-Modus ---
    // Wenn die Suche (search) die Quelle ist, nutzen wir einen Modus, 
    // der in fitMapToTarget die Zentrierung priorisiert.
 // --- DIE WEICHE mit navigationMode ---
    let navigationMode;

    if (origin === 'search') {
        // Suche erzwingt die volle Zentrierung
        navigationMode = 'CENTER'; 
    } else if (origin === 'headerClick' || origin === 'swipe') {
        // Header/Swipe nutzt die Minimal-Navigation (Safe-Viewport Check)
        navigationMode = 'TOVIEWPORT'; 
    } else {
        // Standard für normale Klicks
        navigationMode = 'RESIZE';
    }

    mylog(`[Map] Selektion GID: ${gid} | Origin: ${origin} | Mode: ${navigationMode}`);

    // fitMapToTarget erhält nun den spezifischen Modus
    fitMapToTarget(gid, marker.getLatLng(), cluster, navigationMode);

    // State Updates
    mapState.activeMarkerOrCluster = marker;
    mapState.activeMarkerOrClusterGID = gid;
  
    UpdateMarkerIcon(marker, true);

}



/**
 * Neuen Marker hinzufügen
 */
export function addNewMarkerFromStore(gid) {
    const poi = getPoiData(gid);
    if (!poi) return;

    const markers = getMarkers();
    const statusInfo = getColorCodeAndText(poi.last_cleaned);
    const colorCode = statusInfo.colorCode;

    const marker = L.marker([poi.lat, poi.lng], {
        icon: L.divIcon({
            className: "poi-icon " + colorCode,
            html: getMarkerIcon(poi.caretaker, colorCode),
            iconSize: mapState.originalActiveMarkerSize,
        }),
        gid: poi.gid
    });

    marker.on('click', function (event) {
        if (event) L.DomEvent.stopPropagation(event);

        appEvents.dispatchEvent(new CustomEvent('poi:requestSelection', {
            detail: { gid: this.options.gid, parentCluster: this.__parent, origin: 'click'  }
        }));
    });

    markers.addLayer(marker);
    Promise.resolve().then(() => {
        appEvents.dispatchEvent(new CustomEvent('map:refreshMarkersDone', {
            detail: { gid: gid }
        }));
    });
}



export async function loadPois(backendService, loadingUpdateCallback) {
    // 1. Daten vom Backend holen
    const features = await backendService.fetchAllPois(loadingUpdateCallback);
    
    // 2. In Poi Instanzen umwandeln und im Store registrieren
    const poiInstances = features.map(feature => {
        const coords = feature.geometry?.coordinates;
        if (!coords) return null;
        return new Poi({
            ...feature.properties,
            lat: parseFloat(coords[1]),
            lng: parseFloat(coords[0])
        });
    }).filter(p => p !== null);

    updatePoiStore(poiInstances);
    return poiInstances;
}

export function renderPois() {
    const markers = getMarkers();
    const map = getMap();
    
    // Bestehende Marker/Spider-Beine entfernen
    markers.clearLayers();
    
    const poiMarkers = [];
    const store = getPoiStore();

    // Über den vorhandenen Store iterieren
    store.forEach((poiInstance) => {
        const status = getColorCodeAndText(poiInstance.last_cleaned);
        const marker = L.marker([poiInstance.lat, poiInstance.lng], {
            icon: createPoiIcon(poiInstance.caretaker, status.colorCode),
            gid: poiInstance.gid
        });

        marker.on('click', (e) => {
            L.DomEvent.stopPropagation(e);
            appEvents.dispatchEvent(new CustomEvent('poi:requestSelection', {
                detail: { gid: marker.options.gid, parentCluster: marker.__parent, origin: 'click' }
            }));
        });

        poiMarkers.push(marker);
    });

    markers.addLayers(poiMarkers);
    if (!map.hasLayer(markers)) {
        map.addLayer(markers);
    }
    
    mylog(`Map-POI-Mgr: ${poiMarkers.length} Marker aus Store gerendert.`);
}

// Initialer Aufruf kombiniert beides
export async function loadAndRenderPois(backendService, loadingUpdateCallback) {
    await loadPois(backendService, loadingUpdateCallback);
    renderPois();
}

function createPoiIcon(caretaker, colorCode, size = 30) {
    return L.divIcon({
        className: "poi-icon " + colorCode,
        html: getMarkerIcon(caretaker, colorCode),
        iconSize: [size, size],
        iconAnchor: [size / 2, size / 2] 
    });
}
/**
 * Aktualisiert einen einzelnen POI asynchron, berechnet Cluster neu und behält den Fokus.
 * Nutzt den spezialisierten Store-Merge und stellt sicher, dass Poi-Methoden erhalten bleiben.
 */
export async function refreshPoiAndClusters(gid, updatedData) {
    const markersGroup = getMarkers();
    const oldMarker = findMarkerByGid(gid);

    if (!markersGroup || !oldMarker) {
        mylog(`[Update] Marker GID ${gid} nicht auf Karte gefunden. Abbruch.`);
        return;
    }

    // 1. Daten im Store aktualisieren & Mergen
    // Wir nutzen hier direkt die spezialisierte Map-Logik deines Stores

    updateSinglePoiInStore(updatedData); 

    // Die "mergedData" sind nun die absolut aktuellen Daten inkl. aller Poi-Methoden
    const mergedData = getPoiData(gid); 
    if (!mergedData) return;

    // 2. Den alten Marker entfernen (bevor wir den neuen hinzufügen)
    markersGroup.removeLayer(oldMarker);

    // 3. Status für Icon berechnen
    const { colorCode } = getColorCodeAndText(mergedData.last_cleaned);

    // 4. Neuen Marker erstellen (direkt an den neuen Koordinaten)
    const newMarker = L.marker([mergedData.lat, mergedData.lng], {
        icon: createPoiIcon(mergedData.caretaker, colorCode),
        gid: gid
    });

    // 5. Klick-Event binden (für konsistente UI-Reaktion)
    newMarker.on('click', (e) => {
        if (e) L.DomEvent.stopPropagation(e);
        appEvents.dispatchEvent(new CustomEvent('poi:requestSelection', {
            detail: { gid: gid, parentCluster: newMarker.__parent, origin: 'click' }
        }));
    });

    // 6. In die Cluster-Gruppe integrieren (erzwingt Re-Clustering an neuer Position)
    await markersGroup.addLayer(newMarker);

    // 7. State-Synchronisation: Den neuen Marker als "aktiv" markieren
    mapState.activeMarkerOrCluster = newMarker;
    mapState.activeMarkerOrClusterGID = gid;
    
    // Blauen Ring (Highlight) sofort auf den neuen Marker setzen
    UpdateMarkerIcon(newMarker, true);

    // 8. Kamera-Check: Wo befindet sich der Marker jetzt? (Cluster oder Einzeln)
    const visibleParent = markersGroup.getVisibleParent(newMarker);
    const targetCluster = (visibleParent && visibleParent !== newMarker) ? visibleParent : null;

    // Karte nachführen (RESIZE Modus wahrt den aktuellen Zoom-Kontext)
    fitMapToTarget(gid, newMarker.getLatLng(), targetCluster, 'RESIZE');

    mylog(`[Update-Success] GID ${gid} umgezogen nach: ${mergedData.lat}, ${mergedData.lng}`);
}