/**
 * p11ModalNative.js
 * Specialized bridge for native-like modal behavior and swipe-to-close gestures.
 * Optimized with advanced safety checks (scroll detection, interactive elements).
 * Includes automatic Z-Index management for stacked modals and global Escape-key support.
 * Part of the p11 UI Library.
 */

export const ModalNativeFunctions = {
    _activeModals: [], // Internal stack for Z-Index management
    //_baseZIndex: 1050, is now managed via p11utility.js and IEventStateService
    _globalHandlersInstalled: false,

    /**
     * Focuses the modal, manages Z-Index and adds it to the internal stack.
     * Now operates WITHOUT overwriting the global DotNet helper for swipes.
     */
    focusModalAndTrapModalNative: function (element, restoreFocusId, preventScroll, enableFocusTrap, closeOnOutsideClick) {
        const sb = this._logic;
        sb._log("FocusModalAndTrap initiated", { restoreFocusId, preventScroll });

        if (!element) return;

        //// --- Z-INDEX MANAGEMENT ---
        //// Calculate new Z-Index: each modal gets +2 (one for backdrop, one for content)
        //const newZIndex = this._baseZIndex + (this._activeModals.length * 2);
        //element.style.zIndex = newZIndex;
        // --- Z-INDEX MANAGEMENT ---
        // Calculate new Z-Index via central Utility (uses configured layer offsets)
        const newZIndex = p11Js.Utility.getNextZIndex(this._activeModals.length, 'modal');
        element.style.zIndex = newZIndex;

        // Find the corresponding backdrop (Bootstrap default) and place it behind the modal
        const backdrop = document.querySelector('.modal-backdrop.show:not([style*="z-index"])')
            || document.querySelector('.modal-backdrop.show');

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

        // Add to internal stack to track layers (we no longer store a dotNet reference here)
        this._activeModals.push({
            id: element.id,
            el: element,
            backdrop: backdrop,
            restoreId: restoreFocusId
        });

        // Ensure Global Listeners (like Escape key or global Utility clicks) are installed
        this._installGlobalListeners();

        sb._log("Z-Index assigned", { zIndex: newZIndex, stackDepth: this._activeModals.length });
        // --------------------------

        // 1. Set focus to the modal element for accessibility
        setTimeout(() => {
            if (element) {
                element.focus();
            }
        }, 50);

        //// 2. Body Scroll Lock
        //if (preventScroll) {
        //    document.body.style.overflow = 'hidden';
        //    document.body.style.touchAction = 'none';
        //    document.body.classList.add('modal-open');
        //}
        // 2. Body Scroll Lock (Managed by central Utility counter)
        if (preventScroll) {
            // QM-Sicherheit: Falls Blazor keine ID ans Element gebunden hat, 
            // nehmen wir die ID aus unserem internen Stack (die wir gerade mit .push gespeichert haben)
            const currentId = element.id || (this._activeModals.length > 0 ? this._activeModals[this._activeModals.length - 1].id : "unknown-modal");

            sb._log("Requesting Scroll Lock for ID:", currentId);

            // Jetzt rufen wir die Utility auf
            p11Js.Utility.requestScrollLock(currentId);

            // ZUSÄTZLICHER SICHERHEITS-CHECK (Falls die Utility nicht reagiert)
            if (document.body.style.overflow !== 'hidden') {
                console.error("[p11][ModalNative] CRITICAL: Utility.requestScrollLock failed to lock body! Forcing lock now.");
                document.body.style.setProperty('overflow', 'hidden', 'important');
                document.body.classList.add('modal-open');
            }
        }

        // 3. Enable the swipe gesture logic 
        // (Uses the existing global _dotNetHelper which is the EventStateService)
        this.enable(true);
    },

    /**
     * Releases modal resources, cleans up Z-Index stack and restores focus.
     * Required by UiUtilities.ReleaseModalNative.
     */
    releaseModalNative: function (element, restoreFocusId, preventScroll) {
        this._logic._log("ReleaseModalNative initiated", { restoreFocusId });

        // 1. Element aus dem internen Stack entfernen (mit Null-Check für das Element)
        // Wenn das Element bereits durch Blazor (DOM-Entfernung) weg ist, 
        // machen wir nur mit dem Rest-Cleanup weiter.
        if (element) {
            this._activeModals = this._activeModals.filter(m => m.el !== element);
        } else {
            this._logic._log("ReleaseModalNative: Element reference lost (likely removed by Blazor), performing general cleanup.");
        }

        // 2. Body-Scroll-Lock Management
        // We always call release; the Utility decides if other components still need the lock.
        p11Js.Utility.releaseScrollLock(element ? element.id : null);

        if (this._activeModals.length > 0) {
            // Fokus auf das nun oberste Modal im Stack setzen
            const topModal = this._activeModals[this._activeModals.length - 1];

            //// Fokus auf das nun oberste Modal im Stack setzen
            //const topModal = this._activeModals[this._activeModals.length - 1];
            if (topModal && topModal.el) {
                setTimeout(() => {
                    // Nochmal prüfen, ob das Element noch existiert, bevor der Fokus gesetzt wird
                    if (topModal && topModal.el) {
                        try {
                            topModal.el.focus();
                        } catch (e) {
                            this._logic._log("Focus restore failed", e);
                        }
                    }
                }, 10);
            }
        }

        // 3. Fokus-Wiederherstellung (für Barrierefreiheit - falls eine ID mitgegeben wurde)
        if (restoreFocusId) {
            const el = document.getElementById(restoreFocusId);
            if (el) {
                try {
                    el.focus();
                } catch (e) {
                    // Stiller Fehler, falls Element nicht fokussierbar
                }
            }
        }

        // 4. Globaler Cleanup (Overlay entfernen, Swipe-Status zurücksetzen)
        // Das stellt sicher, dass auch nach einem Swipe-Ende alle JS-internen Zustände sauber sind.
        this.forceReset();
    },

    /**
     * Installs global event listeners only once.
     */
    _installGlobalListeners: function () {
        if (this._globalHandlersInstalled) return;

        // Global Escape Key Support: Always closes the TOPMOST modal
        document.addEventListener('keydown', (e) => {
            if (e.key === 'Escape' && this._activeModals.length > 0) {
                const topModal = this._activeModals[this._activeModals.length - 1];
                this._logic._log("Global Escape detected, invoking HandleEscapeKey");
                if (topModal.dotNet) {
                    topModal.dotNet.invokeMethodAsync("HandleEscapeKey");
                }
            }
        });

        this._globalHandlersInstalled = true;
    },

    enable: function (enable) {
        this._logic.enable(enable);
    },

    registerHelper: function (dotNetHelper) {
        this._logic._dotNetHelper = dotNetHelper;
        this._logic._log("DotNetHelper registered via p11Js.Modal");
    },

    forceReset: function () {
        this._logic.forceReset();
    },

    /**
     * Updates the swipe configuration values from C#.
     * Used by IEventStateService.SyncSwipeConfigAsync to ensure AOT-safe data transfer.
     */
    updateConfiguration: function (config) {
        if (!config) return;
        const sb = this._logic;

        // Map C# Model to JS Logic
        sb.edgeSize = config.edgeSize ?? sb.edgeSize;
        sb.threshold = config.threshold ?? sb.threshold;
        sb.maxVerticalDelta = config.maxVerticalDelta ?? sb.maxVerticalDelta;
        sb.duration = config.duration ?? sb.duration;
        sb.maxSwipeDistance = config.maxSwipeDistance ?? sb.maxSwipeDistance;

        // Store platform specific overrides to be applied during _configureForPlatform
        sb._androidConfig = { edge: config.androidEdgeSize, threshold: config.androidThreshold };
        sb._iosConfig = { edge: config.iosEdgeSize, threshold: config.iosThreshold };

        // Re-run configuration to apply changes immediately
        sb._configureForPlatform();

        sb._log("Configuration updated from C#", config);
    },

    /**
     * Required by UiUtilities.RegisterEventStateService.
     */
    registerEventStateService: function (dotNetRef) {
        this._logic.setDotNetHelper(dotNetRef);
    },

    /**
     * Required by UiUtilities.SetSwipeEnabled.
     */
    setSwipeEnabled: function (enabled) {
        this._logic.enable(enabled);
    },

    // Internal Swipe Logic
    _logic: {
        isEnabled: false,
        _dotNetHelper: null,
        startX: 0,
        startY: 0,
        currentX: 0,
        isSwiping: false,
        startTime: 0,
        currentTargetEl: null,
        currentBackdropEl: null, // NEW: Track the real backdrop
        edgeSize: 25,
        threshold: 80,
        maxVerticalDelta: 60,
        duration: 300,
        maxSwipeDistance: 0.7,
        _handlers: null,

        /**
         * Uses the central p11Js logger if available.
         */
        _log: function (message, data) {
            if (window.p11Js && typeof window.p11Js.log === 'function') {
                window.p11Js.log("ModalNative", message, data);
            } else {
                console.log(`[p11ModalNative] ${message}`, data || "");
            }
        },

        enable: function (enable) {
            this.isEnabled = !!enable;
            this._configureForPlatform();
            this._log(`Swipe state: ${this.isEnabled ? "ENABLED" : "DISABLED"}`);
        },

        _configureForPlatform: function () {
            const platform = window.Capacitor?.getPlatform ? window.Capacitor.getPlatform() : 'web';

            if (platform === 'android') {
                this.edgeSize = this._androidConfig?.edge ?? 0;
                this.threshold = this._androidConfig?.threshold ?? 9999;
            } else if (platform === 'ios') {
                this.edgeSize = this._iosConfig?.edge ?? 25;
                this.threshold = this._iosConfig?.threshold ?? 80;
            } else {
                // Web / Fallback stays as defined in updateConfiguration or defaults
                if (!this._iosConfig) { // Only set defaults if no config was synced yet
                    this.edgeSize = 15;
                    this.threshold = 120;
                }
            }
        },

        onStart: function (e) {
            // If explicitly disabled, we don't start.
            // However, for the App-Swipe (index.html) we usually want it always enabled.
            //if (!this.isEnabled && ModalNativeFunctions._activeModals.length > 0) return false;

            if (!this.isEnabled) return false;

            if (!e.touches || e.touches.length !== 1) return false;

            const touch = e.touches[0];

            // 1. Validation: Edge Zone
            if (touch.clientX > this.edgeSize) return false;

            // 2. Validation: Prevent swiping on interactive elements
            const target = e.target;
            const interactiveSelector = 'button, a, input, textarea, select, .no-swipe';
            if (target.closest(interactiveSelector)) {
                this._log("Aborted: Interactive element detected");
                return false;
            }

            // 3. Validation: Scroll Position
            const scrollContainer = target.closest('main, .modal-body, .scrollable, [data-scrollable]');
            if (scrollContainer && scrollContainer.scrollTop > 0) {
                this._log("Aborted: Container is scrolled");
                return false;
            }

            this.startX = touch.clientX;
            this.startY = touch.clientY;
            this.isSwiping = false; // Will be set in onMove
            this.startTime = Date.now();
            this.currentX = 0;

            this._log("Swipe sequence initialized");
            return true;
        },

        onMove: function (e) {
            // 1. Basis-Validierung (Wie in index.html)
            if (!this.isEnabled || this.startX === 0) return;
            if (!e.touches || e.touches.length !== 1) return;

            const touch = e.touches[0];
            const dx = touch.clientX - this.startX;
            const dy = Math.abs(touch.clientY - this.startY);

            // Initialisierungs-Phase: Wird einmalig getriggert, wenn Threshold erreicht
            if (!this.isSwiping) {
                // Horizontaler Move muss dominieren (min. 10px), vertikaler Drift begrenzt
                if (dx < 10 || dy > this.maxVerticalDelta) return;

                this.isSwiping = true;

                // Erkennung: Oberstes Modal aus der internen Liste oder Haupt-App
                const topModal = ModalNativeFunctions._activeModals[ModalNativeFunctions._activeModals.length - 1];
                const isModalOpen = !!topModal;

                if (isModalOpen) {
                    // Wir nehmen das ganze Modal-Element (topModal.el) für maximale CSS-Stabilität
                    this.currentTargetEl = topModal.el;
                    this.currentBackdropEl = topModal.backdrop;
                } else {
                    // Logik für Page-Swipe (Main App)
                    this.currentTargetEl = document.getElementById('app');
                    this.currentBackdropEl = null;
                }

                if (this.currentTargetEl) {
                    // Transitionen während des Draggens deaktivieren für sofortiges Feedback
                    this.currentTargetEl.style.transition = 'none';
                    this.currentTargetEl.style.willChange = 'transform';
                }

                // Erzeugt das künstliche Overlay hinter dem Element
                this._createOverlay(isModalOpen);
                this._log("Swipe sequence started", { modalMode: isModalOpen, target: this.currentTargetEl?.id || 'modal' });
            }

            // Standard-Browserverhalten (wie Pull-to-Refresh) verhindern
            if (e.cancelable) e.preventDefault();

            // Distanz berechnen und begrenzen (Clamp)
            const maxDistance = window.innerWidth * this.maxSwipeDistance;
            this.currentX = Math.max(0, Math.min(dx, maxDistance));

            // Transformation auf das Ziel-Element anwenden
            if (this.currentTargetEl) {
                this.currentTargetEl.style.transform = `translateX(${this.currentX}px)`;
            }

            // Visuelles Feedback: Künstliches Overlay abdunkeln
            const overlay = document.getElementById('p11-swipe-overlay');
            if (overlay) {
                // Overlay wird maximal 0.5 deckend (Schwarz)
                const opacity = Math.min(0.5, this.currentX / 300);
                overlay.style.opacity = opacity.toString();
            }

            // Visuelles Feedback: Echten Modal-Hintergrund ausfaden
            if (this.currentBackdropEl) {
                // Startet bei 0.5 (Bootstrap Standard) und geht gegen 0
                const backdropOpacity = Math.max(0, 0.5 - (this.currentX / 600));
                this.currentBackdropEl.style.opacity = backdropOpacity.toString();
            }
        },
                
        onEnd: function () {
            if (!this.isSwiping) {
                this._reset();
                return;
            }

            const durationSinceStart = Date.now() - this.startTime;
            const velocity = this.currentX / durationSinceStart;

            this._log("Swipe ended", { dist: this.currentX, vel: velocity });

            const shouldAccept = this.currentX > this.threshold || velocity > 0.3;

            if (shouldAccept) {
                // --- 1. ERFOLGREICHER SWIPE (Fly-out) ---
                if (this.currentTargetEl) {
                    // Wir nutzen die duration (jetzt 300ms) und das saubere Bezier-Timing
                    this.currentTargetEl.style.transition = `transform ${this.duration}ms cubic-bezier(0.25, 0.46, 0.45, 0.94)`;
                    this.currentTargetEl.style.transform = 'translateX(100%)';
                }

                if (this.currentBackdropEl) {
                    this.currentBackdropEl.style.transition = `opacity ${this.duration}ms ease-out`;
                    this.currentBackdropEl.style.opacity = '0';
                }

                const overlay = document.getElementById('p11-swipe-overlay');
                if (overlay) {
                    overlay.style.transition = `opacity ${this.duration}ms ease-out`;
                    overlay.style.opacity = '0';
                }

                // WICHTIG: Nicht sofort triggern! 
                // Wir geben der Animation 50-100ms Vorsprung, bevor Blazor das Element löscht.
                setTimeout(() => {
                    this._triggerCSharpBack();
                    this._reset();
                }, 80);

            } else {
                // --- 2. ABGEBROCHENER SWIPE (Snap-back) ---
                if (this.currentTargetEl) {
                    this.currentTargetEl.style.transition = `transform ${this.duration}ms ease-out`;
                    this.currentTargetEl.style.transform = 'translateX(0)';
                }

                if (this.currentBackdropEl) {
                    this.currentBackdropEl.style.transition = `opacity ${this.duration}ms ease-out`;
                    this.currentBackdropEl.style.opacity = '0.5';
                }

                const overlay = document.getElementById('p11-swipe-overlay');
                if (overlay) {
                    overlay.style.transition = `opacity ${this.duration}ms ease-out`;
                    overlay.style.opacity = '0';
                }

                setTimeout(() => {
                    this._cleanupWithFallback(false);
                    this._reset();
                }, this.duration + 20);
            }
        },

        onCancel: function () {
            this._log("Swipe cancelled by system (e.g. interruption)");

            // Wir nutzen die Snap-Back Animation (translateX 0)
            if (this.currentTargetEl) {
                this.currentTargetEl.style.transition = `transform ${this.duration}ms ease-out`;
                this.currentTargetEl.style.transform = 'translateX(0)';
            }

            if (this.currentBackdropEl) {
                this.currentBackdropEl.style.transition = `opacity ${this.duration}ms ease-out`;
                this.currentBackdropEl.style.opacity = '0.5';
            }

            const overlay = document.getElementById('p11-swipe-overlay');
            if (overlay) {
                overlay.style.transition = `opacity ${this.duration}ms ease-out`;
                overlay.style.opacity = '0';
            }

            // Nach der Animation alles aufräumen
            setTimeout(() => {
                this._cleanupWithFallback(false);
                this._reset();
            }, this.duration);
        },

        /**
         * Notifies the C# EventStateService that a successful swipe gesture occurred.
         * If no DotNet-Helper is registered (e.g., in standard Web/WASM mode), 
         * the call is gracefully ignored to prevent console noise.
         */
        _triggerCSharpBack: function () {
            try {
                // 1. Wurzel finden
                const root = this._logic || (window.p11Js && window.p11Js.ModalNative);
                if (!root) {
                    console.error("[p11] Critical: Could not find ModalNative root logic.");
                    return;
                }

                // 2. Sicherer Log-Mechanismus
                const safeLog = (msg, data) => {
                    if (root._log) root._log(msg, data);
                    else if (root.log) root.log(msg, data);
                    else console.log("[p11][Backup-Log] " + msg, data || "");
                };

                // 3. Aktive Modale prüfen
                const hasActiveModals = root._activeModals && root._activeModals.length > 0;

                // 4. C# Brücke prüfen
                if (this._dotNetHelper) {
                    safeLog("Triggering HandleNativeBack in C#", { hasActiveModals });

                    // Funkspruch an Blazor
                    this._dotNetHelper.invokeMethodAsync('HandleNativeBack', true);

                    // Fall 3 Sicherung
                    if (!hasActiveModals) {
                        safeLog("No active modals. Performing immediate JS state reset.");
                        if (root.forceReset) root.forceReset();
                    }
                } else {
                    const isNative = window.Capacitor?.isNative;
                    if (isNative) {
                        console.warn("[p11] Swipe detected, but no DotNet-Reference.");
                    }
                    if (root.forceReset) root.forceReset();
                }
            } catch (e) {
                console.error("[p11] Critical error in _triggerCSharpBack:", e);
                // Letzter Rettungsanker für den UI-Reset
                if (window.p11Js && window.p11Js.ModalNative && window.p11Js.ModalNative.forceReset) {
                    window.p11Js.ModalNative.forceReset();
                }
            }
        },

        /**
         * Registers the DotNet reference from C# (EventStateService).
         * @param {object} dotNetHelper - The DotNetObjectReference.
         */
        setDotNetHelper: function (dotNetHelper) {
            this._dotNetHelper = dotNetHelper;
            this._log("DotNet-Helper registered successfully.");
        },

        /**
         * Creates a visual overlay behind the element being swiped.
         * @param {boolean} isModalOpen - Determines the z-index stacking.
         */
        _createOverlay: function (isModalOpen) {
            if (document.getElementById('p11-swipe-overlay')) return;

            const overlay = document.createElement('div');
            overlay.id = 'p11-swipe-overlay';

            // Dynamischer Z-Index: Vor oder hinter dem Modal/App
            const zIndex = isModalOpen ? 1100 : 9998;
            overlay.style.zIndex = zIndex.toString();

            document.body.appendChild(overlay);
            this._log(`Overlay created (Modal-Mode: ${isModalOpen}, Z-Index: ${zIndex})`);
        },

        /**
         * Cleans up CSS and DOM elements after a swipe gesture.
         * Integrates the old _cleanup logic for footers and backdrops.
         * @param {boolean} isSuccess - True if back action triggered, false if aborted.
         */
        _cleanupWithFallback: function (isSuccess) {
            // 1. Overlay entfernen (ID auf p11 angepasst)
            const overlay = document.getElementById('p11-swipe-overlay');
            if (overlay) overlay.remove();

            if (this.currentTargetEl) {
                if (!isSuccess) {
                    // --- LOGIK AUS DER ALTEN _cleanup (Snap-Back) ---
                    this.currentTargetEl.style.transition = 'transform 0.1s ease-out';
                    this.currentTargetEl.style.transform = '';

                    // Backdrops zurücksetzen
                    if (this.currentBackdropEl) {
                        this.currentBackdropEl.style.transition = 'opacity 0.1s ease-out';
                        this.currentBackdropEl.style.opacity = '0.5';
                    }

                    // Spezial-Handling für Footer/Fixierte Elemente (falls keine Modale offen sind)
                    const isModalOpen = ModalNativeFunctions._activeModals.length > 0;
                    if (!isModalOpen) {
                        const fixedElements = document.querySelectorAll('footer, .footer, .fixed-bottom');
                        fixedElements.forEach(el => {
                            el.style.transition = 'transform 0.1s ease-out';
                            el.style.transform = '';
                        });
                    }

                    // Endgültiges Löschen der Styles nach der Mini-Animation
                    setTimeout(() => {
                        if (this.currentTargetEl) {
                            this.currentTargetEl.style.transition = '';
                            this.currentTargetEl.style.willChange = '';
                        }
                    }, 100);

                } else {
                    // --- ERFOLGS-FALL (Fly-Out) ---
                    // Element bleibt bei 100%, bis Blazor es entfernt
                    this.currentTargetEl.style.transition = 'none';

                    // Sicherheits-Timer (wie besprochen)
                    setTimeout(() => {
                        if (this.currentTargetEl && document.body.contains(this.currentTargetEl)) {
                            if (this.currentTargetEl.style.transform === 'translateX(100%)') {
                                this.currentTargetEl.style.transform = '';
                                this.currentTargetEl.style.transition = '';
                            }
                        }
                    }, 500);
                }
            }
            this._log(`Cleanup executed (Success: ${isSuccess})`);
        },

        /**
         * Resets all internal tracking variables to their initial state.
         * Called after every swipe completion or cancellation.
         */
        _reset: function () {
            this.startX = 0;
            this.startY = 0;
            this.currentX = 0;
            this.startTime = 0;
            this.isSwiping = false;

            // Wichtig: Referenzen auf DOM-Elemente lösen, um Memory Leaks zu vermeiden
            this.currentTargetEl = null;
            this.currentBackdropEl = null;

            this._log("Internal status reset.");
        },

        /**
         * Forcefully resets the UI to a clean state. 
         * Use this as a fallback if the UI remains stuck after a gesture.
         */
        forceReset: function () {
            this._log("Force-Reset requested. Normalizing UI state...");

            // 1. Alle potenziell betroffenen Elemente finden (App, Modals, Backdrops, Overlay)
            const elementsToClean = document.querySelectorAll(
                '#app, .modal, .modal-backdrop, #p11-swipe-overlay'
            );

            elementsToClean.forEach(el => {
                if (el) {
                    // Styles sofort hart zurücksetzen
                    el.style.transition = 'none';
                    el.style.transform = '';

                    if (el.classList.contains('modal-backdrop')) {
                        el.style.opacity = ''; // Zurück auf Bootstrap Default (0.5 via CSS)
                    }

                    // Overlay komplett entfernen
                    if (el.id === 'p11-swipe-overlay') {
                        el.remove();
                    }

                    // Nach einem kurzen Moment die Style-Attribute ganz säubern
                    setTimeout(() => {
                        el.style.transition = '';
                        el.style.willChange = '';
                    }, 50);
                }
            });

            // 2. Bootstrap-Reste vom Body entfernen (verhindert Scroll-Lock)
            document.body.classList.remove('modal-open');
            document.body.style.overflow = '';
            document.body.style.paddingRight = '';

            // 3. Interne Variablen zurücksetzen
            this._reset();

            this._log("Force-Reset completed.");
        },

        /**
         * Completely shuts down the module and cleans up all resources.
         * Essential for SPA environments like Blazor.
         */
        dispose: function () {
            this._log("Disposing module...");

            // 1. System deaktivieren (entfernt ggf. Event-Listener oder setzt Flags)
            this.isEnabled = false;

            // 2. Visuelle Reste entfernen (Overlay, Transformationen)
            // Wir nutzen false, da es kein erfolgreicher Swipe war
            this._cleanupWithFallback(false);

            // 3. DotNet-Referenz löschen (Wichtig gegen Memory Leaks!)
            this._dotNetHelper = null;

            // 4. Interne Variablen zurücksetzen
            this._reset();

            this._log("Module disposed and resources cleared.");
        }
    }
};

