/**
 * @fileoverview bs-gen-ui.js
 * BottomSheet UI - Stabilisierte Fassung.
 * Trennung von Foto-Stack (Header) und Content (Text/Links).
 */

import { mylog } from "./utilities.js";
import { cancelSpeech } from "./poi-speech-service.js";

export class BsUI extends EventTarget {
    static instance = null;
    _displayedObject = null;
    isExpanded = false;
    _currentCoords = null;

    currentAddress = { street: '', houseNr: '', localDistrict: '' };
    closeCallbacks = [];
    _headerClickCallback = null;
    _onResizeCallback = null;
    _onHeaderSwipeHorizontal = null;

    static getInstance() {
        return BsUI.instance;
    }

    constructor(wrapperId, elementId, contentAreaId, actionsAreaId) {
        super();
        if (BsUI.instance) return BsUI.instance;

        this.wrapperId = wrapperId;
        this.elementId = elementId;
        this.contentAreaId = contentAreaId;
        this.actionsAreaId = actionsAreaId;

        this._defineTemplates();
        this._injectCSS();
        this._injectHTML();
        this._cacheElements();
        this._initBasicUiEvents();
        this._setupHeaderInteractions();

        this.close();
        BsUI.instance = this;
    }

    setClickedObject(obj) { this._displayedObject = obj; }
    getClickedObject() { return this._displayedObject; }
    setCoords(coords) { this._currentCoords = coords ? { lat: coords.lat, lng: coords.lng } : null; }
    getCoords() { return this._currentCoords; }
    updateAddress(s, h, l) { this.currentAddress = { street: s || '', houseNr: h || '', localDistrict: l || '' }; }

    setBsTitle(text) { if (this.headerTitle) this.headerTitle.innerHTML = text; }
    setBsLocation(text) { if (this.headerLocation) this.headerLocation.innerHTML = text; }

