jQuery(document).ready(function($){
    var img = document.getElementById('img-crop');
    var i18n = window.CALLIOPE_SP_ADMIN_I18N || {};
    var MAX_OUTPUT_EDGE = 1600;
    var MAX_DATA_URL_LENGTH = 1800000;
    var INITIAL_JPEG_QUALITY = 0.84;
    var MIN_JPEG_QUALITY = 0.68;
    var cropState = {
        image: null,
        canvas: null,
        ctx: null,
        wrapper: null,
        controls: null,
        zoomInput: null,
        formatSelect: null,
        zoom: 1,
        offsetX: 0,
        offsetY: 0,
        dragging: false,
        startX: 0,
        startY: 0,
        startOffsetX: 0,
        startOffsetY: 0,
        originalSrc: '',
        sourceMime: 'image/jpeg'
    };

    function t(key, fallback) {
        return i18n[key] || fallback;
    }

    function normalizeHashtags(value) {
        var raw = String(value || '')
            .replace(/[\r\n\t,;]+/gu, ' ')
            .replace(/\s+/gu, ' ')
            .trim();

        if (!raw) {
            return '';
        }

        var parts = raw.split(' ');
        var normalized = [];
        var seen = {};

        parts.forEach(function(part){
            var tag = String(part || '')
                .replace(/^[#\s,;]+/gu, '')
                .replace(/[#\s,;]+$/gu, '')
                .replace(/[^\p{L}\p{M}\p{N}_]+/gu, '');

            if (!tag) {
                return;
            }

            var key = tag.toLocaleLowerCase();
            if (seen[key]) {
                return;
            }

            seen[key] = true;
            normalized.push('#' + tag);
        });

        return normalized.join(' ');
    }

    function updateHashtagPreview() {
        var input = document.getElementById('calliope_sp_hashtags');
        var hint = document.getElementById('calliope_sp_hashtags_preview_hint');
        if (!input || !hint) {
            return;
        }

        var normalized = normalizeHashtags(input.value);
        if (!normalized) {
            hint.style.display = 'none';
            hint.textContent = '';
            return;
        }

        hint.style.display = 'block';
        hint.textContent = t('hashtagsPreviewLabel', 'Normalized hashtags preview:') + ' ' + normalized;
    }

    function getSelectedFormat() {
        if (!cropState.formatSelect) {
            cropState.formatSelect = document.getElementById('calliope_sp_image_format');
        }

        return cropState.formatSelect ? String(cropState.formatSelect.value || 'original') : 'original';
    }

    function getFormatConfig() {
        var format = getSelectedFormat();
        var image = cropState.image;

        if (format === 'square') {
            return {
                mode: 'crop',
                ratioLabel: '1 / 1',
                ratioValue: 1,
                outputWidth: 1080,
                outputHeight: 1080
            };
        }

        if (format === 'portrait') {
            return {
                mode: 'crop',
                ratioLabel: '4 / 5',
                ratioValue: 4 / 5,
                outputWidth: 1080,
                outputHeight: 1350
            };
        }

        if (format === 'landscape') {
            return {
                mode: 'crop',
                ratioLabel: '16 / 9',
                ratioValue: 16 / 9,
                outputWidth: 1600,
                outputHeight: 900
            };
        }

        var width = image && image.naturalWidth ? image.naturalWidth : 4;
        var height = image && image.naturalHeight ? image.naturalHeight : 5;
        var scale = Math.min(1, MAX_OUTPUT_EDGE / Math.max(width, height));

        return {
            mode: 'original',
            ratioLabel: width + ' / ' + height,
            ratioValue: width / height,
            outputWidth: Math.max(1, Math.round(width * scale)),
            outputHeight: Math.max(1, Math.round(height * scale))
        };
    }

    function isCropMode() {
        return getFormatConfig().mode === 'crop';
    }

    function syncWrapperAspectRatio() {
        if (!cropState.wrapper) {
            return;
        }

        cropState.wrapper.style.aspectRatio = getFormatConfig().ratioLabel;
    }

    function syncCropControls() {
        if (!cropState.controls) {
            cropState.controls = document.getElementById('calliope-sp-native-crop-controls');
        }

        if (!cropState.controls) {
            return;
        }

        cropState.controls.style.display = isCropMode() ? 'flex' : 'none';
        cropState.wrapper.classList.toggle('is-dragging', false);

        if (!isCropMode()) {
            cropState.zoom = 1;
            cropState.offsetX = 0;
            cropState.offsetY = 0;
            cropState.dragging = false;
            if (cropState.zoomInput) {
                cropState.zoomInput.value = '1';
            }
        }
    }

    function getOutputMime() {
        // Always send a compact JPEG to avoid huge admin POST payloads and
        // to keep Meta/Threads/Instagram media URLs simple and widely accepted.
        return 'image/jpeg';
    }

    function clearImageState(options){
        options = options || {};

        cropState.image = null;
        cropState.zoom = 1;
        cropState.offsetX = 0;
        cropState.offsetY = 0;
        cropState.dragging = false;
        cropState.originalSrc = '';
        cropState.sourceMime = 'image/jpeg';

        if (cropState.ctx && cropState.canvas) {
            cropState.ctx.clearRect(0, 0, cropState.canvas.width, cropState.canvas.height);
            cropState.canvas.removeAttribute('width');
            cropState.canvas.removeAttribute('height');
            cropState.canvas.style.width = '';
            cropState.canvas.style.height = '';
        }
        if (cropState.zoomInput) {
            cropState.zoomInput.value = '1';
        }
        if (cropState.wrapper) {
            cropState.wrapper.classList.remove('is-dragging');
        }

        $('#img-crop').attr('src', '');
        $('#final-img').attr('src', '').removeAttr('srcset');
        $('#calliope_sp_data').val('').trigger('change');
        $('#edit-area').hide();
        $('#preview').hide();
        $('#btn-up, #btn-local').show();
        $('#file-input').val('');

        if (options.clearAltText) {
            $('#calliope_sp_alt_text').val('');
        }

        try {
            localStorage.removeItem('calliope_sp_cropped_image_data');
            localStorage.removeItem('calliope_sp_image_format');
        } catch(e) {}
    }

    function setupNativeCropper(){
        var wrapper = document.querySelector('.cropper-wrapper');
        if (!wrapper) {
            return;
        }

        cropState.wrapper = wrapper;
        cropState.formatSelect = document.getElementById('calliope_sp_image_format');
        img.style.display = 'none';

        var canvas = document.getElementById('calliope-sp-native-crop-canvas');
        if (!canvas) {
            canvas = document.createElement('canvas');
            canvas.id = 'calliope-sp-native-crop-canvas';
            canvas.setAttribute('aria-label', 'Image crop preview');
            wrapper.appendChild(canvas);
        }

        cropState.canvas = canvas;
        cropState.ctx = canvas.getContext('2d');

        var controls = document.getElementById('calliope-sp-native-crop-controls');
        if (!controls) {
            controls = document.createElement('div');
            controls.id = 'calliope-sp-native-crop-controls';
            controls.className = 'calliope-sp-native-crop-controls';
            controls.innerHTML = '<label for="calliope-sp-native-crop-zoom">Zoom</label><input id="calliope-sp-native-crop-zoom" type="range" min="1" max="3" step="0.01" value="1" /><button type="button" class="button" id="calliope-sp-native-crop-reset">Fit image</button>';
            wrapper.insertAdjacentElement('afterend', controls);
        }

        cropState.controls = controls;
        cropState.zoomInput = document.getElementById('calliope-sp-native-crop-zoom');

        cropState.zoomInput.addEventListener('input', function(){
            if (!isCropMode()) {
                this.value = '1';
                return;
            }

            cropState.zoom = parseFloat(this.value) || 1;
            constrainCrop();
            drawCropPreview();
        });

        var resetButton = document.getElementById('calliope-sp-native-crop-reset');
        if (resetButton) {
            resetButton.addEventListener('click', function(){
                cropState.zoom = 1;
                cropState.offsetX = 0;
                cropState.offsetY = 0;
                cropState.zoomInput.value = '1';
                drawCropPreview();
            });
        }

        canvas.addEventListener('pointerdown', function(event){
            if (!cropState.image || !isCropMode()) {
                return;
            }
            cropState.dragging = true;
            cropState.startX = event.clientX;
            cropState.startY = event.clientY;
            cropState.startOffsetX = cropState.offsetX;
            cropState.startOffsetY = cropState.offsetY;
            canvas.setPointerCapture(event.pointerId);
            wrapper.classList.add('is-dragging');
        });

        canvas.addEventListener('pointermove', function(event){
            if (!cropState.dragging || !isCropMode()) {
                return;
            }
            cropState.offsetX = cropState.startOffsetX + event.clientX - cropState.startX;
            cropState.offsetY = cropState.startOffsetY + event.clientY - cropState.startY;
            constrainCrop();
            drawCropPreview();
        });

        function endDrag(event){
            if (!cropState.dragging) {
                return;
            }
            cropState.dragging = false;
            try { canvas.releasePointerCapture(event.pointerId); } catch(e) {}
            wrapper.classList.remove('is-dragging');
        }

        canvas.addEventListener('pointerup', endDrag);
        canvas.addEventListener('pointercancel', endDrag);
        canvas.addEventListener('pointerleave', endDrag);

        if (cropState.formatSelect) {
            cropState.formatSelect.addEventListener('change', function(){
                syncWrapperAspectRatio();
                syncCropControls();
                constrainCrop();
                drawCropPreview();
            });
        }

        window.addEventListener('resize', function(){
            if (!cropState.image) {
                return;
            }
            syncWrapperAspectRatio();
            constrainCrop();
            drawCropPreview();
        });

        syncWrapperAspectRatio();
        syncCropControls();
    }

    function getCanvasSize(){
        var wrapper = cropState.wrapper;
        var width = wrapper ? wrapper.clientWidth : 360;
        var height = wrapper ? wrapper.clientHeight : 450;

        if (!height || height < 1) {
            var config = getFormatConfig();
            if (config.ratioValue > 0) {
                height = Math.round(width / config.ratioValue);
            }
        }

        return {
            width: Math.max(240, width),
            height: Math.max(240, height || 240)
        };
    }

    function getDrawData(size){
        var image = cropState.image;
        var coverScale = Math.max(size.width / image.naturalWidth, size.height / image.naturalHeight);
        var scale = coverScale * cropState.zoom;
        var drawWidth = image.naturalWidth * scale;
        var drawHeight = image.naturalHeight * scale;

        return {
            scale: scale,
            drawWidth: drawWidth,
            drawHeight: drawHeight,
            drawX: (size.width - drawWidth) / 2 + cropState.offsetX,
            drawY: (size.height - drawHeight) / 2 + cropState.offsetY
        };
    }

    function constrainCrop(){
        if (!cropState.image) {
            return;
        }

        if (!isCropMode()) {
            cropState.zoom = 1;
            cropState.offsetX = 0;
            cropState.offsetY = 0;
            return;
        }

        var size = getCanvasSize();
        var draw = getDrawData(size);
        var maxX = Math.max(0, (draw.drawWidth - size.width) / 2);
        var maxY = Math.max(0, (draw.drawHeight - size.height) / 2);

        cropState.offsetX = Math.min(maxX, Math.max(-maxX, cropState.offsetX));
        cropState.offsetY = Math.min(maxY, Math.max(-maxY, cropState.offsetY));
    }

    function drawCropPreview(){
        if (!cropState.canvas || !cropState.ctx || !cropState.image) {
            return;
        }

        syncWrapperAspectRatio();
        syncCropControls();

        var size = getCanvasSize();
        var ratio = window.devicePixelRatio || 1;
        var canvas = cropState.canvas;
        var ctx = cropState.ctx;

        canvas.width = Math.round(size.width * ratio);
        canvas.height = Math.round(size.height * ratio);
        canvas.style.width = size.width + 'px';
        canvas.style.height = size.height + 'px';

        ctx.setTransform(ratio, 0, 0, ratio, 0, 0);
        ctx.clearRect(0, 0, size.width, size.height);
        ctx.fillStyle = '#f8faff';
        ctx.fillRect(0, 0, size.width, size.height);

        var draw = getDrawData(size);
        ctx.drawImage(cropState.image, draw.drawX, draw.drawY, draw.drawWidth, draw.drawHeight);

        if (isCropMode()) {
            ctx.save();
            ctx.strokeStyle = 'rgba(255,255,255,0.85)';
            ctx.lineWidth = 1;
            ctx.setLineDash([4, 4]);
            ctx.beginPath();
            ctx.moveTo(size.width / 3, 0);
            ctx.lineTo(size.width / 3, size.height);
            ctx.moveTo((size.width / 3) * 2, 0);
            ctx.lineTo((size.width / 3) * 2, size.height);
            ctx.moveTo(0, size.height / 3);
            ctx.lineTo(size.width, size.height / 3);
            ctx.moveTo(0, (size.height / 3) * 2);
            ctx.lineTo(size.width, (size.height / 3) * 2);
            ctx.stroke();
            ctx.restore();
        }
    }

    function startCropping(src, options){
        options = options || {};
        setupNativeCropper();

        $('#btn-up, #btn-local').hide();
        $('#edit-area').show();
        $('#preview').hide();

        cropState.originalSrc = String(src || '');
        cropState.sourceMime = String(options.mime || '').toLowerCase() || 'image/jpeg';

        if (cropState.sourceMime.indexOf('image/') !== 0 && /^data:image\//i.test(cropState.originalSrc)) {
            cropState.sourceMime = cropState.originalSrc.replace(/^data:([^;]+);.*$/i, '$1').toLowerCase();
        }

        var image = new Image();
        image.onload = function(){
            cropState.image = image;
            cropState.zoom = 1;
            cropState.offsetX = 0;
            cropState.offsetY = 0;
            if (cropState.zoomInput) {
                cropState.zoomInput.value = '1';
            }
            syncWrapperAspectRatio();
            syncCropControls();
            drawCropPreview();
        };
        image.onerror = function(){
            alert(t('imageLoadFailed', 'The selected image could not be loaded.'));
            clearImageState();
        };
        image.src = src;
        img.src = src;
    }

    function buildFinalCanvas(){
        if (!cropState.image) {
            return null;
        }

        var config = getFormatConfig();
        var output = document.createElement('canvas');
        var ctx = output.getContext('2d');

        if (!ctx) {
            return null;
        }

        if (!isCropMode()) {
            output.width = config.outputWidth;
            output.height = config.outputHeight;
            ctx.fillStyle = '#ffffff';
            ctx.fillRect(0, 0, output.width, output.height);
            ctx.drawImage(cropState.image, 0, 0, output.width, output.height);
            return output;
        }

        var size = getCanvasSize();
        var draw = getDrawData(size);
        var scaleX = config.outputWidth / size.width;
        var scaleY = config.outputHeight / size.height;

        output.width = config.outputWidth;
        output.height = config.outputHeight;
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(0, 0, output.width, output.height);
        ctx.drawImage(
            cropState.image,
            draw.drawX * scaleX,
            draw.drawY * scaleY,
            draw.drawWidth * scaleX,
            draw.drawHeight * scaleY
        );

        return output;
    }

    function cloneScaledCanvas(sourceCanvas, scale) {
        var scaled = document.createElement('canvas');
        var scaledCtx = scaled.getContext('2d');
        if (!scaledCtx) {
            return null;
        }

        scaled.width = Math.max(1, Math.round(sourceCanvas.width * scale));
        scaled.height = Math.max(1, Math.round(sourceCanvas.height * scale));
        scaledCtx.fillStyle = '#ffffff';
        scaledCtx.fillRect(0, 0, scaled.width, scaled.height);
        scaledCtx.drawImage(sourceCanvas, 0, 0, scaled.width, scaled.height);
        return scaled;
    }

    function buildFinalImageData(){
        var canvas = buildFinalCanvas();
        if (!canvas) {
            return '';
        }

        var mime = getOutputMime();

        try {
            var workingCanvas = canvas;
            var quality = INITIAL_JPEG_QUALITY;
            var dataURL = workingCanvas.toDataURL(mime, quality);
            var attempts = 0;

            while (dataURL && dataURL.length > MAX_DATA_URL_LENGTH && attempts < 8) {
                attempts++;

                if (quality > MIN_JPEG_QUALITY) {
                    quality = Math.max(MIN_JPEG_QUALITY, quality - 0.08);
                } else {
                    var smaller = cloneScaledCanvas(workingCanvas, 0.85);
                    if (!smaller) {
                        break;
                    }
                    workingCanvas = smaller;
                }

                dataURL = workingCanvas.toDataURL(mime, quality);
            }

            if (dataURL && dataURL.length > MAX_DATA_URL_LENGTH) {
                return '';
            }

            return dataURL || '';
        } catch (error) {
            return '';
        }
    }

    function storeFinalImageData(dataURL, options){
        options = options || {};

        if (!dataURL) {
            return false;
        }

        $('#calliope_sp_data').val(dataURL).trigger('change');

        if (options.updatePreview) {
            $('#final-img').attr('src', dataURL);
        }

        if (options.persist) {
            try {
                if (dataURL.length <= 500000) {
                    localStorage.setItem('calliope_sp_cropped_image_data', dataURL);
                } else {
                    localStorage.removeItem('calliope_sp_cropped_image_data');
                }
            } catch(e) {}
        }

        return true;
    }

    function syncSelectedImageForPublish(){
        if (!cropState.image) {
            return true;
        }

        var dataURL = buildFinalImageData();
        if (!dataURL) {
            alert(t('imageExportFailed', 'The selected image could not be prepared. Please click Apply crop or choose another image before publishing.'));
            return false;
        }

        return storeFinalImageData(dataURL, {
            persist: true,
            updatePreview: false
        });
    }

    var params = new URLSearchParams(window.location.search);
    if (params.get('calliope_sp_published') === '1' || params.get('calliope_sp_clear_image') === '1') {
        clearImageState({ clearAltText: true });
    } else {
        try {
            var saved = localStorage.getItem('calliope_sp_cropped_image_data');
            if (saved) {
                $('#final-img').attr('src', saved);
                $('#calliope_sp_data').val(saved);
                $('#preview').show();
                $('#btn-up, #btn-local').show();
            }
        } catch(e) {}
    }

    setupNativeCropper();
    updateHashtagPreview();

    $('#calliope_sp_hashtags').on('blur change', function(){
        var normalized = normalizeHashtags($(this).val());
        if (normalized) {
            $(this).val(normalized);
        }
        updateHashtagPreview();
    }).on('input', function(){
        updateHashtagPreview();
    });

    $('#btn-up').on('click', function(e){
        e.preventDefault();

        var frame = wp.media({
            title: t('selectImage', 'Select image'),
            multiple: false
        });

        frame.on('select', function(){
            var attachment = frame.state().get('selection').first().toJSON();
            if (attachment && attachment.alt !== undefined) {
                $('#calliope_sp_alt_text').val(attachment.alt);
            }
            startCropping(attachment.url, {
                mime: attachment.mime || ''
            });
        });

        frame.open();
    });

    $('#btn-local').on('click', function(){
        $('#file-input').trigger('click');
    });

    $('#file-input').on('change', function(e){
        var file = e.target.files && e.target.files[0];
        if (!file) return;

        var reader = new FileReader();
        reader.onload = function(ev){
            startCropping(ev.target.result, {
                mime: file.type || ''
            });
        };
        reader.readAsDataURL(file);
    });

    $('#btn-ok').on('click', function(){
        var dataURL = buildFinalImageData();
        if (!dataURL) {
            alert(t('imageExportFailed', 'The selected image could not be prepared. Please choose another image and try again.'));
            return;
        }

        storeFinalImageData(dataURL, {
            persist: true,
            updatePreview: true
        });

        $('#edit-area').hide();
        $('#preview').show();
        $('#btn-up, #btn-local').show();
    });

    $(document).on('submit', '#calliope_sp_publish_form', function(event){
        if (!syncSelectedImageForPublish()) {
            event.preventDefault();
            event.stopImmediatePropagation();
            return false;
        }

        return true;
    });

    $(document).on('click', '#btn-del', function(event){
        event.preventDefault();
        event.stopPropagation();
        clearImageState({ clearAltText: true });
        return false;
    });

    document.addEventListener('click', function(event){
        var target = event.target;
        if (!target || !target.closest) {
            return;
        }

        var removeButton = target.closest('#btn-del');
        if (!removeButton) {
            return;
        }

        event.preventDefault();
        event.stopPropagation();
        clearImageState({ clearAltText: true });
    }, true);
});