/**
 * Global Touch Listeners initialization
 */
function setupSwipeListeners() {
    const sb = ModalNativeFunctions._logic;

    if (sb._handlers) {
        document.removeEventListener('touchstart', sb._handlers.start);
        document.removeEventListener('touchmove', sb._handlers.move);
        document.removeEventListener('touchend', sb._handlers.end);
        document.removeEventListener('touchcancel', sb._handlers.cancel);
    }

    const startHandler = (e) => sb.onStart.call(sb, e);
    const moveHandler = (e) => sb.onMove.call(sb, e);
    const endHandler = (e) => sb.onEnd.call(sb, e);
    const cancelHandler = (e) => sb.onCancel.call(sb, e);

    document.addEventListener('touchstart', startHandler, { passive: true });
    document.addEventListener('touchmove', moveHandler, { passive: false });
    document.addEventListener('touchend', endHandler, { passive: true });
    document.addEventListener('touchcancel', cancelHandler, { passive: true });

    sb._handlers = {
        start: startHandler,
        move: moveHandler,
        end: endHandler,
        cancel: cancelHandler
    };

    sb._log("Touch listeners established");
}

/**
 * Handles iOS-specific safe area bottom spacing for footers and layouts.
 */
function setFooterBottom() {
    let footerBottom = 0;
    const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);

    if (isIOS) {
        const rootStyles = getComputedStyle(document.documentElement);
        const safeBottomStr = rootStyles.getPropertyValue('--ion-safe-area-bottom')
            || rootStyles.getPropertyValue('env(safe-area-inset-bottom)')
            || '0px';

        const safeBottom = parseFloat(safeBottomStr);
        footerBottom = (safeBottom > 0) ? safeBottom : 8;
    }

    document.documentElement.style.setProperty('--p11-footer-fix', `${footerBottom}px`);
    document.body.style.paddingBottom = `${footerBottom}px`;
}

/* ========================================================================
   AUTO-INITIALIZATION
   ======================================================================== */
const initializeP11Native = () => {
    ModalNativeFunctions._logic._log("Initializing UI Services...");

    // 1. Layout-Korrektur (Safe Areas)
    setFooterBottom();
    window.addEventListener('resize', setFooterBottom);

    // 2. Swipe-Listener registrieren
    setupSwipeListeners();

    // 3. App-Modus aktivieren
    ModalNativeFunctions.enable(true);
};

if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initializeP11Native);
} else {
    initializeP11Native();
}