// ── CONFIGURACIÓN DE PLANTILLAS DE CLIENTES ──
export const clientTemplates = {
    'Esp': {
        'Generico': 'images/AF Generico Esp.png',
        'Claro': 'images/AF Claro Esp.png',
        'Colgate': 'images/AF Colgate Esp.png',
        'KitchenAid': 'images/AF KitchenAid Esp.png',
        'Kraft': 'images/AF Kraft Esp.png',
        'Motorola': 'images/AF Motorola Esp.png',
        'Nestle': 'images/AF Nestle Esp.png',
        'P&G': 'images/AF P&G Esp.png',
        'Philip Morris': 'images/AF Philip Morris Esp.png',
        'Whirlpool': 'images/AF Whirlpool Esp.png'
    },
    'Ing': {
        'Generico': 'images/AF Generico Ing.png',
        'Claro': 'images/AF Claro Ing.png',
        'Colgate': 'images/AF Colgate Ing.png',
        'KitchenAid': 'images/AF KitchenAid Ing.png',
        'Kraft': 'images/AF Kraft Ing.png',
        'Motorola': 'images/AF Motorola Ing.png',
        'Nestle': 'images/AF Nestle Ing.png',
        'P&G': 'images/AF P&G Ing.png',
        'Philip Morris': 'images/AF Philip Morris Ing.png',
        'Whirlpool': 'images/AF Whirlpool Ing.png'
    }
};

// ── INYECTORES DINÁMICOS DE DEPENDENCIAS ──
function loadScript(src, globalKey) {
    return new Promise((resolve) => {
        if (window[globalKey]) return resolve(window[globalKey]);
        const s = document.createElement('script');
        s.src = src;
        s.onload = () => resolve(window[globalKey]);
        document.head.appendChild(s);
    });
}

export const getQRLib = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js', 'QRCode');
const getHtml2Canvas = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js', 'html2canvas');
export const getJSZip = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js', 'JSZip');
export const getXLSXLib = () => loadScript('https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js', 'XLSX');

export function convertDriveUrlToDirect(url) {
    if (!url) return '';

    if (!url.includes('drive.google.com') && !url.includes('docs.google.com')) {
        return url;
    }

    try {
        const regExp = /(?:https?:\/\/)?(?:drive\.google\.com\/)(?:file\/d\/|open\?id=)([\w-]+)/;
        const match = url.match(regExp);
        if (match && match[1]) {
            // Endpoint optimizado para saltar bloqueos pesados de descargas directas anónimas
            return `https://drive.google.com/thumbnail?id=${match[1]}&sz=w1000`;
        }
    } catch (e) {
        // ignore
    }
    return url;
}

export async function fetchImageAsBlob(url) {
    if (!url) return null;

    if (url.startsWith('blob:') || url.startsWith('data:')) {
        try {
            const response = await fetch(url);
            if (response.ok) return await response.blob();
        } catch (e) {
            // ignore
        }
        return null;
    }

    if (url.includes('drive.google.com') || url.includes('docs.google.com')) {
        try {
            const response = await fetch(url);
            if (response.ok) return await response.blob();
        } catch {
            // CORS blocked
        }
        return null;
    }

    try {
        const proxyUrl = `https://images.weserv.nl/?url=${encodeURIComponent(url)}&default=${encodeURIComponent(url)}`;
        const response = await fetch(proxyUrl);
        if (!response.ok) throw new Error("Error en respuesta de red proxy");
        return await response.blob();
    } catch (e) {
        try {
            const response = await fetch(url, { mode: 'cors' });
            return await response.blob();
        } catch {
            return null;
        }
    }
}

function preloadImage(src) {
    return new Promise((resolve) => {
        if (!src) return resolve(null);
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.onload = () => resolve(src);
        img.onerror = () => {
            const retryImg = new Image();
            retryImg.onload = () => resolve(src);
            retryImg.onerror = () => resolve(null);
            retryImg.src = src;
        };
        img.src = src;
    });
}

