/**
 * Three.js GLB viewer and design decal application (car products).
 */
(function (global) {
    "use strict";

    global.IAPC = global.IAPC || {};

    var deps = {
        getCanvas: null,
        redraw: null,
        getDesignCanvas: null,
        notify: null,
        translate: null
    };

    var iapcVista3DActiva = false;
    var iapc3DScene = null;
    var iapc3DCamera = null;
    var iapc3DRenderer = null;
    var iapc3DModel = null;
    var iapc3DAnimation = null;
    var iapc3DLoaded = false;
    var iapc3DBodyMesh = null;
    var iapc3DBodyMeshes = [];
    var iapc3DMeshes = [];

    global.iapc3DBodyMesh = iapc3DBodyMesh;
    global.iapc3DMeshes = iapc3DMeshes;

    function notify(message, type) {
        if (deps.notify) {
            deps.notify(message, type);
        }
    }

    function translate(key) {
        if (deps.translate) {
            return deps.translate.apply(null, arguments);
        }

        return key;
    }

    function getCanvas() {
        return deps.getCanvas ? deps.getCanvas() : null;
    }

    function getDesignCanvas() {
        return deps.getDesignCanvas ? deps.getDesignCanvas() : null;
    }

    function redraw() {
        if (deps.redraw) {
            deps.redraw();
        }
    }

    function centrarModelo3D(modelo) {
        var box = new THREE.Box3().setFromObject(modelo);
        var centro = box.getCenter(new THREE.Vector3());
        var size = box.getSize(new THREE.Vector3());

        modelo.position.x -= centro.x;
        modelo.position.y -= centro.y;
        modelo.position.z -= centro.z;

        var maxDim = Math.max(size.x, size.y, size.z);
        var escala = 5.5 / maxDim;

        modelo.scale.setScalar(escala);
    }

    function mostrarVista3D() {
        var contenedor3D = document.getElementById("iapc_3d_wrap");
        var canvas = getCanvas();

        if (!contenedor3D || !canvas) {
            return;
        }

        canvas.style.display = "none";
        contenedor3D.style.display = "block";
        contenedor3D.style.width = "100%";
        contenedor3D.style.height = "500px";
    }

    function ocultarVista3D() {
        var contenedor3D = document.getElementById("iapc_3d_wrap");
        var canvas = getCanvas();

        if (!contenedor3D || !canvas) {
            return;
        }

        contenedor3D.style.display = "none";
        canvas.style.display = "block";
    }

    function animarModelo3D() {
        if (!iapcVista3DActiva || !iapc3DRenderer || !iapc3DScene || !iapc3DCamera) {
            return;
        }

        if (iapc3DModel) {
            iapc3DModel.rotation.y += 0.01;
        }

        iapc3DRenderer.render(iapc3DScene, iapc3DCamera);
        iapc3DAnimation = global.requestAnimationFrame(animarModelo3D);
    }

    function aplicarDecalAlModelo3D() {
        var designCanvas = getDesignCanvas();

        redraw();

        if (!designCanvas || !iapc3DBodyMeshes.length) {
            return;
        }

        var textura = new THREE.CanvasTexture(designCanvas);
        textura.flipY = false;
        textura.needsUpdate = true;
        textura.wrapS = THREE.ClampToEdgeWrapping;
        textura.wrapT = THREE.ClampToEdgeWrapping;

        iapc3DBodyMeshes.forEach(function (mesh) {
            var tieneUV = !!(mesh.geometry && mesh.geometry.attributes && mesh.geometry.attributes.uv);

            if (!tieneUV) {
                console.warn("Mesh has no UV map:", mesh.name);
                return;
            }

            mesh.material = new THREE.MeshBasicMaterial({
                map: textura
            });

            mesh.material.needsUpdate = true;
        });

        if (iapc3DRenderer && iapc3DScene && iapc3DCamera) {
            iapc3DRenderer.render(iapc3DScene, iapc3DCamera);
        }
    }

    function seleccionarCarroceriaManual() {
        if (!iapc3DMeshes.length) {
            notify(translate("no3dParts"), "warning");
            return;
        }

        var lista = iapc3DMeshes
            .map(function (item, index) {
                return index + ": " + item.name;
            })
            .join("\n");

        var elegido = global.prompt(translate("selectBodyMesh") + "\n\n" + lista);

        if (elegido === null) {
            return;
        }

        var index = parseInt(elegido, 10);

        if (!iapc3DMeshes[index]) {
            notify(translate("invalidNumber"), "warning");
            return;
        }

        iapc3DBodyMesh = iapc3DMeshes[index].mesh;
        global.iapc3DBodyMesh = iapc3DBodyMesh;

        notify(translate("bodySelected", iapc3DMeshes[index].name), "success");
        aplicarDecalAlModelo3D();
    }

    function cargarModelo3D() {
        var contenedor3D = document.getElementById("iapc_3d_wrap");
        var canvas = getCanvas();

        function failNotify(message, type) {
            notify(message, type);
            return false;
        }

        if (!contenedor3D) {
            return failNotify(translate("no3dContainer"), "error");
        }

        if (typeof THREE === "undefined" || typeof THREE.GLTFLoader === "undefined") {
            return failNotify(translate("noThreeJs"), "error");
        }

        if (
            typeof global.IAPC_DATA === "undefined" ||
            global.IAPC_DATA.productType !== "car" ||
            !global.IAPC_DATA.model3d
        ) {
            return failNotify(translate("no3dModel"), "warning");
        }

        if (iapc3DLoaded) {
            mostrarVista3D();
            aplicarDecalAlModelo3D();
            return true;
        }

        notify(translate("loading3d"), "info");

        contenedor3D.innerHTML = "";

        var ancho = canvas ? (canvas.clientWidth || 600) : 600;
        var alto = canvas ? (canvas.clientHeight || 500) : 500;

        iapc3DScene = new THREE.Scene();
        iapc3DCamera = new THREE.PerspectiveCamera(45, ancho / alto, 0.1, 1000);
        iapc3DCamera.position.set(0, 1.2, 8);
        iapc3DCamera.lookAt(0, 0, 0);

        iapc3DRenderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        iapc3DRenderer.setSize(ancho, alto);
        iapc3DRenderer.setPixelRatio(global.devicePixelRatio || 1);
        contenedor3D.appendChild(iapc3DRenderer.domElement);

        iapc3DScene.add(new THREE.AmbientLight(0xffffff, 1.2));

        var luzDireccional = new THREE.DirectionalLight(0xffffff, 1.6);
        luzDireccional.position.set(3, 5, 4);
        iapc3DScene.add(luzDireccional);

        var loader = new THREE.GLTFLoader();

        loader.load(
            global.IAPC_DATA.model3d,
            function (gltf) {
                iapc3DModel = gltf.scene;
                iapc3DScene.add(iapc3DModel);

                var carroceriaEncontrada = false;

                iapc3DMeshes = [];
                iapc3DBodyMeshes = [];
                global.iapc3DMeshes = iapc3DMeshes;

                var bodyMeshNames = Array.isArray(global.IAPC_DATA.bodyMeshNames)
                    ? global.IAPC_DATA.bodyMeshNames
                    : [];

                iapc3DModel.traverse(function (objeto) {
                    if (!objeto.isMesh) {
                        return;
                    }

                    var nombre = objeto.name || "Unnamed";

                    iapc3DMeshes.push({
                        name: nombre,
                        mesh: objeto
                    });

                    if (
                        bodyMeshNames.includes(nombre) ||
                        (
                            global.IAPC_DATA.allowedBodyNames &&
                            global.IAPC_DATA.allowedBodyNames.includes(nombre)
                        )
                    ) {
                        carroceriaEncontrada = true;
                        iapc3DBodyMeshes.push(objeto);
                    }
                });

                centrarModelo3D(iapc3DModel);

                iapc3DLoaded = true;
                iapcVista3DActiva = true;
                mostrarVista3D();
                animarModelo3D();

                if (carroceriaEncontrada) {
                    notify(translate("loaded3d"), "success");
                    aplicarDecalAlModelo3D();
                } else {
                    notify(translate("loaded3dNoBody"), "warning");
                    seleccionarCarroceriaManual();
                }
            },
            function () {},
            function (error) {
                console.error("GLB load error:", error);

                notify(translate("error3dAlert"), "error");
                iapcVista3DActiva = false;

                var btn3D = document.getElementById("iapc_3d_view");

                if (btn3D) {
                    btn3D.textContent = translate("view3d");
                }

                ocultarVista3D();
                redraw();
            }
        );

        return true;
    }

    function updateIfActive() {
        if (iapcVista3DActiva && iapc3DBodyMeshes.length) {
            aplicarDecalAlModelo3D();
        }
    }

    function shouldUpdateDecal() {
        return iapcVista3DActiva && iapc3DBodyMeshes.length > 0;
    }

    function configure(options) {
        deps.getCanvas = options.getCanvas || null;
        deps.redraw = options.redraw || null;
        deps.getDesignCanvas = options.getDesignCanvas || null;
        deps.notify = options.notify || null;
        deps.translate = options.translate || null;
    }

    global.aplicarDecalAlModelo3D = aplicarDecalAlModelo3D;

    global.IAPC.viewer3d = {
        configure: configure,
        loadModel: cargarModelo3D,
        applyDecal: aplicarDecalAlModelo3D,
        updateIfActive: updateIfActive,
        shouldUpdateDecal: shouldUpdateDecal,
        show: mostrarVista3D,
        hide: ocultarVista3D
    };
})(window);
