window.WebpImagePaster = window.WebpImagePaster || {};

window.WebpImagePaster.Processor = (function () {
    var Utils = window.WebpImagePaster.Utils;
    var __ = wp.i18n.__;

    function getMimeAndExtension(targetFormat) {
        var mimeType = 'image/webp';
        var extension = '.webp';

        if (targetFormat === 'png') {
            mimeType = 'image/png';
            extension = '.png';
        } else if (targetFormat === 'avif') {
            mimeType = 'image/avif';
            extension = '.avif';
        } else if (targetFormat === 'jpeg') {
            mimeType = 'image/jpeg';
            extension = '.jpg';
        } else if (targetFormat === 'gif') {
            mimeType = 'image/gif';
            extension = '.gif';
        } else if (targetFormat === 'svg') {
            mimeType = 'image/svg+xml';
            extension = '.svg';
        }

        return { mimeType: mimeType, extension: extension };
    }

    function generatePreview(blob, options, callback) {
        if (!blob) {
            return;
        }

        var width = options.width || 0;
        var quality = options.quality !== undefined ? options.quality : 85;
        var format = options.format || 'webp';
        var rawSourceFmt = Utils.getBlobFormat(blob);
        var detectedFormat = options.detectedFormat || rawSourceFmt;
        var keepOriginalIfLarger = options.keepOriginalIfLarger !== false;

        // 1. 원본 포맷(orig)에 너비 변경이 없는 경우 원본 Blob 즉시 반환
        if (format === 'orig' && width === 0) {
            var directUrl = URL.createObjectURL(blob);
            callback({
                url: directUrl,
                sizeText: Utils.formatFileSize(blob.size),
                blob: blob,
                isDirect: true
            });
            return;
        }

        var img = new Image();
        var objectUrl = URL.createObjectURL(blob);

        img.onerror = function () {
            URL.revokeObjectURL(objectUrl);
            callback({
                url: '',
                sizeText: '',
                error: __('Failed to load image.', 'webp-image-paster')
            });
        };

        img.onload = function () {
            var naturalW = img.width;
            var naturalH = img.height;
            var targetWidth = naturalW;
            var targetHeight = naturalH;

            if (width > 0) {
                targetWidth = width;
                targetHeight = Math.round((naturalH / naturalW) * targetWidth);
            }

            var canvas = document.createElement('canvas');
            canvas.width = targetWidth;
            canvas.height = targetHeight;

            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0, targetWidth, targetHeight);

            var decimalQuality = quality / 100;
            var previewMimeType = 'image/webp';

            if (format === 'png') {
                previewMimeType = 'image/png';
            } else if (format === 'avif') {
                previewMimeType = 'image/avif';
            } else if (format === 'orig') {
                if (detectedFormat === 'jpeg' || detectedFormat === 'jpg' || detectedFormat === 'heic' || detectedFormat === 'heif') {
                    previewMimeType = 'image/jpeg';
                } else if (detectedFormat === 'png') {
                    previewMimeType = 'image/png';
                } else if (detectedFormat === 'webp') {
                    previewMimeType = 'image/webp';
                } else if (detectedFormat === 'avif') {
                    previewMimeType = 'image/avif';
                } else if (rawSourceFmt === 'jpeg' || rawSourceFmt === 'jpg') {
                    previewMimeType = 'image/jpeg';
                } else if (rawSourceFmt === 'png') {
                    previewMimeType = 'image/png';
                }
            }

            canvas.toBlob(function (previewBlob) {
                URL.revokeObjectURL(objectUrl);
                if (previewBlob) {
                    // 용량 증가 방지 옵션 활성화 시:
                    // 변환 결과가 원본보다 크거나 같고 해상도가 확대되지 않은 경우 원본 유지
                    if (keepOriginalIfLarger && targetWidth <= naturalW && previewBlob.size >= blob.size) {
                        var origDirectUrl = URL.createObjectURL(blob);
                        var fmtLabel = rawSourceFmt ? rawSourceFmt.toUpperCase() + ' ' : '';
                        callback({
                            url: origDirectUrl,
                            sizeText: Utils.formatFileSize(blob.size) + ' (' + fmtLabel + __('Original kept: smaller size', 'webp-image-paster') + ')',
                            blob: blob,
                            convertedSizeText: Utils.formatFileSize(previewBlob.size),
                            isReverted: true
                        });
                        return;
                    }

                    var previewUrl = URL.createObjectURL(previewBlob);
                    callback({
                        url: previewUrl,
                        sizeText: Utils.formatFileSize(previewBlob.size),
                        blob: previewBlob
                    });
                } else {
                    callback({
                        url: '',
                        sizeText: __('Format not supported by browser', 'webp-image-paster'),
                        error: __('Format not supported by browser', 'webp-image-paster')
                    });
                }
            }, previewMimeType, decimalQuality);
        };

        img.src = objectUrl;
    }

    function generateMultiPreview(blobList, options, callback) {
        if (!blobList || blobList.length === 0) {
            callback({ thumbnails: [], totalSizeText: '0 KB', totalBytes: 0 });
            return;
        }

        var total = blobList.length;
        var completed = 0;
        var thumbnails = [];
        var totalBytes = 0;

        for (var i = 0; i < total; i++) {
            (function (idx, blob) {
                var rawSourceFmt = Utils.getBlobFormat(blob);
                generatePreview(blob, options, function (result) {
                    var itemSize = (result.blob ? result.blob.size : (blob ? blob.size : 0));
                    var isReverted = !!result.isReverted;
                    var formatBadge = '';

                    if (isReverted) {
                        formatBadge = (rawSourceFmt ? rawSourceFmt.toUpperCase() + ' ' : '') + __('Original kept', 'webp-image-paster');
                    } else if (options.format === 'orig') {
                        formatBadge = (rawSourceFmt ? rawSourceFmt.toUpperCase() : 'ORIG');
                    } else {
                        formatBadge = (options.format || 'webp').toUpperCase();
                    }

                    thumbnails[idx] = {
                        url: result.url,
                        name: blob.name || ('image-' + (idx + 1)),
                        sizeText: Utils.formatFileSize(itemSize),
                        formatBadge: formatBadge,
                        isReverted: isReverted,
                        bytes: itemSize
                    };

                    completed++;
                    if (completed === total) {
                        for (var k = 0; k < thumbnails.length; k++) {
                            totalBytes += (thumbnails[k] && thumbnails[k].bytes) ? thumbnails[k].bytes : 0;
                        }
                        callback({
                            thumbnails: thumbnails,
                            totalSizeText: Utils.formatFileSize(totalBytes),
                            totalBytes: totalBytes
                        });
                    }
                });
            })(i, blobList[i]);
        }
    }

    function processImage(blob, options, callback) {
        var rawSourceFmt = Utils.getBlobFormat(blob);
        var sourceFormat = rawSourceFmt || 'png';

        var targetFormat = options.format || 'webp';
        if (targetFormat === 'orig') {
            targetFormat = sourceFormat;
        }

        var formatMeta = getMimeAndExtension(targetFormat);
        var mimeType = formatMeta.mimeType;
        var extension = formatMeta.extension;

        var cleanName = Utils.sanitizeFileName(options.name) || 'image';
        var cleanAlt = Utils.sanitizeAltText(options.alt);

        var targetWidth = 0;
        if (options.width) {
            targetWidth = parseInt(options.width, 10);
            if (isNaN(targetWidth)) {
                targetWidth = 0;
            }
        }

        var allowUpscale = !!options.allowUpscale;
        var keepOriginalIfLarger = options.keepOriginalIfLarger !== false;

        // 1. SVG는 캔버스 래스터화 방지를 위해 무조건 원본 바이패스
        if (targetFormat === 'svg') {
            callback(blob, cleanName + '.svg', cleanAlt);
            return;
        }

        // 2. GIF 애니메이션이고 크기 변경이 없는 경우 원본 바이패스
        if (targetFormat === 'gif' && targetWidth === 0) {
            callback(blob, cleanName + '.gif', cleanAlt);
            return;
        }

        // 3. 너비가 0(Orig)인 경우:
        // 'orig' 선택 또는 원본 포맷 == 대상 포맷인 경우 품질 손실 없이 100% 원본 바이패스
        if (targetWidth === 0 && blob) {
            if (options.format === 'orig' || (rawSourceFmt && rawSourceFmt === targetFormat)) {
                var origExt = '.' + (rawSourceFmt === 'jpeg' ? 'jpg' : (rawSourceFmt || 'webp'));
                callback(blob, cleanName + origExt, cleanAlt);
                return;
            }
        }

        var img = new Image();
        var objectUrl = URL.createObjectURL(blob);

        img.onerror = function () {
            URL.revokeObjectURL(objectUrl);
            alert(__('Failed to load image.', 'webp-image-paster'));
        };

        img.onload = function () {
            var naturalW = img.width;
            var naturalH = img.height;
            var finalW = naturalW;
            var finalH = naturalH;

            var needsResize = false;
            if (targetWidth > 0) {
                if (allowUpscale || naturalW > targetWidth) {
                    var pW = targetWidth > 8000 ? 8000 : targetWidth;
                    finalW = pW;
                    finalH = Math.round((naturalH / naturalW) * pW);
                    needsResize = (finalW !== naturalW);
                }
            }

            // 만약 리사이징이 필요 없고, 원본 포맷과 대상 포맷이 같다면 -> 리인코딩 없이 100% 원본 바이패스 (품질 저하 방지)
            if (!needsResize && (options.format === 'orig' || (rawSourceFmt && rawSourceFmt === targetFormat))) {
                URL.revokeObjectURL(objectUrl);
                var keepExt = '.' + (rawSourceFmt === 'jpeg' ? 'jpg' : (rawSourceFmt || 'webp'));
                callback(blob, cleanName + keepExt, cleanAlt);
                return;
            }

            var canvas = document.createElement('canvas');
            canvas.width = finalW;
            canvas.height = finalH;

            var ctx = canvas.getContext('2d');
            ctx.drawImage(img, 0, 0, finalW, finalH);

            var finalQuality = options.quality !== undefined ? options.quality : 85;
            var decimalQuality = finalQuality / 100;

            canvas.toBlob(function (convertedBlob) {
                URL.revokeObjectURL(objectUrl);
                if (!convertedBlob) {
                    alert(__('Conversion failed. Your browser might not support encoding ', 'webp-image-paster') + targetFormat.toUpperCase());
                    return;
                }

                // [핵심] 용량 증가 방지 검사:
                // 변환 결과 파일 용량이 원본보다 크거나 같고 해상도가 확대되지 않은 경우 원본 파일 및 확장자 유지
                if (keepOriginalIfLarger && finalW <= naturalW && convertedBlob.size >= blob.size) {
                    var safeOrigExt = '.' + (rawSourceFmt === 'jpeg' ? 'jpg' : (rawSourceFmt || 'webp'));
                    callback(blob, cleanName + safeOrigExt, cleanAlt);
                    return;
                }

                callback(convertedBlob, cleanName + extension, cleanAlt);
            }, mimeType, decimalQuality);
        };

        img.src = objectUrl;
    }

    function processMultipleImages(blobList, options, callback) {
        if (!blobList || blobList.length === 0) {
            callback([]);
            return;
        }

        var results = [];
        var completedCount = 0;
        var total = blobList.length;

        for (var i = 0; i < total; i++) {
            (function (idx, blob) {
                var rawName = blob.name ? blob.name.replace(/\.[^/.]+$/, '') : ('image-' + (idx + 1));
                var cleanName = Utils.sanitizeFileName(rawName) || ('image-' + (idx + 1));
                var cleanAlt = rawName;

                processImage(blob, {
                    name: cleanName,
                    alt: cleanAlt,
                    width: options.width,
                    quality: options.quality,
                    format: options.format,
                    allowUpscale: options.allowUpscale,
                    keepOriginalIfLarger: options.keepOriginalIfLarger
                }, function (convertedBlob, finalFileName, finalAlt) {
                    results[idx] = {
                        blob: convertedBlob,
                        fileName: finalFileName,
                        altText: finalAlt
                    };
                    completedCount++;
                    if (completedCount === total) {
                        callback(results);
                    }
                });
            })(i, blobList[i]);
        }
    }

    return {
        getMimeAndExtension: getMimeAndExtension,
        generatePreview: generatePreview,
        generateMultiPreview: generateMultiPreview,
        processImage: processImage,
        processMultipleImages: processMultipleImages
    };
})();
