// bs-po-co,js
/*
UI-Lifecycle: Koordination des Bottom Sheets und Listener-Cleanup.

Singleton-Datenfluss: Bezug stabiler Daten über map-markers-co und poi-store.

Abstrahierte Zugriffskontrolle: Nutzung von checkDistance zur Entkopplung von räumlicher Logik und UI-Anzeige.

Backend-Synchronität: Unmittelbare Updates des Marker-Status via ScStone.

Content-Handling: Automatisierte Aufbereitung von HTML, Scraping von Biografien und Sprachausgabe.
*/
import { getAdminMode } from './admin-mode-co.js';
import { detachAllBsListeners } from './bs-gen-co.js';
import { attachSwipeListeners } from './bs-cluster-co.js';
import { findMarkerByGid } from './map-gen-mgr.js';
import { getMap, getMarkers } from './map-markers-co.js';
import { UpdateMarkerIcon, isMarkerHighlighted } from './map-poi-mgr.js';
import { getColorCodeAndText } from './marker-display-utils.js';
import { getPoiData } from './poi-store.js';
import { LocationTrackingCoordinator } from './loc-tracking-co.js';
import { handleReadBiography, cancelSpeech } from './poi-speech-service.js';
import { ScStone } from './ScStone.js';
import { showToast, is_development, checkDistance , mylog} from './sc-utilities.js';
import { createUpdateClickHandler } from './update-poi-details-co.js';


let poiReadButtonHandler = null;

/**
 * Die Hauptfunktion, die das Bottom Sheet aktualisiert.
 * @param {L.Marker} clickedMarker
 * @param {BsUI} bottomSheetUI
 * @param {BackendService} backendService
 * @param {Object} mapState
 * @param {InsertPoiUI} addButtonUIInstance
 * @param {UpdatePoiUI} updatePoiUIInstance
 */
/**
 * Die Hauptfunktion, die das Bottom Sheet aktualisiert.
 */
export function updateBsForPoi(gid, {
    bottomSheetUI,
    backendService,
    mapState,
    insertPoiUI,
    updatePoiUI
}) {
    const map = getMap();
mylog ("updatebsforpoi start")
    // 1. Bereinigung
    detachAllBsListeners(bottomSheetUI);
    detachPoiButtonListeners(bottomSheetUI);

    cancelSpeech();

    // 2. Daten & Instanzen
    const clickedMarker = findMarkerByGid(gid);
    // 2. Das Objekt für die gesamte Klasse bekannt machen
    bottomSheetUI.setClickedObject(clickedMarker);
    const storeData = getPoiData(gid);
    const scStoneInstance = new ScStone({ gid: gid }, backendService);

    const { contentHtml, options } = getBottomSheetDataAndActions(storeData);

    // 3. UI befüllen
    //bottomSheetUI.setBsHeaderText(`${storeData.first_name || ''} ${storeData.last_name || ''} ↗`);
    bottomSheetUI.setBsHeaderText(`${storeData.first_name} ${storeData.last_name} <i class="fas fa-external-link-alt" style="font-size: 0.8em; margin-left: 5px;"></i>`);
    bottomSheetUI.setContent(contentHtml);
    bottomSheetUI.setActions(options);
    bottomSheetUI.setCoords({ lat: Number(storeData.lat), lng: Number(storeData.lng) });

    // 4. Cluster-Logik
    const parentCluster = mapState.parentClusterOfActiveMarker;
    if (parentCluster) {
        bottomSheetUI.setNavButtonsState(true, true);
        // Wir geben das gesamte Objekt für die Swipe-Listener weiter
        attachSwipeListeners(bottomSheetUI, parentCluster, arguments[1]);
    } else {
        bottomSheetUI.setNavButtonsState(false, false);
    }

    // 5. Listener binden
    attachActionListeners(
        bottomSheetUI,
        clickedMarker,
        scStoneInstance,
        insertPoiUI, // Hier passen wir die Namen an dein allParams an
        updatePoiUI,
        backendService,
        mapState,
        options
    );
}

/**
 * Hängt Event-Listener an die Aktionen im Bottom-Sheet an.
 */
