(function ($) {
    "use strict";

    const initVanillaDraggable = ($scope) => {
        const wrapper = $scope.find('.sifency-draggable-wrapper')[0];
        if (!wrapper) return;

        // Disable in Elementor Editor to allow editing
        if ($('body').hasClass('elementor-editor-active')) {
            return;
        }

        const inner = wrapper.querySelector('.sifency-draggable-inner');
        const boundsType = wrapper.dataset.bounds || 'window';

        let isDragging = false;
        let currentX = 0, currentY = 0;
        let initialX = 0, initialY = 0;
        let xOffset = 0, yOffset = 0;

        // Boundary Setup
        const checkBounds = (x, y) => {
            const rect = wrapper.getBoundingClientRect();
            let minX, maxX, minY, maxY;

            if (boundsType === 'window') {
                minX = -rect.left + xOffset;
                maxX = window.innerWidth - rect.right + xOffset;
                minY = -rect.top + yOffset;
                maxY = window.innerHeight - rect.bottom + yOffset;
            } else {
                const parentRect = wrapper.parentElement.getBoundingClientRect();
                minX = parentRect.left - rect.left + xOffset;
                maxX = parentRect.right - rect.right + xOffset;
                minY = parentRect.top - rect.top + yOffset;
                maxY = parentRect.bottom - rect.bottom + yOffset;
            }

            // Clamp values
            const clampedX = Math.min(Math.max(x, minX), maxX);
            const clampedY = Math.min(Math.max(y, minY), maxY);

            return { x: clampedX, y: clampedY };
        };

        const dragStart = (e) => {
            if (e.type === "touchstart") {
                initialX = e.touches[0].clientX - xOffset;
                initialY = e.touches[0].clientY - yOffset;
            } else {
                initialX = e.clientX - xOffset;
                initialY = e.clientY - yOffset;
            }

            // Check if user is clicking on an inner interactive element (like a link)
            if (e.target.tagName.toLowerCase() === 'a') return;

            isDragging = true;

            wrapper.classList.add('sifency-is-dragging');
            
            // Bring to front
            wrapper.style.zIndex = 9999;
        };

        const dragEnd = (e) => {
            initialX = currentX;
            initialY = currentY;
            isDragging = false;
            
            wrapper.classList.remove('sifency-is-dragging');
        };

        const drag = (e) => {
            if (!isDragging) return;
            
            e.preventDefault(); // Prevents scroll while dragging on mobile

            let rawX, rawY;
            if (e.type === "touchmove") {
                rawX = e.touches[0].clientX - initialX;
                rawY = e.touches[0].clientY - initialY;
            } else {
                rawX = e.clientX - initialX;
                rawY = e.clientY - initialY;
            }

            // Apply Boundaries
            const bounded = checkBounds(rawX, rawY);
            currentX = bounded.x;
            currentY = bounded.y;

            xOffset = currentX;
            yOffset = currentY;

            // Hardware Accelerated Movement using requestAnimationFrame for smoothness
            requestAnimationFrame(() => {
                wrapper.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`;
            });
        };

        // Event Listeners for Mouse
        wrapper.addEventListener("mousedown", dragStart, false);
        window.addEventListener("mouseup", dragEnd, false);
        window.addEventListener("mousemove", drag, false);

        // Event Listeners for Touch (Mobile)
        wrapper.addEventListener("touchstart", dragStart, { passive: false });
        window.addEventListener("touchend", dragEnd, false);
        window.addEventListener("touchmove", drag, { passive: false });
    };

    $(window).on('elementor/frontend/init', function () {
        elementorFrontend.hooks.addAction(
            'frontend/element_ready/sifency-draggable-object.default',
            initVanillaDraggable
        );
    });

})(jQuery);