/**
 * p11DrawerNative.js
 * Specialized for native drawer behavior with local isolated swipe gestures.
 * Optimized using p11Js.Utility for swipe mathematics.
 */

export const DrawerNativeFunctions = {
    _activeDrawers: new Map(),
    _dotNetHelper: null,

    /**
     * Entspricht der alten registerEventStateService.
     * Wird von UiUtilities.RegisterEventStateService aufgerufen.
     */
    registerEventStateService: function (dotNetRef) {
        this._dotNetHelper = dotNetRef;
        window.p11Js.log("DrawerNative", "EventStateService-Ref registriert.");
    },

    /**
     * Initialisiert den Drawer: Setzt Z-Index, Scroll-Lock und Swipe-Gesten.
     */
    focusDrawerAndTrapNative: function (element, elementId, position, preventScroll, enableFocusTrap, dotNetCompRef) {
        if (!element) {
            console.error("[p11][DrawerNative] CRITICAL: Element is null for ID:", elementId);
            return;
        }

        // 1. Snapshot des aktuellen Zustands vor der Bearbeitung
        const computedStyle = window.getComputedStyle(element);
        window.p11Js.log("DrawerNative", `Initializing Drawer: ${elementId}`, {
            classes: element.className,
            currentDisplay: computedStyle.display,
            currentVisibility: computedStyle.visibility,
            currentZIndex: computedStyle.zIndex,
            dimensions: `${element.offsetWidth}x${element.offsetHeight}`
        });

        // 2. Z-Index Management (Modal-Ansatz)
        const stackDepth = this._activeDrawers.size;
        const newZIndex = window.p11Js.Utility.getNextZIndex(stackDepth, 'P11DrawerNative');
        element.style.zIndex = newZIndex;

        // Overlay finden und synchronisieren
        const overlay = element.parentElement ? element.parentElement.querySelector('.p11-drawer-overlay') : null;
        let outsideClickHandler = null;

        // Lokale Kopien für Closure-Sicherheit (für Overlay und Escape)
        const currentDotNetRef = dotNetCompRef;
        const globalHelper = this._dotNetHelper || window.p11Js.EventStateRef;

        if (overlay) {
            overlay.style.zIndex = (newZIndex - 1);

            outsideClickHandler = (e) => {
                if (e) {
                    e.preventDefault();
                    e.stopPropagation();
                }

                window.p11Js.log("DrawerNative", `Outside click captured for ${elementId}`);

                // 1. Versuch: Direkte Referenz
                if (currentDotNetRef) {
                    currentDotNetRef.invokeMethodAsync('HandleOutsideClick')
                        .catch(err => console.error("[p11] Direct call failed:", err));
                    return;
                }

                // 2. Versuch: Globaler Fallback
                if (globalHelper) {
                    globalHelper.invokeMethodAsync('HandleNativeBack', true, elementId)
                        .catch(err => console.error("[p11] Fallback call failed:", err));
                } else {
                    console.error("[p11][DrawerNative] CRITICAL: No DotNet reference available at all!");
                }
            };
            overlay.addEventListener('click', outsideClickHandler);

            window.p11Js.log("DrawerNative", `Z-Index Sync: Drawer=${newZIndex}, Overlay=${newZIndex - 1}`);
        }

        window.p11Js.log("DrawerNative", `Applied Z-Index: ${newZIndex} (Stack Depth: ${stackDepth})`);

        // 3. Scroll Lock
        if (preventScroll) {
            window.p11Js.Utility.requestScrollLock(elementId);
        }

        // 4. Escape-Key Handler (Direkte Kommunikation mit der Komponente)
        const escapeHandler = (e) => {
            if (e.key === 'Escape') {
                window.p11Js.log("DrawerNative", `Escape key detected for ${elementId}`);

                if (currentDotNetRef) {
                    currentDotNetRef.invokeMethodAsync('HandleEscapeKey')
                        .catch(err => console.error("[p11] Escape direct call failed:", err));
                } else if (globalHelper) {
                    globalHelper.invokeMethodAsync('HandleNativeBack', true, elementId);
                }
            }
        };
        element.addEventListener('keydown', escapeHandler);

        // 5. State speichern (inkl. dotNetCompRef für Swipe/Cleanup)
        this._activeDrawers.set(elementId, {
            element,
            overlay,
            outsideClickHandler,
            escapeHandler,
            dotNetCompRef: currentDotNetRef,
            position,
            preventScroll,
            cleanup: null
        });

        this._setupSwipe(element, elementId, position);

        // 6. Check ob die "--open" Klasse vorhanden ist
        if (!element.classList.contains('p11-drawer--open')) {
            console.warn(`[p11][DrawerNative] WARNING: Element ${elementId} does NOT have 'p11-drawer--open' class yet! Blazor sync issue?`);
        }

        if (enableFocusTrap) {
            setTimeout(() => {
                if (element && document.contains(element)) {
                    element.focus();
                    window.p11Js.log("DrawerNative", "Focus trap executed.");
                }
            }, 100);
        }
    },

    /**
     * Interne Methode für die Swipe-Logik.
     * Inklusive synchroner Steuerung der Overlay-Opacity (Modal-Ansatz).
     */
    //_setupSwipe: function (element, elementId, position) {
    //    let startX = 0, startY = 0, isMoving = false;
    //    let lastX = 0, lastY = 0; // Merkt sich die letzte Position für das Ende

    //    // Dynamischer Schwellenwert mit Sicherheits-Deckel (max 100px)
    //    const getThreshold = () => {
    //        const size = (position === 'top' || position === 'bottom') ? element.offsetHeight : element.offsetWidth;
    //        let t = size * 0.2;
    //        if (t > 100) t = 100;
    //        if (t < 60) t = 60;
    //        return t;
    //    };

    //    const overlay = element.parentElement ? element.parentElement.querySelector('.p11-drawer-overlay') : null;
    //    const drawerState = this._activeDrawers.get(elementId);

    //    const handleStart = (e) => {
    //        if (!e.touches || e.touches.length !== 1) return;

    //        startX = e.touches[0].clientX;
    //        startY = e.touches[0].clientY;
    //        lastX = startX;
    //        lastY = startY;
    //        isMoving = true;

    //        // --- DETAILLIERTES ELEMENT LOGGING ---
    //        const targetEl = e.target;
    //        window.p11Js.log("DrawerNative",
    //            `Swipe START auf Element: <${targetEl.tagName.toLowerCase()}> ` +
    //            `ID: "${targetEl.id}" Klassen: "${targetEl.className}" ` +
    //            `| Ursprung: X:${startX.toFixed(0)} Y:${startY.toFixed(0)} | Pos: ${position}`);

    //        // Transitionen hart ausschalten
    //        element.style.setProperty('transition', 'none', 'important');
    //        if (overlay) overlay.style.setProperty('transition', 'none', 'important');

    //        // Verhindert Scrollen während des Swipes
    //        //element.style.touchAction = 'none';
    //    };

    //    const handleMove = (e) => {
    //        if (!isMoving) return;

    //        const touch = e.touches[0];
    //        lastX = touch.clientX;
    //        lastY = touch.clientY;

    //        const diffX = lastX - startX;
    //        const diffY = lastY - startY;

    //        let moveAmount = 0;
    //        let transformStr = "";

    //        // Bewegung berechnen
    //        if (position === 'right' && diffX > 0) {
    //            moveAmount = diffX;
    //            transformStr = `translateX(${moveAmount}px)`;
    //        }
    //        else if (position === 'left' && diffX < 0) {
    //            moveAmount = Math.abs(diffX);
    //            transformStr = `translateX(${diffX}px)`;
    //        }
    //        else if (position === 'bottom' && diffY > 0) {
    //            moveAmount = diffY;
    //            transformStr = `translateY(${moveAmount}px)`;
    //        }
    //        else if (position === 'top' && diffY < 0) {
    //            moveAmount = Math.abs(diffY);
    //            transformStr = `translateY(${diffY}px)`;
    //        }

    //        if (moveAmount > 0) {
    //            element.style.setProperty('transform', transformStr, 'important');
    //            if (overlay) {
    //                const totalSize = (position === 'top' || position === 'bottom') ? element.offsetHeight : element.offsetWidth;
    //                const progress = Math.min(1, moveAmount / totalSize);
    //                overlay.style.setProperty('opacity', (1 - (progress * 0.8)).toString(), 'important');
    //            }
    //        }
    //    };

    //    const handleEnd = (e) => {
    //        if (!isMoving) return;
    //        isMoving = false;

    //        // Wir nutzen lastX/lastY, da e.touches beim Ende leer sein können
    //        const finalDiffX = lastX - startX;
    //        const finalDiffY = lastY - startY;
    //        const threshold = getThreshold();
    //        let shouldClose = false;

    //        const currentDiff = (position === 'left' || position === 'right') ? finalDiffX : finalDiffY;
    //        window.p11Js.log("DrawerNative", `Swipe End. Delta: ${currentDiff.toFixed(0)} (Threshold: ${threshold.toFixed(0)})`);

    //        // Schwellenwert-Check
    //        switch (position) {
    //            case 'bottom': if (finalDiffY > threshold) shouldClose = true; break;
    //            case 'top': if (finalDiffY < -threshold) shouldClose = true; break;
    //            case 'left': if (finalDiffX < -threshold) shouldClose = true; break;
    //            case 'right': if (finalDiffX > threshold) shouldClose = true; break;
    //        }

    //        element.style.removeProperty('transition');
    //        if (overlay) overlay.style.removeProperty('transition');

    //        if (shouldClose) {
    //            window.p11Js.log("DrawerNative", "Threshold reached: Closing...");

    //            if (drawerState && drawerState.dotNetCompRef) {
    //                drawerState.dotNetCompRef.invokeMethodAsync('HandleSwipeClose')
    //                    .catch(err => console.error("[p11] Swipe callback failed", err));
    //            } else {
    //                const helper = this._dotNetHelper || window.p11Js.EventStateRef;
    //                if (helper) {
    //                    helper.invokeMethodAsync('HandleNativeBack', true, elementId);
    //                }
    //            }
    //        } else {
    //            window.p11Js.log("DrawerNative", "Threshold not reached: Snapping back.");
    //            element.style.setProperty('transform', '', 'important');
    //            if (overlay) overlay.style.setProperty('opacity', '1', 'important');
    //        }

    //        setTimeout(() => { if (element) element.style.touchAction = ''; }, 300);
    //    };

    //    element.addEventListener('touchstart', handleStart, { passive: true });
    //    element.addEventListener('touchmove', handleMove, { passive: false });
    //    element.addEventListener('touchend', handleEnd, { passive: true });

    //    if (drawerState) {
    //        drawerState.cleanup = () => {
    //            element.removeEventListener('touchstart', handleStart);
    //            element.removeEventListener('touchmove', handleMove);
    //            element.removeEventListener('touchend', handleEnd);
    //            element.style.removeProperty('transform');
    //            element.style.removeProperty('touch-action');
    //            if (overlay) {
    //                overlay.style.removeProperty('opacity');
    //                overlay.style.removeProperty('transition');
    //            }
    //            window.p11Js.log("DrawerNative", `Swipe resources released for ${elementId}`);
    //        };
    //    }
    //},
    /**
         * Interne Methode für die Swipe-Logik.
         * Inklusive synchroner Steuerung der Overlay-Opacity (Modal-Ansatz).
         */
    _setupSwipe: function (element, elementId, position) {
        let startX = 0, startY = 0, isMoving = false;
        let lastX = 0, lastY = 0;

        const getThreshold = () => {
            const size = (position === 'top' || position === 'bottom') ? element.offsetHeight : element.offsetWidth;
            let t = size * 0.15;
            if (t > 80) t = 80;
            if (t < 40) t = 40;
            return t;
        };

        const edgeSize = 120;
        const overlay = element.parentElement ? element.parentElement.querySelector('.p11-drawer-overlay') : null;
        const drawerState = this._activeDrawers.get(elementId);

        const handleStart = (e) => {
            if (!e.touches || e.touches.length !== 1) return;

            const touch = e.touches[0];
            const rect = element.getBoundingClientRect();

            // 1. Relative Position berechnen
            const relX = touch.clientX - rect.left;
            const relY = touch.clientY - rect.top;

            // 2. Edge-Check Logik
            let isAtEdge = false;
            if (position === 'top' && relY <= edgeSize) isAtEdge = true;
            else if (position === 'bottom' && (rect.height - relY) <= edgeSize) isAtEdge = true;
            else if (position === 'left' && relX <= edgeSize) isAtEdge = true;
            else if (position === 'right' && (rect.width - relX) <= edgeSize) isAtEdge = true;

            // --- LOGGING ---
            const targetEl = e.target;
            window.p11Js.log("DrawerNative",
                `Touch START: Edge=${isAtEdge} | Pos=${position} | relY=${relY.toFixed(0)} | <${targetEl.tagName.toLowerCase()}>`);

            if (!isAtEdge) {
                startX = 0;
                startY = 0;
                return;
            }

            // 3. Werte setzen wenn am Rand
            startX = touch.clientX;
            startY = touch.clientY;
            lastX = startX;
            lastY = startY;
            isMoving = false;

            element.style.setProperty('transition', 'none', 'important');
            if (overlay) overlay.style.setProperty('transition', 'none', 'important');
        };

        const handleMove = (e) => {
            // WICHTIG: Wenn startX 0 ist (kein Edge-Match oder abgebrochen), sofort raus
            if (startX === 0) return;

            const touch = e.touches[0];
            const currentX = touch.clientX;
            const currentY = touch.clientY;

            const diffX = currentX - startX;
            const diffY = currentY - startY;
            const absX = Math.abs(diffX);
            const absY = Math.abs(diffY);

            if (!isMoving) {
                // Erst ab 10px Bewegung entscheiden wir: Swipe oder Scroll?
                if (absX > 5 || absY > 5) {
                    let userWantsToSwipe = false;
                    if (position === 'left' || position === 'right') {
                        if (absX > absY * 1.5) userWantsToSwipe = true;
                    } else {
                        if (absY > absX * 1.5) userWantsToSwipe = true;
                    }

                    if (userWantsToSwipe) {
                        isMoving = true;
                        element.style.touchAction = 'none'; // Browser-Scrollen sperren
                        window.p11Js.log("DrawerNative", "Swipe erkannt: Scrollen blockiert.");
                    } else {
                        window.p11Js.log("DrawerNative", "Scrollen erkannt: Swipe deaktiviert.");
                        startX = 0;
                        return;
                    }
                } else {
                    return;
                }
            }

            // Wenn isMoving aktiv ist, verhindern wir das Standardverhalten
            if (e.cancelable) e.preventDefault();

            lastX = currentX;
            lastY = currentY;

            let moveAmount = 0;
            let transformStr = "";

            // Richtungsspezifische Bewegung (nur in "Schließ-Richtung" erlauben)
            if (position === 'right' && diffX > 0) {
                moveAmount = diffX;
                transformStr = `translateX(${moveAmount}px)`;
            } else if (position === 'left' && diffX < 0) {
                moveAmount = Math.abs(diffX);
                transformStr = `translateX(${diffX}px)`;
            } else if (position === 'bottom' && diffY > 0) {
                moveAmount = diffY;
                transformStr = `translateY(${moveAmount}px)`;
            } else if (position === 'top' && diffY < 0) {
                moveAmount = Math.abs(diffY);
                transformStr = `translateY(${diffY}px)`;
            }

            if (moveAmount > 0) {
                element.style.setProperty('transform', transformStr, 'important');
                if (overlay) {
                    const totalSize = (position === 'top' || position === 'bottom') ? element.offsetHeight : element.offsetWidth;
                    const progress = Math.min(1, moveAmount / totalSize);
                    // Overlay wird synchron mit der Bewegung ausgeblendet
                    overlay.style.setProperty('opacity', (1 - (progress * 0.8)).toString(), 'important');
                }
            }
        };

        const handleEnd = (e) => {
            // Wenn der Start schon ungültig war, ignorieren
            if (startX === 0) return;

            const finalDiffX = lastX - startX;
            const finalDiffY = lastY - startY;
            const threshold = getThreshold();
            let shouldClose = false;

            if (isMoving) {
                // Schwellenwert prüfen
                switch (position) {
                    case 'bottom': if (finalDiffY > threshold) shouldClose = true; break;
                    case 'top': if (finalDiffY < -threshold) shouldClose = true; break;
                    case 'left': if (finalDiffX < -threshold) shouldClose = true; break;
                    case 'right': if (finalDiffX > threshold) shouldClose = true; break;
                }

                element.style.removeProperty('transition');
                if (overlay) overlay.style.removeProperty('transition');

                if (shouldClose) {
                    window.p11Js.log("DrawerNative", "Threshold erreicht: Schließen...");
                    if (drawerState && drawerState.dotNetCompRef) {
                        drawerState.dotNetCompRef.invokeMethodAsync('HandleSwipeClose')
                            .catch(err => console.error("[p11] Swipe callback failed", err));
                    } else {
                        const helper = this._dotNetHelper || window.p11Js.EventStateRef;
                        if (helper) {
                            helper.invokeMethodAsync('HandleNativeBack', true, elementId);
                        }
                    }
                } else {
                    window.p11Js.log("DrawerNative", "Threshold nicht erreicht: Snap-back.");
                    element.style.setProperty('transform', '', 'important');
                    if (overlay) overlay.style.setProperty('opacity', '1', 'important');
                }
            }

            // Cleanup für den nächsten Touch-Zyklus
            isMoving = false;
            startX = 0;
            startY = 0;

            // Touch-Action verzögert zurücksetzen, um "Ghost-Clicks" oder sofortiges Scrollen zu vermeiden
            setTimeout(() => {
                if (element && this._activeDrawers.has(elementId)) {
                    element.style.touchAction = (position === 'bottom' || position === 'top') ? 'pan-x' : 'pan-y';
                }
            }, 300);
        };

        element.addEventListener('touchstart', handleStart, { passive: true });
        element.addEventListener('touchmove', handleMove, { passive: false });
        element.addEventListener('touchend', handleEnd, { passive: true });

        if (drawerState) {
            drawerState.cleanup = () => {
                element.removeEventListener('touchstart', handleStart);
                element.removeEventListener('touchmove', handleMove);
                element.removeEventListener('touchend', handleEnd);
                element.style.removeProperty('transform');
                element.style.removeProperty('touch-action');
                if (overlay) {
                    overlay.style.removeProperty('opacity');
                    overlay.style.removeProperty('transition');
                }
                window.p11Js.log("DrawerNative", `Swipe resources released for ${elementId}`);
            };
        }
    },

    /**
     * Gibt Drawer-Ressourcen frei (Swipe-Events, Scroll-Lock).
     */
    releaseDrawerNative: function (elementId) {
        const state = this._activeDrawers.get(elementId);
        if (!state) {
            window.p11Js.log("DrawerNative", `Release skipped: No state found for ${elementId}`);
            return;
        }

        // 1. Events entfernen (Swipe-Cleanup aus _setupSwipe)
        // Dies entfernt touchstart, touchmove und touchend
        if (state.cleanup) {
            state.cleanup();
        }

        // 2. Zusätzliche Handler entfernen (Click auf Overlay & Escape Taste)
        // Wichtig, damit bei Wiederverwendung des DOM-Elements keine doppelten Listener entstehen
        if (state.overlay && state.outsideClickHandler) {
            state.overlay.removeEventListener('click', state.outsideClickHandler);
            window.p11Js.log("DrawerNative", `Overlay Click-Listener removed for ${elementId}`);
        }

        if (state.element && state.escapeHandler) {
            state.element.removeEventListener('keydown', state.escapeHandler);
            window.p11Js.log("DrawerNative", `Escape-Listener removed for ${elementId}`);
        }

        // 3. Scroll Lock aufheben
        if (state.preventScroll) {
            window.p11Js.Utility.releaseScrollLock(elementId);
        }

        // 4. DotNet-Referenz aufräumen (Optionaler Schutz)
        if (state.dotNetCompRef) {
            state.dotNetCompRef = null;
        }

        // 5. Aus Map löschen
        this._activeDrawers.delete(elementId);

        window.p11Js.log("DrawerNative", `Released Drawer: ${elementId}`);
    }
};