/**
 * p11ModalNative.js
 * Version 2.2
 * Kombiniert die robuste C#-Brücke der alten Version mit der neuen lokalen Listener-Architektur.
 */

export const ModalNativeFunctions = {
    _activeModals: new Map(), // Speicherung via Guid/ID für gezielten Zugriff
    _dotNetHelper: null,      // Die Referenz zum EventStateService
    _isEnabled: true,         // Globaler Schalter für das Modul

    /* ========================================================================
       C# INTERFACE (Bridge-Funktionen aus der alten Version)
       ======================================================================== */

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

    /**
     * Alias für die Registrierung des Helpers (aus dem alten registerHelper).
     */
    registerHelper: function (dotNetHelper) {
        this._dotNetHelper = dotNetHelper;
        p11Js.log("ModalNative", "DotNetHelper registriert.");
    },

    /**
         * Aktiviert oder deaktiviert die Swipe-Logik (Abwärtskompatibel).
         */
    enable: function (enabled) {
        this.setSwipeEnabled(enabled);
    },

    /**
     * Aktiviert oder deaktiviert die Swipe-Logik (aus der alten Version).
     */
    setSwipeEnabled: function (enabled) {
        this._isEnabled = enabled;
        p11Js.log("ModalNative", `Modul-Status: ${enabled ? 'AKTIVIERT' : 'DEAKTIVIERT'}`);
    },

    /**
     * Synchronisiert Konfigurationswerte aus C# (EdgeSize, Threshold etc.).
     */
    updateConfiguration: function (config) {
        if (!config) return;
        // Wir speichern die Config lokal ab, damit die Swipe-Logik darauf zugreifen kann
        this._config = {
            edgeSize: p11Js.Utility.getPlatform() === 'ios' ? (config.iosEdgeSize ?? 35) : (config.androidEdgeSize ?? 0),
            threshold: config.threshold ?? 80,
            velocityLimit: 0.3
        };
        p11Js.log("ModalNative", "Konfiguration aktualisiert", this._config);
    },

    /* ========================================================================
       MODAL CORE LOGIC (Initialisierung & Release)
       ======================================================================== */

    focusModalAndTrapModalNative: function (element, elementId, restoreFocusId, preventScroll) {
        if (!element || !elementId) return;

        p11Js.log("ModalNative", `Initializing Modal: ${elementId}`);

        // 1. Z-Index via Utility
        const stackDepth = this._activeModals.size;
        const newZIndex = window.p11Js.Utility.getNextZIndex(stackDepth, 'P11ModalNative');
        element.style.zIndex = newZIndex;

        const backdrop = document.querySelector('.modal-backdrop.show:not([style*="z-index"])')
            || document.querySelector('.modal-backdrop.show');
        if (backdrop) {
            backdrop.style.zIndex = (newZIndex - 1);
        }

        // 2. Scroll Lock via Utility
        if (preventScroll) {
            p11Js.Utility.requestScrollLock(elementId);
        }

        // 3. Lokale Listener einrichten
        const swipeCleanup = this._setupLocalSwipe(element, elementId, backdrop);

        const escapeHandler = (e) => {
            if (e.key === 'Escape') this._triggerClose(elementId);
        };
        element.addEventListener('keydown', escapeHandler);

        // 4. In Map registrieren
        this._activeModals.set(elementId, {
            element,
            backdrop,
            restoreFocusId,
            cleanup: () => {
                swipeCleanup();
                element.removeEventListener('keydown', escapeHandler);
            }
        });

        // 5. Initialer Fokus
        setTimeout(() => { if (document.contains(element)) element.focus(); }, 50);
    },

    releaseModalNative: function (elementId) {
        const state = this._activeModals.get(elementId);
        if (!state) return;

        p11Js.log("ModalNative", `Release Modal: ${elementId}`);

        if (state.cleanup) state.cleanup();
        p11Js.Utility.releaseScrollLock(elementId);
        this._resetElementStyles(state.element, state.backdrop);

        this._activeModals.delete(elementId);

        // Fokus-Hierarchie wiederherstellen (Stack-Logik)
        if (this._activeModals.size > 0) {
            const modalArray = Array.from(this._activeModals.values());
            const topModal = modalArray[modalArray.length - 1];
            if (topModal?.element) {
                setTimeout(() => { try { topModal.element.focus(); } catch (e) { } }, 10);
            }
        } else if (state.restoreFocusId) {
            const el = document.getElementById(state.restoreFocusId);
            if (el) setTimeout(() => { try { el.focus(); } catch (e) { } }, 50);
        }
    },

    /* ========================================================================
       INTERNAL HELPERS (Swipe & Communication)
       ======================================================================== */

    _setupLocalSwipe: function (element, elementId, backdrop) {
        let startX = 0, startY = 0, startTime = 0, isSwiping = false;

        // Standard-Config oder aktualisierte Config aus C#
        const cfg = this._config || {
            edgeSize: p11Js.Utility.getPlatform() === 'ios' ? 35 : 0,
            threshold: 80,
            velocityLimit: 0.3
        };

        const onStart = (e) => {
            if (!this._isEnabled || !e.touches || e.touches.length !== 1) return;
            const touch = e.touches[0];

            if (cfg.edgeSize > 0 && touch.clientX > cfg.edgeSize) return;
            if (e.target.closest('button, a, input, textarea, select, .no-swipe')) return;

            startX = touch.clientX;
            startY = touch.clientY;
            startTime = Date.now();
            isSwiping = false;
            element.style.transition = 'none';
            if (backdrop) backdrop.style.transition = 'none';
        };

        const onMove = (e) => {
            if (startX === 0) return;
            const metrics = p11Js.Utility.getSwipeMetrics(e, startX, startY);
            if (!metrics) return;

            if (!isSwiping) {
                if (metrics.diffX > 10 && metrics.isHorizontal) isSwiping = true;
                else if (metrics.absY > 30) { startX = 0; return; }
            }

            if (isSwiping) {
                if (e.cancelable) e.preventDefault();
                const moveX = Math.max(0, metrics.diffX);
                element.style.transform = `translateX(${moveX}px)`;
                if (backdrop) {
                    const progress = Math.min(1, moveX / (window.innerWidth * 0.8));
                    backdrop.style.opacity = (0.5 * (1 - progress)).toString();
                }
            }
        };

        const onEnd = (e) => {
            if (!isSwiping) { this._resetElementStyles(element, backdrop); startX = 0; return; }
            const duration = Date.now() - startTime;
            const finalTouch = e.changedTouches ? e.changedTouches[0] : null;
            const diffX = finalTouch ? finalTouch.clientX - startX : 0;
            const velocity = diffX / duration;

            if (diffX > cfg.threshold || velocity > cfg.velocityLimit) {
                this._executeFlyOut(element, backdrop, elementId);
            } else {
                this._executeSnapBack(element, backdrop);
            }
            startX = 0; isSwiping = false;
        };

        element.addEventListener('touchstart', onStart, { passive: true });
        element.addEventListener('touchmove', onMove, { passive: false });
        element.addEventListener('touchend', onEnd, { passive: true });

        return () => {
            element.removeEventListener('touchstart', onStart);
            element.removeEventListener('touchmove', onMove);
            element.removeEventListener('touchend', onEnd);
        };
    },

    _executeFlyOut: function (element, backdrop, elementId) {
        element.style.transition = 'transform 0.2s cubic-bezier(0.25, 0.46, 0.45, 0.94)';
        element.style.transform = 'translateX(100%)';
        if (backdrop) {
            backdrop.style.transition = 'opacity 0.2s ease-out';
            backdrop.style.opacity = '0';
        }
        setTimeout(() => this._triggerClose(elementId), 180);
    },

    _executeSnapBack: function (element, backdrop) {
        element.style.transition = 'transform 0.3s ease-out';
        element.style.transform = 'translateX(0)';
        if (backdrop) {
            backdrop.style.transition = 'opacity 0.3s ease-out';
            backdrop.style.opacity = '0.5';
        }
    },

    _resetElementStyles: function (element, backdrop) {
        if (element) { element.style.transform = ''; element.style.transition = ''; }
        if (backdrop) { backdrop.style.opacity = ''; backdrop.style.transition = ''; }
    },

    _triggerClose: function (elementId) {
        // Hier nutzen wir die spezifisch registrierte C#-Referenz
        if (this._dotNetHelper) {
            this._dotNetHelper.invokeMethodAsync('HandleNativeBack', true, elementId);
        } else {
            console.error("[p11] ModalNative: Kein DotNetHelper registriert.");
        }
    },

    forceReset: function () {
        this._activeModals.forEach((value, key) => this.releaseModalNative(key));
        p11Js.Utility.clearBodyStyles();
    }
};