// ── GENERADOR DE QR NATIVO (Garantiza ID limpio en URL) ──
export async function renderQRCode(employeeId, canvasElement) {
    if (!canvasElement) return;
    const cleanId = (employeeId || '').replace(/[-\s]/g, '');
    const ctx = canvasElement.getContext('2d');
    ctx.clearRect(0, 0, canvasElement.width, canvasElement.height);

    if (cleanId.length <= 2) return;

    const QRCodeLib = await getQRLib();
    const tmp = document.createElement('div');
    tmp.style.display = 'none';
    document.body.appendChild(tmp);

    new QRCodeLib(tmp, {
        text: `http://localhost:5173/empleado-id/${cleanId}`,
        width: 55,
        height: 55,
        colorDark: '#000000',
        colorLight: '#ffffff',
        correctLevel: QRCodeLib.CorrectLevel.M
    });

    await new Promise((resolve) => setTimeout(resolve, 60));

    const img = tmp.querySelector('img') || tmp.querySelector('canvas');

    const drawIt = (src) => {
        return new Promise((res) => {
            const i = new Image();
            i.onload = () => {
                ctx.fillStyle = '#ffffff';
                ctx.fillRect(0, 0, 55, 55);
                ctx.drawImage(i, 0, 0, 55, 55);
                if (tmp.parentNode) document.body.removeChild(tmp);
                res();
            };
            i.src = src;
        });
    };

    if (img && img.tagName === 'CANVAS') {
        await drawIt(img.toDataURL());
    } else if (img) {
        if (img.complete) await drawIt(img.src);
        else {
            await new Promise((res) => {
                img.onload = async () => {
                    await drawIt(img.src);
                    res();
                };
            });
        }
    } else {
        if (tmp.parentNode) document.body.removeChild(tmp);
    }
}

// ── ENGINE DE PROCESAMIENTO INDIVIDUAL ──
export async function downloadIDCards(config) {
    const { name, role, selectedClient, language, photoSrc, baseUrl, qrCanvas, onStateChange } = config;

    if (onStateChange) onStateChange({ processing: true, text: 'Procesando...' });

    const html2canvasLib = await getHtml2Canvas();
    const cleanName = name.trim().replace(/\s+/g, '') || 'Empleado';

    const frontBgUrl = `${baseUrl}images/AF GLM Frente.png`;
    const currentGroup = clientTemplates[language] || clientTemplates['Esp'];
    const backBgFile = currentGroup[selectedClient] || 'images/AF Generico Esp.png';
    const backBgUrl = `${baseUrl}${backBgFile}`;

    const sandbox = document.createElement('div');
    sandbox.style.position = 'fixed';
    sandbox.style.top = '-9999px';
    sandbox.style.left = '-9999px';
    sandbox.style.width = '1400px';
    document.body.appendChild(sandbox);

    const cardStyleBase = `
        position: relative;
        width: 650px;
        height: 1004px;
        border-radius: 16px;
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        display: inline-block;
        margin-right: 50px;
        overflow: hidden;
        font-family: Arial, Helvetica, sans-serif;
    `;

    const vFront = document.createElement('div');
    vFront.style.cssText = cardStyleBase;
    vFront.style.backgroundImage = `url('${frontBgUrl}')`;

    let photoTagHtml = `
        <div style="width:100%; height:100%; background:#e1e9ee; display:flex; align-items:center; justify-content: center;">
            <svg style="width:100px; height:100px; opacity:0.3; color:#4F758B;" viewBox="0 0 28 28" fill="none"><circle cx="14" cy="10" r="5.5" stroke="currentColor" stroke-width="1.5"/><path d="M3 24c0-6 22-6 22 0" stroke="currentColor" stroke-width="1.5"/></svg>
        </div>
    `;

    if (photoSrc) {
        photoTagHtml = `<div style="width:100%; height:100%; background-image:url('${photoSrc}'); background-size:cover; background-position:center; background-repeat:no-repeat;"></div>`;
    }

    vFront.innerHTML = `
        <div style="position:absolute; top:260.5px; left:131.5px; width:384px; height:384px; border-radius:50%; overflow:hidden; z-index:5;">
            ${photoTagHtml}
        </div>
        <div style="position:absolute; top:715px; left:20px; right:20px; font-size:38px; font-weight:900; color:#FFFFFF; text-align:center; text-transform:uppercase; letter-spacing:1px; word-break:break-word; z-index:5;">
            ${name.toUpperCase() || 'NOMBRE APELLIDO'}
        </div>
        <div style="position:absolute; bottom:32px; right:15px; font-size:26px; font-weight:700; color:#6B8499; text-align:right; text-transform:uppercase; letter-spacing:1px; max-width:550px; white-space:nowrap; z-index:5;">
            ${role.toUpperCase() || 'PUESTO'}
        </div>
    `;

    const vBack = document.createElement('div');
    vBack.style.cssText = cardStyleBase;
    vBack.style.backgroundImage = `url('${backBgUrl}')`;

    const vQRZone = document.createElement('div');
    vQRZone.style.cssText = `position: absolute; bottom: 27px; right: 27px; background: #ffffff; padding: 11px; border-radius: 16px; display: flex; align-items: center; justify-content: center; z-index: 5;`;

    const vQRCanvas = document.createElement('canvas');
    vQRCanvas.width = 149;
    vQRCanvas.height = 149;
    vQRCanvas.style.width = '100px';
    vQRCanvas.style.height = '100px';
    const vQRContext = vQRCanvas.getContext('2d');

    if (vQRContext && qrCanvas) {
        vQRContext.imageSmoothingEnabled = false;
        vQRContext.drawImage(qrCanvas, 0, 0, 149, 149);
    }
    vQRZone.appendChild(vQRCanvas);
    vBack.appendChild(vQRZone);

    sandbox.appendChild(vFront);
    sandbox.appendChild(vBack);

    const renderOpts = { scale: 1, useCORS: true, allowTaint: false, backgroundColor: null, logging: false, width: 650, height: 1004 };

    try {
        const frontCanvas = await html2canvasLib(vFront, renderOpts);
        executeFileDownload(frontCanvas.toDataURL('image/png'), `${cleanName}Frente.png`);

        const backCanvas = await html2canvasLib(vBack, renderOpts);
        executeFileDownload(backCanvas.toDataURL('image/png'), `${cleanName}Reverso.png`);
    } catch (error) {
        // silent
    } finally {
        if (sandbox.parentNode) document.body.removeChild(sandbox);
        if (onStateChange) onStateChange({ processing: false, text: '⬇ Descargar' });
    }
}