function attachActionListeners(
    bottomSheetUI, marker, scStoneInstance,
    addButtonUIInstance, updatePoiUIInstance, backendService, mapState, options) {

    // Singletons intern holen
    // const markers = getMarkers();
    // const map = getMap();

    console.debug('DEBUG: attachActionListeners: Starte Listener-Attachement für POI.');

    const poiCleanButton = bottomSheetUI._poiCleanButton;
    const poiDirtyButton = bottomSheetUI._poiDirtyButton;
    const fallbackButton = bottomSheetUI._fallbackButton;

    // const { options } = getBottomSheetDataAndActions(marker);

    if (options.showFallbackButton && fallbackButton) {
        fallbackButton.classList.remove('hidden');
        fallbackButton.textContent = options.fallbackButtonText;

        const fallbackClickHandler = function () {
            showToast("Bitte nähere dich dem Stolperstein, um ihn zu markieren.");
        };
        fallbackButton.addEventListener('click', fallbackClickHandler);
        fallbackButton._fallbackButtonListener = fallbackClickHandler;
    }

    else if (options.showMainActionDiv) {
        if (options.showPoiCleanButton && poiCleanButton) {
            poiCleanButton.classList.remove('hidden');
            poiCleanButton.textContent = "Der Zustand ist gut";

            const cleanClickHandler = createCleanClickHandler(marker, mapState, scStoneInstance);
            poiCleanButton.addEventListener('click', cleanClickHandler);
            poiCleanButton._cleanButtonListener = cleanClickHandler;
        }

        if (options.showPoiDirtyButton && poiDirtyButton) {
            poiDirtyButton.classList.remove('hidden');
            poiDirtyButton.textContent = "Der Zustand ist schlecht";

            const dirtyClickHandler = createDirtyClickHandler(marker, mapState, scStoneInstance);
            poiDirtyButton.addEventListener('click', dirtyClickHandler);
            poiDirtyButton._dirtyButtonListener = dirtyClickHandler;
        }
    }

    if (!poiReadButtonHandler) {
        poiReadButtonHandler = handleReadButtonClick;
        document.body.addEventListener('click', poiReadButtonHandler);
        console.log("DEBUG: TTS-Body-Listener einmalig ATTACHED.");
    }

    const caretakerCheckbox = bottomSheetUI._caretakerCheckbox;
    if (caretakerCheckbox) {
        const handleCaretakerChange = async function () {
            const gid = parseInt(marker.options.data.gid, 10);
            const isChecked = this.checked;
            if (isNaN(gid)) {
                console.error("Fehler: GID des Markers ist keine gültige Zahl.");
                return;
            }
            await handleCaretakerCheckboxChange(marker, mapState, isChecked, scStoneInstance);
        };
        caretakerCheckbox.addEventListener('change', handleCaretakerChange);
        caretakerCheckbox._caretakerChangeListener = handleCaretakerChange;
    }

    const editButton = bottomSheetUI.editButton;
    if (editButton) {
        const handleEditClick = function (event) {
            event.stopPropagation();

            createUpdateClickHandler(
                bottomSheetUI,
                marker,
                backendService,
                mapState,
                addButtonUIInstance,
                updatePoiUIInstance
            )();
        };

        editButton.addEventListener('click', handleEditClick);
        editButton._editButtonListener = handleEditClick;
    }
    console.debug('DEBUG: attachActionListeners: Listener-Attachement für POI abgeschlossen.');
}

function getBottomSheetDataAndActions(poiData) {
    // poiData enthält bereits lat, lng, first_name, last_name, caretaker etc.
    const lat = Number(poiData.lat);
    const lng = Number(poiData.lng);

    let isCaretaker = poiData.caretaker !== "" && poiData.caretaker !== null;
    let caretakerStatus = poiData.caretaker || "";
    let isCaretakerAnonym = caretakerStatus === "anonym";

    const locTrackingCoordinator = LocationTrackingCoordinator.getInstance();
    const currentUserPosition = locTrackingCoordinator.getUserPosition();

    // Distanzprüfung gegen die stabilen Store-Koordinaten
    const isNearby = (currentUserPosition && lat && lng)
        ? checkDistance(
            currentUserPosition[0],
            currentUserPosition[1],
            lat,
            lng,
            99
        )
        : false;

    const isAdmin = getAdminMode.getStatus();
    const showActiveState = isNearby || isAdmin;

    const options = {
        showCaretaker: showActiveState,
        isCaretaker: isCaretaker,
        caretakerLabelText: 'Putzpatenschaft',
        showMainActionDiv: showActiveState,
        showFallbackButton: !showActiveState,
        fallbackButtonText: "Adresse aufsuchen, um den Zustand zu erfassen",
        showPoiCleanButton: showActiveState,
        showPoiDirtyButton: showActiveState,
        showAddButton: showActiveState,
        showEditButton: showActiveState,
    };

    return {
        contentHtml: getPOIContentHtml(poiData), // Auch hier nur noch Daten übergeben
        options: options
    };
}