 _defineTemplates() {
        const cameraIcon = `
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink: 0;">
            <path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path>
            <circle cx="12" cy="13" r="4"></circle>
        </svg>`;

        this.panelHTML = `
        <div id="${this.wrapperId}" class="bottom-sheet-wrapper hidden">
            <div class="bottom-sheet-toggle-handle"><i class="fas fa-chevron-up"></i></div>
            <div id="${this.elementId}" class="bottom-sheet">
                <div class="bottom-sheet-content-wrapper">
                    <div class="bottom-sheet-header">
                        <div id="nav-prev-button" class="bs-header-nav-btn hidden-via-js"><i class="fas fa-chevron-left"></i></div>
                        <div id="bs-header-center-part" class="bs-header-center">
                            <div class="header-text-stack">
                                <div class="bs-title-row">
                                    <h4 id="bs-header-title"></h4>
                                    <i id="bs-title-eye-icon" class="fas fa-eye bs-inline-eye"></i>
                                </div>
                                <div id="bs-header-location" class="bs-location-row"></div>
                            </div>
                        </div>
                        <div id="nav-next-button" class="bs-header-nav-btn hidden-via-js"><i class="fas fa-chevron-right"></i></div>
                    </div>
                    <div class="bottom-sheet-expanded">
                        <div class="bottom-sheet-content">
                            <div id="bs-photo-slot"></div>
                            <div id="${this.contentAreaId}"></div>
                        </div>
                    </div>
                </div>
                <div class="bottom-sheet-actions" id="${this.actionsAreaId}">
                    <div class="expanded-actions-container">
                        <div id="caretaker-checkbox-container" class="hidden">
                            <label><input type="checkbox" id="caretaker-checkbox" /><span id="caretaker-label">Patenschaft</span></label>
                        </div>
                        <div id="add-stolperstein-button" class="ctrl-button bottom-sheet-add-button hidden"><i class="fas fa-plus"></i></div>
                        <div id="edit-stolperstein-button" class="ctrl-button bottom-sheet-edit-button hidden"><i class="fas fa-pen"></i></div>
                    </div>
                    <div id="bottom-sheet-main-actions" class="bottom-sheet-main-actions hidden">
                        <button id="poi-clean-button" class="btn primary hidden"><span>glänzend</span>${cameraIcon}</button>
                        <button id="intro-button" class="btn info-btn hidden"></button>
                        <button id="poi-dirty-button" class="btn secondary hidden"><span>stumpf</span>${cameraIcon}</button>
                        <button id="cluster-clean-button" class="btn primary hidden">Alle glänzend</button>
                        <button id="cluster-dirty-button" class="btn secondary hidden">Alle stumpf</button>
                    </div>
                    <button id="fallback-button" class="btn hidden">Bitte die Adresse aufsuchen</button>
                </div>
            </div>
        </div>`;

        this.panelCSS = `
        .bottom-sheet-wrapper { position: fixed; bottom: 0; left: 0; width: 100%; transform: translateY(100%); transition: transform 0.3s ease-out; z-index: 1000; display: flex; flex-direction: column-reverse; align-items: center; touch-action: none; }
        .bottom-sheet-wrapper.open { transform: translateY(0); }
        .bottom-sheet-wrapper.hidden { display: none !important; }
        .bottom-sheet { width: 100%; min-height: 120px; max-height: 60vh; background-color: #fff; border-top-left-radius: 15px; border-top-right-radius: 15px; display: flex; flex-direction: column; overflow: hidden; position: relative; }
        .bottom-sheet-toggle-handle { position: absolute; left: 50%; top: -30px; transform: translateX(-50%); width: 50px; height: 30px; display: flex; justify-content: center; align-items: center; cursor: pointer; background-color: #fff; border-top-left-radius: 15px; border-top-right-radius: 15px; box-shadow: 0 -2px 5px rgba(0,0,0,0.1); }
        .bottom-sheet-header { display: flex; align-items: center; padding: 10px; background-color: #f9f9f9; min-height: 60px; border-bottom: 1px solid #ccc; 
        }
        .bs-header-center { flex-grow: 1; display: flex; align-items: center; cursor: pointer; overflow: hidden; }
        .header-text-stack { display: flex; flex-direction: column; width: 100%; }
        #bs-header-title { margin: 0; font-size: 1.1em; color: #333; }
        .bs-inline-eye { display: none; color: #007AFF; margin-left: 8px; }
        .bs-header-nav-btn { width: 40px; display: flex; justify-content: center; align-items: center; cursor: pointer; font-size: 1.3rem; }
        .bottom-sheet-expanded { display: none; flex-direction: column; flex-grow: 1; overflow: hidden; }
        .bottom-sheet.expanded .bottom-sheet-expanded { display: flex; }
        .bottom-sheet-content { padding: 0 20px 15px 20px; overflow-y: auto; max-height: 50vh; }
        
        /* UPDATE: Hintergrund auf Mittelgrau */
        .bottom-sheet-actions { 
            padding: 15px 10px; 
            border-top: 1px solid #ccc; 
            background: #f9f9f9; 
        }

        .expanded-actions-container { display: none; align-items: center; margin-bottom: 10px; }
        .bottom-sheet.expanded .expanded-actions-container { display: flex; }
        .ctrl-button { width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 5px; cursor: pointer; }
        .bottom-sheet-add-button { background: #28a745; color: #fff; }
        .bottom-sheet-edit-button { background: #ffc107; color: #222; }
        .bottom-sheet-main-actions { display: flex; gap: 10px; width: 100%; }
        .btn { flex-grow: 1; height: 44px; border-radius: 8px; border: none; font-weight: bold; font-size: 18px;cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; }
        .btn.primary { background: #28a745; color: #fff; }
        .btn.secondary { background: pink; color: #000; }
        .hidden { display: none !important; }
        .hidden-via-js { display: none !important; }
        
        #fallback-button { 
            background-color: #511ba6 !important; 
            color: white !important;
            width: 100% !important;
            display: block !important; 
            margin-top: 5px !important;
            padding: 15px !important; 
            border-radius: 10px !important;
            font-weight: bold !important;
            font-size: 1.1em !important;
            border: none;
            box-shadow: 0 4px 10px rgba(81, 27, 166, 0.3);
            cursor: pointer;
            box-sizing: border-box;
        }

        #intro-button.btn.info-btn {
            padding: 0 !important;
            background: none !important;
            border: none !important;
            box-shadow: none !important;
            width: auto !important;
            height: auto !important;
            display: flex !important;
            align-items: center;
            justify-content: center;
        }

        .sc-intro-btn-circle {
            width: 44px !important;
            background-color: #007bff;
            border-radius: 50% !important;
            display: flex !important;
            align-items: center;
            justify-content: center;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            flex-shrink: 0;
        }

        .poi-photo-flex-container { display: flex; align-items: center; justify-content: center; gap: 15px; width: 100%; }
        .photo-stack { position: relative; z-index: 1; }
        .photo-stack::before, .photo-stack::after { content: ""; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background: #fff; border: 1px solid #ccc; border-radius: 8px; z-index: -1; }
        .photo-stack::before { transform: translate(4px, 4px); }
        .photo-stack::after { transform: translate(8px, 8px); opacity: 0.5; }
        .poi-main-img { display: block; max-width: 100%; height: 180px; object-fit: contain; border-radius: 8px; border: 2px solid #fff; box-shadow: 0 2px 8px rgba(0,0,0,0.2); cursor: pointer; }
        .poi-photo-badge-side { background: rgba(0,0,0,0.8); color: white; padding: 6px 14px; border-radius: 20px; font-size: 1.4rem; font-weight: 800; cursor: pointer; }
        #bs-photo-slot.hidden { display: none !important; }
        @keyframes handle-bounce {
    0%, 100% { transform: translateX(-50%) translateY(0); }
    50% { transform: translateX(-50%) translateY(-15px); }
}

.bounce-effect {
    animation: handle-bounce 0.5s ease-out;
}
        `;
    }

