(() => {
    'use strict';

    const DEFAULTS = {
        maxDimension: 1600,
        targetBytes: 700 * 1024,
        initialQuality: 0.86,
        minQuality: 0.50,
    };

    function isCompressibleImage(file) {
        return file instanceof File
            && /^image\/(jpeg|png|webp)$/i.test(file.type || '')
            && !/\.gif$/i.test(file.name || '');
    }

    function fileNameForType(name, mime) {
        const base = String(name || 'imagem').replace(/\.[^.]+$/, '');
        if (mime === 'image/webp') return `${base}.webp`;
        if (mime === 'image/png') return `${base}.png`;
        return `${base}.jpg`;
    }

    async function loadBitmap(file) {
        if ('createImageBitmap' in window) {
            try {
                return await createImageBitmap(file, { imageOrientation: 'from-image' });
            } catch (_) {
                return await createImageBitmap(file);
            }
        }
        return await new Promise((resolve, reject) => {
            const image = new Image();
            const objectUrl = URL.createObjectURL(file);
            image.onload = () => {
                URL.revokeObjectURL(objectUrl);
                resolve(image);
            };
            image.onerror = () => {
                URL.revokeObjectURL(objectUrl);
                reject(new Error('Não foi possível preparar esta imagem.'));
            };
            image.src = objectUrl;
        });
    }

    function canvasBlob(canvas, type, quality) {
        return new Promise((resolve, reject) => {
            canvas.toBlob(blob => blob ? resolve(blob) : reject(new Error('Não foi possível reduzir a imagem.')), type, quality);
        });
    }

    async function compressFile(file, options = {}) {
        if (!isCompressibleImage(file)) return file;

        const settings = { ...DEFAULTS, ...options };
        const bitmap = await loadBitmap(file);
        const originalWidth = bitmap.width || bitmap.naturalWidth || 0;
        const originalHeight = bitmap.height || bitmap.naturalHeight || 0;
        if (!originalWidth || !originalHeight) return file;

        let scale = Math.min(1, settings.maxDimension / Math.max(originalWidth, originalHeight));
        let width = Math.max(1, Math.round(originalWidth * scale));
        let height = Math.max(1, Math.round(originalHeight * scale));
        const outputType = file.type === 'image/png' ? 'image/webp' : (file.type === 'image/webp' ? 'image/webp' : 'image/jpeg');
        let bestBlob = null;

        for (let resizePass = 0; resizePass < 4; resizePass++) {
            const canvas = document.createElement('canvas');
            canvas.width = width;
            canvas.height = height;
            const context = canvas.getContext('2d', { alpha: outputType !== 'image/jpeg' });
            if (!context) return file;
            if (outputType === 'image/jpeg') {
                context.fillStyle = '#ffffff';
                context.fillRect(0, 0, width, height);
            }
            context.imageSmoothingEnabled = true;
            context.imageSmoothingQuality = 'high';
            context.drawImage(bitmap, 0, 0, width, height);

            for (let quality = settings.initialQuality; quality >= settings.minQuality; quality -= 0.08) {
                const blob = await canvasBlob(canvas, outputType, quality);
                bestBlob = blob;
                if (blob.size <= settings.targetBytes) break;
            }
            if (bestBlob && bestBlob.size <= settings.targetBytes) break;
            if (width <= 480 && height <= 480) break;
            width = Math.max(320, Math.round(width * 0.82));
            height = Math.max(320, Math.round(height * 0.82));
        }

        if (bitmap && typeof bitmap.close === 'function') bitmap.close();
        if (!bestBlob || (bestBlob.size >= file.size && file.size <= settings.targetBytes)) return file;
        return new File([bestBlob], fileNameForType(file.name, outputType), {
            type: outputType,
            lastModified: Date.now(),
        });
    }

    async function prepareInput(input, options = {}) {
        const file = input?.files?.[0];
        if (!file || !isCompressibleImage(file)) return file || null;
        const compressed = await compressFile(file, options);
        if (compressed !== file && typeof DataTransfer !== 'undefined') {
            const transfer = new DataTransfer();
            transfer.items.add(compressed);
            input.files = transfer.files;
            input.dataset.originalSize = String(file.size);
            input.dataset.compressedSize = String(compressed.size);
        }
        return compressed;
    }

    window.CFCImageTools = { compressFile, prepareInput };

    function imageInputsForForm(form) {
        return [...form.querySelectorAll('input[type="file"]')].filter(input => {
            if (input.dataset.noImageCompression === '1') return false;
            const file = input.files?.[0];
            return !!file && isCompressibleImage(file);
        });
    }

    document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll('form:not([data-image-compression="manual"]):not([data-image-compression="off"])').forEach(form => {
            if (form.id === 'videoLessonForm') return;
            form.addEventListener('submit', async event => {
                if (form.dataset.cfcImageProcessed === '1' || form.dataset.cfcImageProcessing === '1') return;
                const inputs = imageInputsForForm(form);
                if (!inputs.length) return;

                event.preventDefault();
                form.dataset.cfcImageProcessing = '1';
                const buttons = [...form.querySelectorAll('button[type="submit"], input[type="submit"]')];
                const oldStates = buttons.map(button => ({ button, disabled: button.disabled, text: button.tagName === 'BUTTON' ? button.innerHTML : button.value }));
                buttons.forEach(button => {
                    button.disabled = true;
                    if (button.tagName === 'BUTTON') button.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Preparando imagem...';
                });

                try {
                    for (const input of inputs) await prepareInput(input);
                    form.dataset.cfcImageProcessed = '1';
                    HTMLFormElement.prototype.submit.call(form);
                } catch (error) {
                    delete form.dataset.cfcImageProcessing;
                    oldStates.forEach(({ button, disabled, text }) => {
                        button.disabled = disabled;
                        if (button.tagName === 'BUTTON') button.innerHTML = text;
                        else button.value = text;
                    });
                    alert(error?.message || 'Não foi possível preparar a imagem para envio.');
                }
            }, true);
        });

        const overlay = document.createElement('div');
        overlay.className = 'cfc-image-viewer';
        overlay.setAttribute('aria-hidden', 'true');
        overlay.innerHTML = '<button type="button" class="cfc-image-viewer-close" aria-label="Fechar"><i class="bi bi-x-lg"></i></button><div class="cfc-image-viewer-stage"><img alt="Imagem ampliada"><div class="cfc-image-viewer-caption"></div></div>';
        document.body.appendChild(overlay);
        const viewerImage = overlay.querySelector('img');
        const viewerCaption = overlay.querySelector('.cfc-image-viewer-caption');
        let viewerHistoryEntry = false;

        function closeViewer(fromHistory = false) {
            overlay.classList.remove('is-open');
            overlay.setAttribute('aria-hidden', 'true');
            viewerImage.removeAttribute('src');
            document.body.classList.remove('cfc-image-viewer-open');
            if (viewerHistoryEntry) {
                viewerHistoryEntry = false;
                if (!fromHistory && history.state && history.state.cfcImageViewer) history.back();
            }
        }

        function openViewer(image) {
            const source = image.currentSrc || image.src;
            if (!source) return;
            viewerImage.src = source;
            viewerImage.alt = image.alt || 'Imagem ampliada';
            viewerCaption.textContent = image.alt || '';
            if (!overlay.classList.contains('is-open')) {
                try {
                    history.pushState({ ...(history.state || {}), cfcImageViewer: true }, '', location.href);
                    viewerHistoryEntry = true;
                } catch (_) {}
            }
            overlay.classList.add('is-open');
            overlay.setAttribute('aria-hidden', 'false');
            document.body.classList.add('cfc-image-viewer-open');
            overlay.querySelector('.cfc-image-viewer-close').focus();
        }

        const previewSelector = 'main img:not(.access-home-logo):not(.hero-vehicle)';
        document.querySelectorAll(previewSelector).forEach(image => {
            image.classList.add('cfc-image-previewable');
            image.setAttribute('tabindex', '0');
            image.setAttribute('role', 'button');
            image.setAttribute('aria-label', `${image.alt || 'Imagem'} — toque para ampliar`);
        });

        document.addEventListener('click', event => {
            const image = event.target.closest?.(previewSelector);
            if (!image) return;
            event.preventDefault();
            event.stopPropagation();
            openViewer(image);
        }, true);
        document.addEventListener('keydown', event => {
            if (event.key === 'Escape' && overlay.classList.contains('is-open')) closeViewer();
            if ((event.key === 'Enter' || event.key === ' ') && event.target.matches?.(previewSelector)) {
                event.preventDefault();
                openViewer(event.target);
            }
        });
        overlay.addEventListener('click', event => {
            if (event.target === overlay || event.target.closest('.cfc-image-viewer-close')) closeViewer();
        });
        window.addEventListener('popstate', () => {
            if (overlay.classList.contains('is-open')) closeViewer(true);
        });
    });
})();