// ── ENGINE MASIVO CON SOLUCIÓN TOTAL POR INYECCIÓN DE IMG CORS NATIVA ──
export async function downloadBulkIDCards({ employees, baseUrl, onStateChange, onProcessEmployeePhoto }) {
    if (onStateChange) onStateChange({ processing: true, text: 'Descargando...' });

    const html2canvasLib = await getHtml2Canvas();
    const JSZipLib = await getJSZip();
    const zip = new JSZipLib();

    const hiddenQRCanvas = document.createElement('canvas');
    hiddenQRCanvas.width = 55;
    hiddenQRCanvas.height = 55;

    const sandbox = document.createElement('div');
    sandbox.style.position = 'fixed';
    sandbox.style.top = '-9999px';
    sandbox.style.left = '-9999px';
    sandbox.style.width = '1400px';
    document.body.appendChild(sandbox);

    const cardStyleBase = `
        position: relative;
        width: 650px;
        height: 1004px;
        border-radius: 16px;
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        display: inline-block;
        overflow: hidden;
        font-family: Arial, Helvetica, sans-serif;
    `;

    const renderOpts = { scale: 1, useCORS: true, allowTaint: false, backgroundColor: null, logging: false, width: 650, height: 1004 };

    for (let i = 0; i < employees.length; i++) {
        const emp = employees[i];
        const currentClient = emp.selectedClient || 'Generico';
        const sanitizedEmpName = (emp.name || '').trim().replace(/[\\/:*?"<>|]/g, '-') || `Empleado_${i + 1}`;
        const sanitizedClientName = String(currentClient).trim().replace(/[\\/:*?"<>|]/g, '-');
        const folderName = `${sanitizedEmpName} - ${sanitizedClientName}`;

        const strictCleanId = String(emp.employeeId || '').replace(/[-\s]/g, '');

        await renderQRCode(strictCleanId, hiddenQRCanvas);

        const directDriveUrl = convertDriveUrlToDirect(emp.fotoUrl);
        let validatedPhotoUrl = null;

        if (directDriveUrl && strictCleanId) {
            try {
                const blobData = await fetchImageAsBlob(directDriveUrl);
                if (blobData) {
                    validatedPhotoUrl = URL.createObjectURL(blobData);
                    if (onProcessEmployeePhoto) {
                        await onProcessEmployeePhoto(strictCleanId, blobData, emp.selectedClient || '');
                    }
                }
            } catch (err) {
                // silent
            }
        }

        if (!validatedPhotoUrl && directDriveUrl) {
            validatedPhotoUrl = await preloadImage(directDriveUrl);
        }

        // --- Renderizar Frente Virtual ---
        const vFront = document.createElement('div');
        vFront.style.cssText = cardStyleBase;
        vFront.style.backgroundImage = `url('${baseUrl}images/AF GLM Frente.png')`;

        // CAMBIO ESTRATÉGICO AQUÍ: Usamos una etiqueta <img> HTML real con crossorigin explícito,
        // esto destruye el bloqueo "Anti-Taint" de los lienzos y obliga a html2canvas a procesar la foto de Drive.
        let photoTagHtml = `
            <div style="width:100%; height:100%; background:#e1e9ee; display:flex; align-items:center; justify-content: center;">
                <svg style="width:100px; height:100px; opacity:0.3; color:#4F758B;" viewBox="0 0 28 28" fill="none"><circle cx="14" cy="10" r="5.5" stroke="currentColor" stroke-width="1.5"/><path d="M3 24c0-6 22-6 22 0" stroke="currentColor" stroke-width="1.5"/></svg>
            </div>
        `;

        if (validatedPhotoUrl) {
            photoTagHtml = `<div style="width:100%; height:100%; background-image:url('${validatedPhotoUrl}'); background-size:cover; background-position:center; background-repeat:no-repeat;"></div>`;
        }

        vFront.innerHTML = `
            <div style="position:absolute; top:260.5px; left:131.5px; width:384px; height:384px; border-radius:50%; overflow:hidden; z-index:5;">
                ${photoTagHtml}
            </div>
            <div style="position:absolute; top:715px; left:20px; right:20px; font-size:38px; font-weight:900; color:#FFFFFF; text-align:center; text-transform:uppercase; letter-spacing:1px; word-break:break-word; z-index:5;">
                ${emp.name.toUpperCase()}
            </div>
            <div style="position:absolute; bottom:32px; right:15px; font-size:26px; font-weight:700; color:#6B8499; text-align:right; text-transform:uppercase; letter-spacing:1px; max-width:550px; white-space:nowrap; z-index:5;">
                ${emp.role.toUpperCase()}
            </div>
        `;
        sandbox.appendChild(vFront);

        // --- Renderizar Reverso Virtual ---
        const currentGroup = clientTemplates[emp.language] || clientTemplates['Esp'];
        const backBgFile = currentGroup[currentClient] || currentGroup['Generico'];
        const backBgUrl = `${baseUrl}${backBgFile}`;

        const vBack = document.createElement('div');
        vBack.style.cssText = cardStyleBase;
        vBack.style.backgroundImage = `url('${backBgUrl}')`;

        const vQRZone = document.createElement('div');
        vQRZone.style.cssText = `position: absolute; bottom: 27px; right: 27px; background: #ffffff; padding: 11px; border-radius: 16px; display: flex; align-items: center; justify-content: center; z-index: 5;`;

        const vQRCanvas = document.createElement('canvas');
        vQRCanvas.width = 149;
        vQRCanvas.height = 149;
        vQRCanvas.style.width = '100px';
        vQRCanvas.style.height = '100px';
        const vQRContext = vQRCanvas.getContext('2d');
        if (vQRContext) {
            vQRContext.imageSmoothingEnabled = false;
            vQRContext.drawImage(hiddenQRCanvas, 0, 0, 149, 149);
        }
        vQRZone.appendChild(vQRCanvas);
        vBack.appendChild(vQRZone);
        sandbox.appendChild(vBack);

        // Forzar un retraso mínimo de microsegundos para asegurar el render interno
        await new Promise((resolve) => setTimeout(resolve, 30));

        // Capturas gráficas del ZIP
        const frontCanvas = await html2canvasLib(vFront, renderOpts);
        const frontData = frontCanvas.toDataURL('image/png').split(',')[1];
        zip.file(`${folderName}/Frente.png`, frontData, { base64: true });

        const backCanvas = await html2canvasLib(vBack, renderOpts);
        const backData = backCanvas.toDataURL('image/png').split(',')[1];
        zip.file(`${folderName}/Reverso.png`, backData, { base64: true });

        if (validatedPhotoUrl && validatedPhotoUrl.startsWith('blob:')) {
            URL.revokeObjectURL(validatedPhotoUrl);
        }

        sandbox.removeChild(vFront);
        sandbox.removeChild(vBack);
    }

    if (sandbox.parentNode) document.body.removeChild(sandbox);

    const content = await zip.generateAsync({ type: 'blob' });
    const link = document.createElement('a');
    link.href = URL.createObjectURL(content);
    link.download = `Lote_Carnets_GLM.zip`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    if (onStateChange) onStateChange({ processing: false, text: '⬇ Descargar' });
}

function executeFileDownload(dataUrl, fileName) {
    const link = document.createElement('a');
    link.href = dataUrl;
    link.download = fileName;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
}