(function ($) {
    "use strict";

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

        const canvas = wrapper.querySelector('.sifency-field-canvas');
        const ctx = canvas.getContext('2d');
        const config = JSON.parse(canvas.dataset.config || '{}');

        let width, height;
        let particles = [];
        let mouse = { x: -1000, y: -1000 }; // Default mouse out of screen

        // Variables for physics calculations
        const { gridSize, pWidth, pHeight, radius, color, baseOpacity, hoverOpacity } = config;

        // Convert HEX to RGB for smooth opacity manipulation
        const hexToRgb = (hex) => {
            const shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
            hex = hex.replace(shorthandRegex, (m, r, g, b) => r + r + g + g + b + b);
            const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
            return result ? `${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}` : '255, 255, 255';
        };
        const rgbColor = hexToRgb(color);

        class Particle {
            constructor(x, y) {
                this.x = x;
                this.y = y;
                // Target angle and opacity based on mouse
                this.targetAngle = 0;
                this.targetOpacity = baseOpacity;
                // Current properties (for GSAP to animate)
                this.angle = 0;
                this.opacity = baseOpacity;
            }

            draw() {
                ctx.save();
                ctx.translate(this.x, this.y);
                ctx.rotate(this.angle); // Rotate to face mouse

                // Draw the line/particle
                ctx.fillStyle = `rgba(${rgbColor}, ${this.opacity})`;
                ctx.fillRect(-pWidth / 2, -pHeight / 2, pWidth, pHeight);

                ctx.restore();
            }

            update() {
                // Calculate distance from mouse
                const dx = mouse.x - this.x;
                const dy = mouse.y - this.y;
                const distance = Math.sqrt(dx * dx + dy * dy);

                if (distance < radius) {
                    // Calculate angle facing the mouse
                    this.targetAngle = Math.atan2(dy, dx);

                    // Opacity increases as mouse gets closer
                    const influence = 1 - (distance / radius);
                    this.targetOpacity = baseOpacity + (hoverOpacity - baseOpacity) * influence;
                } else {
                    // Default state when mouse is far
                    this.targetAngle = 0; // Or keep it facing last direction
                    this.targetOpacity = baseOpacity;
                }

                // Smooth GSAP-style interpolation (Lerp)
                this.angle += (this.targetAngle - this.angle) * 0.1;
                this.opacity += (this.targetOpacity - this.opacity) * 0.1;

                this.draw();
            }
        }

        const initCanvas = () => {
            const dpr = window.devicePixelRatio || 1;
            width = wrapper.clientWidth;
            height = wrapper.clientHeight;

            canvas.width = width * dpr;
            canvas.height = height * dpr;
            ctx.scale(dpr, dpr);

            particles = [];

            // Create grid of particles
            for (let y = gridSize; y < height; y += gridSize) {
                for (let x = gridSize; x < width; x += gridSize) {
                    particles.push(new Particle(x, y));
                }
            }
        };

        const animate = () => {
            // Clear canvas for next frame
            ctx.clearRect(0, 0, width, height);

            particles.forEach(p => p.update());

            wrapper.animationFrame = requestAnimationFrame(animate);
        };

        // Event Listeners
        wrapper.addEventListener('mousemove', (e) => {
            const rect = wrapper.getBoundingClientRect();
            mouse.x = e.clientX - rect.left;
            mouse.y = e.clientY - rect.top;
        });

        wrapper.addEventListener('mouseleave', () => {
            // Reset mouse far away so particles return to default
            mouse.x = -1000;
            mouse.y = -1000;
        });

        window.addEventListener('resize', () => {
            initCanvas();
        });

        // Start Engine
        initCanvas();
        if (wrapper.animationFrame) cancelAnimationFrame(wrapper.animationFrame);
        animate();
    };

    $(window).on('elementor/frontend/init', function () {
        elementorFrontend.hooks.addAction(
            'frontend/element_ready/sifency-interactive-field.default',
            initMagneticField
        );
    });

})(jQuery);