/**
 * Erstellt eine Klick-Handler für den "Ist sauber" Button.
 * @param {L.Marker} marker
 * @param {Object} mapState
 * @param {ScStone} scStoneInstance
 */
function createCleanClickHandler(marker, mapState, scStoneInstance) {
    const markers = getMarkers();
    return async function () {
        const poiId = parseInt(marker.options.data.gid, 10);
        if (isNaN(poiId)) {
            showToast("Fehler: Stolperstein-ID ungültig.");
            return;
        }
        try {
            const result = await scStoneInstance.updateCleaningStatus(false);
            if (result.success && result.last_cleaned) {
                marker.options.data.last_cleaned = result.last_cleaned;
                marker.options.data.needs_cleaning = false;
                UpdateMarkerIcon(
                    marker,
                    isMarkerHighlighted(marker.options.data.gid, mapState));
                markers.refreshClusters();
                showToast("Zustand als gut markiert ✅");
            } else {
                showToast("Fehler", `Fehler beim Aktualisieren des Status: ${result.error || 'Backend hat kein Datum zurückgegeben.'}`);
            }
        } catch (error) {
            console.error("Fehler beim Senden der Statusaktualisierung:", error);
            showToast("Fehler", "Fehler beim Senden der Statusaktualisierung.");
        }
    };
}

/**
 * Erstellt einen Klick-Handler für das Markieren eines Stolpersteins als 'schmutzig'.
 * @param {L.Marker} marker
 * @param {Object} mapState
 * @param {ScStone} scStoneInstance
 */
function createDirtyClickHandler(marker, mapState, scStoneInstance) {
    const markers = getMarkers();
    return async function () {
        const poiId = parseInt(marker.options.data.gid, 10);
        if (isNaN(poiId)) {
            showToast("Fehler: Stolperstein-ID ungültig.");
            return;
        }

        try {
            const result = await scStoneInstance.updateCleaningStatus(true);
            if (result.success && result.last_cleaned) {
                marker.options.data.last_cleaned = result.last_cleaned;
                marker.options.data.needs_cleaning = true;
                UpdateMarkerIcon(
                    marker,
                    isMarkerHighlighted(marker.options.data.gid, mapState));
                markers.refreshClusters();
                showToast("Zustand als schlecht markiert 🔴");
            } else {
                showToast("Fehler", `Fehler beim Aktualisieren des Status auf 'ungesäubert': ${result.error || 'Backend hat kein Datum zurückgegeben.'}`);
            }
        } catch (error) {
            console.error("Fehler beim Senden der Dirty-Statusaktualisierung:", error);
            showToast("Fehler", "Fehler beim Senden der Dirty-Statusaktualisierung.");
        }
    };
}

async function handleCaretakerCheckboxChange(marker, mapState, isChecked, scStoneInstance) {
    const action = isChecked ? 'set' : 'remove';
    try {
        const result = await scStoneInstance.updateCaretakerStatus(action);
        if (result.success) {
            marker.options.data.caretaker = isChecked ? 'anonym' : '';
            UpdateMarkerIcon(
                marker,
                isMarkerHighlighted(marker.options.data.gid, mapState));
            showToast(`Putzpatenschaft ${isChecked ? 'gesetzt' : 'entfernt'}!`);
        } else {
            showToast("Fehler", `Fehler beim Aktualisieren der Patenschaft: ${result.error || 'Unbekannter Fehler.'}`);
        }
    } catch (error) {
        console.error("Fehler beim Senden der Patenschaftsaktualisierung:", error);
        showToast("Fehler", "Fehler beim Senden der Patenschaftsaktualisierung.");
    }
}