    _injectHTML() {
        if (document.getElementById(this.wrapperId)) return;
        document.body.insertAdjacentHTML('beforeend', this.panelHTML);
    }

    _injectCSS() {
        if (document.getElementById('bs-gen-ui-styles')) return;
        const style = document.createElement('style');
        style.id = 'bs-gen-ui-styles';
        style.textContent = this.panelCSS;
        document.head.appendChild(style);
    }

    _cacheElements() {
        this.wrapper = document.getElementById(this.wrapperId);
        this.bottomSheet = document.getElementById(this.elementId);
        this.header = this.bottomSheet?.querySelector('.bottom-sheet-header');
        this.headerTitle = document.getElementById('bs-header-title');
        this.headerLocation = document.getElementById('bs-header-location');
        this.navPrevButton = document.getElementById('nav-prev-button');
        this.navNextButton = document.getElementById('nav-next-button');
        this.toggleHandle = this.wrapper?.querySelector('.bottom-sheet-toggle-handle');
        this.photoSlot = document.getElementById('bs-photo-slot'); // Neuer Cache
        this.contentArea = document.getElementById(this.contentAreaId);
        this.actionsArea = document.getElementById(this.actionsAreaId);
        this.addButton = document.getElementById('add-stolperstein-button');
        this.editButton = document.getElementById('edit-stolperstein-button');
        this.poiCleanButton = document.getElementById('poi-clean-button');
        this.introButton = document.getElementById('intro-button');
        this.poiDirtyButton = document.getElementById('poi-dirty-button');
        this.clusterCleanButton = document.getElementById('cluster-clean-button');
        this.clusterDirtyButton = document.getElementById('cluster-dirty-button');
        this.fallbackButton = document.getElementById('fallback-button');
        this.mainActionsContainer = document.getElementById('bottom-sheet-main-actions');
        this.caretakerCheckbox = document.getElementById('caretaker-checkbox');
    }

    _initBasicUiEvents() {
        if (this.toggleHandle) this.toggleHandle.onclick = (e) => { e.stopPropagation(); this.toggleExpansion(); };
    }

    _setupHeaderInteractions() {
        const header = this.header;
        if (!header) return;
        header.style.touchAction = 'none';
        let startX = 0, startY = 0, isDragging = false;
        header.addEventListener('pointerdown', (e) => {
            startX = e.clientX; startY = e.clientY;
            isDragging = true; header.setPointerCapture(e.pointerId);
        });
        header.addEventListener('pointerup', (e) => {
            if (!isDragging) return;
            isDragging = false;
            this._handleHeaderGesture({ startX, startY, endX: e.clientX, endY: e.clientY, target: e.target });
        });
    }
    /*
        _handleHeaderGesture({ startX, startY, endX, endY, target }) {
            const dx = endX - startX, dy = endY - startY;
            const absX = Math.abs(dx), absY = Math.abs(dy);
            if (absX < 10 && absY < 10) {
                const realTarget = target.closest('#bs-header-center-part');
                if (realTarget) this._headerClickCallback?.();
                return;
            }
            if (absX > absY && absX > 30) this._onHeaderSwipeHorizontal?.(dx > 0 ? 'PREVIOUS' : 'NEXT');
            else if (absY > 30) this.setSheetState(dy < 0);
        }*/
    _handleHeaderGesture({ startX, startY, endX, endY, target }) {
        const dx = endX - startX;
        const dy = endY - startY;
        const absX = Math.abs(dx);
        const absY = Math.abs(dy);
        const threshold = 20;

        // Elemente der Pfeile abfragen
        const prevVisible = !this.navPrevButton?.classList.contains('hidden-via-js');
        const nextVisible = !this.navNextButton?.classList.contains('hidden-via-js');

        // 1. Klicks (unverändert)
        if (absX < threshold && absY < threshold) {
            const realTarget = document.elementFromPoint(endX, endY) || target;

            if (realTarget.closest('#nav-prev-button')) return this._onHeaderSwipeHorizontal?.('PREVIOUS');
            if (realTarget.closest('#nav-next-button')) return this._onHeaderSwipeHorizontal?.('NEXT');
            if (realTarget.closest('#bs-header-center-part') || realTarget.id === 'bs-title-eye-icon') {
                return this._headerClickCallback?.();
            }
            return;
        }

        // 2. Swipes - nur wenn mindestens ein Pfeil sichtbar ist - nur dann ist es KEIN einzelstehender poi
        if (absX > absY) {
            if (absX >= threshold && (prevVisible || nextVisible)) {
                this._onHeaderSwipeHorizontal?.(dx > 0 ? 'PREVIOUS' : 'NEXT');
            }
        } else {
            if (absY >= threshold) this.setSheetState(dy < 0);
        }
    }
    isOpen() { return !!(this.wrapper && this.wrapper.classList.contains('open')); }

