(function ($) {
    "use strict";

    const initTrue3DText = ($scope) => {
        const wrapper = $scope.find('.sifency-true-3d-wrapper')[0];
        if (!wrapper) return;

        // Ensure Three.js is loaded
        if (typeof THREE === 'undefined') {
            console.error('Sifency Error: Three.js is not loaded.');
            return;
        }

        const targetSpan = wrapper.querySelector('.sifency-3d-target');
        const canvas = wrapper.querySelector('.sifency-3d-canvas');
        if (!targetSpan || !canvas) return;

        const config = JSON.parse(wrapper.dataset.config || '{}');
        const char = targetSpan.dataset.char;
        const depth = parseFloat(config.depth || 15);
        const speed = parseFloat(config.speed || 0.03);
        const colorHex = config.color || '#ffffff';

        // --- Three.js Setup ---
        const scene = new THREE.Scene();

        // Alpha: true makes canvas background transparent
        const renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: true, antialias: true });

        // Setup Camera
        const camera = new THREE.PerspectiveCamera(45, 1, 0.1, 1000);
        camera.position.z = 100; // Pull camera back to see the letter

        // --- Premium Lighting (Makes it look 3D and not flat) ---
        const ambientLight = new THREE.AmbientLight(0xffffff, 0.6); // Base light
        scene.add(ambientLight);

        const pointLight = new THREE.PointLight(0xffffff, 1.5); // Highlight for edges
        pointLight.position.set(50, 50, 50);
        scene.add(pointLight);

        const backLight = new THREE.PointLight(0xffffff, 0.8);
        backLight.position.set(-50, -50, -50);
        scene.add(backLight);

        let textMesh;
        let animationFrameId;

        // --- Load Font & Generate 3D Text ---
        // Note: You must host a typeface.json file. This is a standard bold font.
        const fontUrl = 'https://threejs.org/examples/fonts/helvetiker_bold.typeface.json';

        const loader = new THREE.FontLoader();
        loader.load(fontUrl, function (font) {

            const textGeo = new THREE.TextGeometry(char, {
                font: font,
                size: 50, // Base size
                height: depth, // The 3D Thickness/Extrusion
                curveSegments: 12, // Smoothness of curves (e.g. for 'R' or 'O')
                bevelEnabled: true, // Bevel makes the edges catch light better!
                bevelThickness: 1,
                bevelSize: 1,
                bevelSegments: 3
            });

            // Center the geometry so it rotates perfectly around its middle
            textGeo.computeBoundingBox();
            const centerOffset = -0.5 * (textGeo.boundingBox.max.x - textGeo.boundingBox.min.x);
            const heightOffset = -0.5 * (textGeo.boundingBox.max.y - textGeo.boundingBox.min.y);
            const depthOffset = -0.5 * (textGeo.boundingBox.max.z - textGeo.boundingBox.min.z);
            textGeo.translate(centerOffset, heightOffset, depthOffset);

            // Create Premium Material (Glossy/Matte plastic look)
            const material = new THREE.MeshStandardMaterial({
                color: colorHex,
                roughness: 0.3, // Lower is glossier
                metalness: 0.2
            });

            textMesh = new THREE.Mesh(textGeo, material);
            scene.add(textMesh);

            // Resize canvas to match the CSS span size
            resize();

            // Start Animation Loop
            render();
        });

        // Resize function to perfectly fit the Canvas over the invisible CSS letter
        const resize = () => {
            const width = targetSpan.offsetWidth;
            const height = targetSpan.offsetHeight;

            // We set the canvas to be square based on height to give rotation room
            const size = Math.max(width, height) * 1.5; // 1.5x buffer for 3D rotation clipping

            renderer.setSize(size, size);
            renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

            camera.aspect = 1;
            camera.updateProjectionMatrix();

            const dist = size / (2 * Math.tan(camera.fov * Math.PI / 360));
            camera.position.z = dist * 1.2; // Minor adjustment to fit perfectly
        };

        window.addEventListener('resize', resize);

        // Animation Loop
        const render = () => {
            if (textMesh) {
                textMesh.rotation.y += speed; // Rotate around Y axis
            }
            renderer.render(scene, camera);
            animationFrameId = requestAnimationFrame(render);
        };

        // Cleanup on Elementor Edit
        $scope.on('remove', () => {
            cancelAnimationFrame(animationFrameId);
            window.removeEventListener('resize', resize);
            if (textMesh) {
                textMesh.geometry.dispose();
                textMesh.material.dispose();
            }
            renderer.dispose();
        });
    };

    $(window).on('elementor/frontend/init', function () {
        elementorFrontend.hooks.addAction(
            'frontend/element_ready/sifency-addons-3d-letter.default',
            initTrue3DText
        );
    });

})(jQuery);