function getPOIContentHtml(poiData) {
    let ContentHtml = `<div class="POI-details">`;
    const data = poiData;
    const color = getColorCodeAndText(data.last_cleaned).colorCode;

    function formatLastCleanedDate(dateString) {
        if (!dateString) {
            return '\?';
        }
        const date = new Date(dateString);
        const options = {
            day: '2-digit',
            month: '2-digit',
            year: 'numeric'
        };
        return date.toLocaleDateString('de-DE', options);
    }

    const formattedDate = formatLastCleanedDate(data.last_cleaned);
    const biographyUrl = data.url_kodb;
    const streetModified = data.street.slice(0, -1) + '*';
    const positionModified = data.stone_position ? '<br>Verlegeort: ' + data.stone_position : ''

    const wikipediaSearchTerms = [
        'Stolperstein',
        data.first_name,
        data.last_name,
        data.year_of_birth,
        streetModified
    ];
    const wikipediaUrl = `https://de.wikipedia.org/wiki/Spezial:Suche?search=${wikipediaSearchTerms.map(term => encodeURIComponent(term)).join('+')}`;

    ContentHtml += `
    <div class="poi-list-item ${color}-marker">
        <p>geboren ${data.year_of_birth}
        ${positionModified}
        <br>Reinigung: ${formattedDate}
        <br><a href="${biographyUrl}" target="_blank">Biographie</a>
        <button class="read-biography-btn" data-url="${biographyUrl}" style="cursor: pointer; background: none; border: none; padding: 0; color: #1e40af;">
            <i class="fas fa-volume-up"></i> Hören
        </button>
        <br><a href="${wikipediaUrl}" target="_blank">Wikipedia</a>
        <br>GID: ${data.gid}
    </div>
    `;
    return ContentHtml;
}

async function handleReadButtonClick(event) {
    const button = event.target.closest('.read-biography-btn');
    if (!button) return;

    const biographyUrl = button.dataset.url;
    // Die ganze "knifflige" Arbeit macht jetzt der Service
    await handleReadBiography(biographyUrl);
}

 export function detachPoiButtonListeners(bottomSheetUI) {
    const poiCleanButton = bottomSheetUI._poiCleanButton;
    if (poiCleanButton && poiCleanButton._cleanButtonListener) {
        poiCleanButton.removeEventListener('click', poiCleanButton._cleanButtonListener);
        delete poiCleanButton._cleanButtonListener;
        console.log("DEBUG: POI Clean Button Listener detached.");
    }

    const poiDirtyButton = bottomSheetUI._poiDirtyButton;
    if (poiDirtyButton && poiDirtyButton._dirtyButtonListener) {
        poiDirtyButton.removeEventListener('click', poiDirtyButton._dirtyButtonListener);
        delete poiDirtyButton._dirtyButtonListener;
        console.log("DEBUG: POI Dirty Button Listener detached.");
    }

    const fallbackButton = bottomSheetUI._fallbackButton;
    if (fallbackButton && fallbackButton._fallbackButtonListener) {
        fallbackButton.removeEventListener('click', fallbackButton._fallbackButtonListener);
        delete fallbackButton._fallbackButtonListener;
        console.log("DEBUG: Fallback Button Listener detached.");
    }

    const caretakerCheckbox = bottomSheetUI._caretakerCheckbox;
    if (caretakerCheckbox && caretakerCheckbox._caretakerChangeListener) {
        caretakerCheckbox.removeEventListener('change', caretakerCheckbox._caretakerChangeListener);
        delete caretakerCheckbox._caretakerChangeListener;
        console.log("DEBUG: Caretaker Checkbox Listener detached.");
    }

    const editButton = bottomSheetUI.editButton;
    if (editButton && editButton._editButtonListener) {
        editButton.removeEventListener('click', editButton._editButtonListener);
        delete editButton._editButtonListener;
        console.log("DEBUG: Edit Button Listener detached.");
    }
}

export function handleMarkerSelectionBs(gid, allParams) {
    const { bottomSheetUI } = allParams;

    // Den Inhalt im Bottom Sheet aktualisieren
    // WICHTIG: Wir nutzen jetzt die kompakte Signatur (gid, allParams)
    updateBsForPoi(gid, allParams);

    // Nur öffnen, wenn es nicht schon offen ist (verhindert Zucken beim Swipen)
    if (!bottomSheetUI.isOpen()) {
        bottomSheetUI.open();
    }
}