    // setBsHeaderText(h) { this.setBsTitle(h); this.setBsLocation(""); }

    async setSheetState(expand) {
        this.isExpanded = expand;
        this.bottomSheet?.classList.toggle('expanded', expand);
        this.wrapper?.classList.toggle('expanded', expand); // für bs resize bei clusterclick
        const icon = this.toggleHandle?.querySelector('i');
        if (icon) icon.style.transform = expand ? 'rotate(180deg)' : 'rotate(0deg)';
        // NEU: Icon-Position an die neue (größere oder kleinere) Höhe anpassen
    requestAnimationFrame(() => {
        this.moveSettingsIconWithBS();
    });
        if (this._onResizeCallback) this._onResizeCallback();
    }

    open() {
        this.wrapper?.classList.remove('hidden');
        // Handle hüpfen lassen
    if (this.toggleHandle) {
        this.toggleHandle.classList.add('bounce-effect');
        // Klasse nach Animation (500ms) wieder entfernen
        setTimeout(() => {
            this.toggleHandle.classList.remove('bounce-effect');
        }, 500);
    }

        // Kleiner Timeout für die CSS-Transition des Sheets
        setTimeout(() => {
            this.wrapper?.classList.add('open');

            // NEU: Icon nach oben schieben, sobald das Sheet ausfährt
            // Wir nutzen requestAnimationFrame, damit die Messung der Höhe präzise ist
            requestAnimationFrame(() => {
                this.moveSettingsIconWithBS();
            });
        }, 10);
    }

    close() {
        cancelSpeech();
        this.wrapper?.classList.remove('open');
        // NEU: Icon sofort wieder auf die Basis-Position (0) schieben
        this.moveSettingsIconWithBS(0);
        setTimeout(() => this.wrapper?.classList.add('hidden'), 300);
        this.closeCallbacks.forEach(cb => cb());
    }

    setPhoto(url, count = 0) {
        if (!this.photoSlot) return;
        this.photoSlot.innerHTML = '';
        if (!url || url.trim() === "") return;

        this.photoSlot.innerHTML = '';
        if (!url || url.trim() === "") {
            this.photoSlot.classList.add('hidden'); // Verstecken, wenn kein Bild
            return;
        }

        this.photoSlot.classList.remove('hidden'); // Anzeigen, wenn Bild da

        const isStack = count > 0;
        const html = `
            <div id="poi-photo-stack-wrapper" class="poi-photo-flex-container" style="margin-top: 15px; margin-bottom: 12px;">
                <div class="${isStack ? 'photo-stack' : ''}">
                    <img src="${url}" class="poi-main-img" alt="POI Foto">
                </div>
                ${isStack ? `<div class="poi-photo-badge-side">+${count}</div>` : ''}
            </div>`;
        this.photoSlot.innerHTML = html;
    }

    toggleEyeIcon(show) {
        const eyeIcon = document.getElementById('bs-title-eye-icon');
        if (eyeIcon) eyeIcon.style.display = show ? 'inline-block' : 'none';
    }

    setContent(h) {
        if (this.contentArea) this.contentArea.innerHTML = h;
    }

    setActions(options) {
        // 1. FOTO-REINIGUNG
        if (this.photoSlot) {
            if (options.showPoiPhotoStack === false) {
                this.photoSlot.innerHTML = '';
                this.photoSlot.classList.add('hidden');
            }
        }

        // 2. ALLE AKTIONEN RESETTEN
        const elements = [
            'caretaker-checkbox-container', 'add-stolperstein-button',
            'edit-stolperstein-button', 'bottom-sheet-main-actions',
            'poi-clean-button', 'poi-dirty-button',
            'cluster-clean-button', 'cluster-dirty-button',
            'fallback-button', 'intro-button'
        ];

        elements.forEach(id => {
            const el = document.getElementById(id);
            if (el) {
                el.classList.add('hidden');
                // Wir überschreiben das CSS-Important direkt auf dem Element
                el.style.setProperty('display', 'none', 'important');
            }
        });

        // 3. NUR ANZEIGEN, WAS AKTIV SEIN SOLL
        if (options.showCaretaker) {
            const el = document.getElementById('caretaker-checkbox-container');
            if (el) {
                el.classList.remove('hidden');
                el.style.setProperty('display', 'flex', 'important');
            }
            if (this.caretakerCheckbox) this.caretakerCheckbox.checked = !!options.isCaretaker;
        }

        if (options.showMainActionDiv || options.showFallbackButton) {
            this.mainActionsContainer?.classList.remove('hidden');
            this.mainActionsContainer.style.setProperty('display', 'flex', 'important');
        }

        // Buttons einzeln schalten
        const buttonMap = {
            showAddButton: this.addButton,
            showEditButton: this.editButton,
            showPoiCleanButton: this.poiCleanButton,
            showPoiDirtyButton: this.poiDirtyButton,
            showClusterCleanButton: this.clusterCleanButton,
            showClusterDirtyButton: this.clusterDirtyButton,
            showIntroButton: this.introButton
        };

        for (const [key, btn] of Object.entries(buttonMap)) {
            if (options[key] && btn) {
                btn.classList.remove('hidden');
                btn.style.setProperty('display', 'flex', 'important');
            }
        }

        // 4. DER ENTSCHEIDENDE FALLBACK-FIX
        if (options.showFallbackButton && this.fallbackButton) {
            this.fallbackButton.classList.remove('hidden');
            this.fallbackButton.style.setProperty('display', 'block', 'important');
        } else if (this.fallbackButton) {
            // Wenn nicht showFallbackButton, dann ZWINGEND ausblenden
            this.fallbackButton.classList.add('hidden');
            this.fallbackButton.style.setProperty('display', 'none', 'important');
        }
    }

    setNavButtonsState(p, n) {
        this.navPrevButton?.classList.toggle('hidden-via-js', !p);
        this.navNextButton?.classList.toggle('hidden-via-js', !n);
    }

    async toggleExpansion() { await this.setSheetState(!this.isExpanded); }
    onClose(cb) { this.closeCallbacks.push(cb); }
    onHeaderClick(cb) { this._headerClickCallback = cb; }
    onResize(cb) { this._onResizeCallback = cb; }
    onHeaderSwipeHorizontal(cb) { this._onHeaderSwipeHorizontal = cb; }

    // In BottomSheetUI.js

    /**
     * Synchronisiert Icon und Karte mit der aktuellen Sheet-Höhe.
     * @param {number} forceHeight - Optional: Erzwingt eine Höhe (z.B. 0 beim Schließen)
     */
    moveSettingsIconWithBS(forceHeight = null) {
        const bs = this.bottomSheet; // Das Sheet-Element der Klasse
        const icon = document.getElementById('settings-icon');

        // 1. Höhe bestimmen: Entweder der erzwungene Wert (0) oder die echte Höhe
        const currentHeight = (forceHeight !== null) ? forceHeight : (bs ? bs.offsetHeight : 0);

        // 2. Icon verschieben
        if (icon) {
            icon.style.transform = `translateY(-${currentHeight}px)`;
        }

        // 3. Karte nachführen (Resize-Logik aus map-gen-mgr.js)
        // Wir triggern das nur, wenn ein Marker aktiv ist
        if (this._clickedObject && typeof fitMapToTarget === 'function') {
            const gid = this._clickedObject.options?.gid;
            const coords = this._clickedObject.getLatLng();

            // Wir nutzen 'RESIZE', damit die Karte nur minimal nachrückt
            fitMapToTarget(gid, coords, null, 'RESIZE');
        }
    }
}