/* global jQuery, askagentoAiSearchImageAdmin */
(function ($) {
    'use strict';

    function escapeHtml(value) {
        return $('<div>').text(value == null ? '' : String(value)).html();
    }

    function normCatalogTitleRough(value) {
        if (value == null) {
            return '';
        }
        return String(value)
            .replace(/<[^>]*>/gi, '')
            .replace(/\s+/g, ' ')
            .trim()
            .toLowerCase();
    }

    function stripSampleFromResultRows(rows, sample, skuNorm, guidNorm, titleNorm, minFiniteDist) {
        if (!Array.isArray(rows)) {
            return [];
        }

        var sku = (skuNorm || '').trim().toLowerCase();
        var guid = (guidNorm || '').trim().toLowerCase();
        var titleN = normCatalogTitleRough(titleNorm || '');
        var minParsed = minFiniteDist == null ? NaN : Number(minFiniteDist);
        var minD = Number.isFinite(minParsed) ? minParsed : null;
        var epsilon = 1e-4;
        var sid = sample && sample.product_id != null ? Number(sample.product_id, 10) : NaN;

        return rows.filter(function (row) {
            var rid = row.product_id != null ? Number(row.product_id, 10) : NaN;

            if (Number.isFinite(sid) && Number.isFinite(rid) && rid === sid) {
                return false;
            }

            if (sku) {
                var rk = row.sku != null ? String(row.sku).trim().toLowerCase() : '';

                if (rk !== '' && rk === sku) {
                    return false;
                }
            }

            if (guid) {
                var rg =
                    row.global_unique_id != null ? String(row.global_unique_id).trim().toLowerCase() : '';

                if (rg !== '' && rg === guid) {
                    return false;
                }
            }

            if (minD !== null && titleN) {
                var rt = normCatalogTitleRough(row.title);
                var rd =
                    row.distance != null && Number.isFinite(Number(row.distance))
                        ? Number(row.distance)
                        : null;

                if (rd !== null && rt !== '' && rt === titleN && Math.abs(rd - minD) <= epsilon) {
                    return false;
                }
            }

            return true;
        });
    }

    /**
     * Cover+center-crop to a square in the browser before POST /search (matches API query image size).
     *
     * @returns {Promise<string>} JPEG data URL (image/jpeg;base64,...).
     */
    function jpegDataUrlFromFile(file, squareSide, quality) {
        if (!(file instanceof File) || typeof squareSide !== 'number' || squareSide < 64 || typeof quality !== 'number') {
            return Promise.reject(new Error('bad_args'));
        }

        var blobUrl = URL.createObjectURL(file);

        return new Promise(function (resolve, reject) {
            var img = new Image();

            img.onload = function () {
                var w = img.naturalWidth || img.width || 0;
                var h = img.naturalHeight || img.height || 0;

                if (!w || !h) {
                    reject(new Error('no_dimensions'));

                    return;
                }

                var S = squareSide;
                var scale = Math.max(S / w, S / h);
                var crop = S / scale;
                var sx = Math.max(0, (w - crop) / 2);
                var sy = Math.max(0, (h - crop) / 2);
                var canvas = document.createElement('canvas');

                canvas.width = S;
                canvas.height = S;

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

                if (!ctx) {
                    reject(new Error('no_canvas'));

                    return;
                }

                ctx.drawImage(img, sx, sy, crop, crop, 0, 0, S, S);

                try {
                    resolve(canvas.toDataURL('image/jpeg', quality));
                } catch (eCanvas) {
                    reject(eCanvas);
                }
            };

            img.onerror = function () {
                reject(new Error('img_error'));
            };

            img.src = blobUrl;
        }).then(
            function (dataUrl) {
                URL.revokeObjectURL(blobUrl);

                return dataUrl;
            },
            function (err) {
                URL.revokeObjectURL(blobUrl);

                throw err;
            }
        );
    }

    function minFiniteDistanceFromRows(rows) {
        if (!Array.isArray(rows)) {
            return null;
        }

        var best = null;

        rows.forEach(function (row) {
            var d = row.distance != null ? Number(row.distance) : NaN;

            if (Number.isFinite(d)) {
                best = best === null ? d : Math.min(best, d);
            }
        });

        return best;
    }

    /**
     * @returns {Promise<object[]>}
     */
    async function fetchAskagentoImageSearchFromB64(b64, limit) {
        var locI18n = askagentoAiSearchImageAdmin.i18n || {};

        if (!askagentoAiSearchImageAdmin.searchUrl || !askagentoAiSearchImageAdmin.siteId) {
            throw new Error(locI18n.directSearchUnavailable || '');
        }

        if (!askagentoAiSearchImageAdmin.apiKey) {
            throw new Error(locI18n.missingDiscoveryApiKey || locI18n.directSearchUnavailable || '');
        }

        var ctrl = new AbortController();
        var timer = window.setTimeout(function () {
            ctrl.abort();
        }, 180000);

        var res;

        try {
            res = await fetch(askagentoAiSearchImageAdmin.searchUrl, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'X-Askagento-Site-Id': askagentoAiSearchImageAdmin.siteId,
                    'X-Askagento-Api-Key': askagentoAiSearchImageAdmin.apiKey
                },
                body: JSON.stringify({
                    modality: 'image',
                    image_base64: b64,
                    limit: limit
                }),
                signal: ctrl.signal
            });
        } finally {
            window.clearTimeout(timer);
        }

        var text = await res.text();
        var decoded;

        try {
            decoded = text ? JSON.parse(text) : {};
        } catch (eJson) {
            var tail = String(text)
                .replace(/\s+/g, ' ')
                .trim()
                .slice(0, 400);

            throw new Error((locI18n.requestFailed || '') + (tail ? ' ' + tail : ''));
        }

        if (!res.ok) {
            var remoteErr =
                decoded && typeof decoded.error === 'string' && decoded.error.trim() !== ''
                    ? decoded.error.trim()
                    : res.statusText || '';

            if (!remoteErr) {
                remoteErr = 'HTTP ' + String(res.status);
            }

            if (remoteErr === 'AI search quota exceeded') {
                remoteErr = locI18n.aiSearchQuotaExceeded || remoteErr;
            }

            throw new Error(remoteErr);
        }

        return decoded && Array.isArray(decoded.results) ? decoded.results : [];
    }

    /**
     * Load a same-origin image URL, downscale to JPEG (same path as file upload).
     *
     * @returns {Promise<string>} data URL
     */
    async function jpegDataUrlFromImageUrl(src, squareSide, quality) {
        var res = await fetch(src, {
            credentials: 'same-origin'
        });

        if (!res.ok) {
            throw new Error('img_fetch');
        }

        var blob = await res.blob();
        var file = new File([blob], 'sample.jpg', { type: blob.type || 'image/jpeg' });

        return jpegDataUrlFromFile(file, squareSide, quality);
    }

    function tileHtml(row, variant) {
        var tileClass = 'askagento-ai-search-admin-tile askagento-ai-search-admin-tile--image';

        if (variant === 'querySample') {
            tileClass += ' askagento-ai-search-admin-tile--query-sample';
        }

        if (!row.image_url) {
            return '';
        }

        return (
            '<li class="' + tileClass + '">' +
            '<div class="askagento-ai-search-admin-tile-inner askagento-ai-search-admin-tile-inner--image-only">' +
            '<img class="askagento-ai-search-admin-thumb" src="' +
            escapeHtml(row.image_url) +
            '" alt="" loading="lazy">' +
            '</div></li>'
        );
    }

    $(function () {
        var i18n = askagentoAiSearchImageAdmin.i18n || {};
        var btn = $('#askagento-ai-img-search-check-status');

        if (!btn.length) {
            return;
        }

        var outBox = $('#askagento-ai-img-search-status-out');
        var listing = $('#askagento-ai-img-search-results-list');
        var queryBlock = $('#askagento-ai-img-search-query-block');
        var queryList = $('#askagento-ai-img-search-query-list');
        var matchesHeading = $('#askagento-ai-img-search-matches-heading');
        var splitPane = $('#askagento-ai-img-search-diagnostics-split');

        var fileInput = $('#askagento-ai-img-search-file');
        var cameraBtn = $('#askagento-ai-img-search-camera');
        var uploadOut = $('#askagento-ai-img-search-upload-out');
        var uploadList = $('#askagento-ai-img-search-upload-results');
        var previewWrap = $('#askagento-ai-img-search-upload-preview-wrap');
        var previewImg = $('#askagento-ai-img-search-upload-preview');

        function setDiagnosticsSplitVisible(on) {
            splitPane.toggleClass('askagento-ai-search-diagnostics-split--visible', !!on);
        }

        btn.on('click', async function () {
            var $btn = $(this);
            var startedAt = Date.now();

            $btn.prop('disabled', true);
            outBox.html('<p>' + escapeHtml(i18n.working || '') + '</p>');
            setDiagnosticsSplitVisible(false);
            queryBlock.hide();
            matchesHeading.hide();
            queryList.empty();
            listing.empty();

            var maxPx = askagentoAiSearchImageAdmin.maxRasterPx ? parseInt(askagentoAiSearchImageAdmin.maxRasterPx, 10) : 260;

            if (!maxPx || maxPx < 64) {
                maxPx = 260;
            }

            try {
                var resp = await $.ajax({
                    url: askagentoAiSearchImageAdmin.ajaxUrl,
                    method: 'POST',
                    data: {
                        action: 'askagento_ai_search_image_admin_check',
                        nonce: askagentoAiSearchImageAdmin.nonce
                    },
                    dataType: 'json'
                });

                if (!resp.success) {
                    var err =
                        resp.data && resp.data.message ? resp.data.message : i18n.failed || '';

                    setDiagnosticsSplitVisible(false);
                    queryBlock.hide();
                    matchesHeading.hide();
                    queryList.empty();
                    listing.empty();
                    outBox.html(
                        '<p class="notice notice-error" style="padding:8px 12px;">' + escapeHtml(err) + '</p>'
                    );

                    return;
                }

                var d = resp.data || {};
                var sampleItem = d.sample_query_item || null;
                var skuNorm =
                    d.sample_product_sku != null ? String(d.sample_product_sku).trim().toLowerCase() : '';

                var guidNorm =
                    d.sample_global_unique_id != null
                        ? String(d.sample_global_unique_id).trim().toLowerCase()
                        : '';

                var imgUrl = d.sample_image_url != null ? String(d.sample_image_url) : '';

                if (imgUrl === '') {
                    throw new Error(i18n.failed || '');
                }

                var dataUrl = await jpegDataUrlFromImageUrl(imgUrl, maxPx, 0.95);
                var comma = String(dataUrl).indexOf(',');
                var b64 = comma >= 0 ? String(dataUrl).slice(comma + 1) : '';

                if (b64.length < 33) {
                    throw new Error(i18n.requestFailed || '');
                }

                var apiLimit = parseInt(d.api_limit, 10);
                var lim = Number.isFinite(apiLimit) ? Math.min(50, Math.max(1, apiLimit)) : 12;
                var visMax = parseInt(d.visible_max, 10);
                var visCap = Number.isFinite(visMax) ? Math.min(50, Math.max(1, visMax)) : 3;

                var rawRows = await fetchAskagentoImageSearchFromB64(b64, lim);
                var minD = minFiniteDistanceFromRows(rawRows);
                var visibleResults = stripSampleFromResultRows(
                    rawRows,
                    sampleItem,
                    skuNorm,
                    guidNorm,
                    d.sample_title_normalized,
                    minD
                ).slice(0, visCap);

                outBox.empty();

                if (sampleItem && sampleItem.product_id) {
                    queryList.empty().append(tileHtml(sampleItem, 'querySample'));
                    queryBlock.show();
                } else {
                    queryList.empty();
                    queryBlock.hide();
                }

                if (visibleResults.length) {
                    matchesHeading.show();
                    visibleResults.forEach(function (row) {
                        listing.append(tileHtml(row));
                    });
                } else {
                    matchesHeading.hide();
                }

                setDiagnosticsSplitVisible(
                    queryList.children().length > 0 || listing.children().length > 0
                );
            } catch (err) {
                var msg;

                if (err && err.message === 'img_fetch') {
                    msg = i18n.sampleImageLoadFailed || i18n.requestFailed || '';
                } else if (err && err.name === 'AbortError') {
                    msg = i18n.timedOut || '';
                } else if (err && err.name === 'TypeError') {
                    var surl = String(askagentoAiSearchImageAdmin.searchUrl || '');

                    if (window.location.protocol === 'https:' && surl.indexOf('http://') === 0) {
                        msg = (i18n.requestFailed || '') + ' ' + (i18n.httpsApiRequired || '').trim();
                    } else {
                        msg = (i18n.requestFailed || '') + (err.message ? ' (' + String(err.message) + ')' : '');
                    }
                } else if (err && err.message) {
                    msg = String(err.message);
                } else {
                    msg = i18n.requestFailed || '';
                }

                setDiagnosticsSplitVisible(false);
                queryBlock.hide();
                matchesHeading.hide();
                queryList.empty();
                listing.empty();
                outBox.html(
                    '<p class="notice notice-error" style="padding:8px 12px;">' + escapeHtml(msg) + '</p>'
                );
            } finally {
                var elapsedSec = (Date.now() - startedAt) / 1000;
                var pingSec = elapsedSec.toFixed(1);

                var pingHtml =
                    '<p class="askagento-ai-search-admin-ping">' +
                    escapeHtml(i18n.ping || '') +
                    ' <strong>' +
                    escapeHtml(pingSec) +
                    '</strong> ' +
                    escapeHtml(i18n.pingUnit || 's') +
                    '</p>';

                outBox.append(pingHtml);
                $btn.prop('disabled', false);
            }
        });

        cameraBtn.on('click', function () {
            fileInput.trigger('click');
        });

        fileInput.on('change', async function () {
            var inputEl = this;
            var f = inputEl.files && inputEl.files[0];

            uploadList.hide().empty();
            uploadOut.empty();

            if (!f) {
                previewWrap.hide();
                previewImg.attr('src', '');
                inputEl.value = '';

                return;
            }

            var reader = new FileReader();

            reader.onload = function () {
                var url = reader.result;

                if (typeof url === 'string') {
                    previewImg.attr('src', url);
                    previewWrap.show();
                }
            };

            reader.readAsDataURL(f);

            uploadOut.html('<p>' + escapeHtml(i18n.uploadWorking || '') + '</p>');

            var startedAt = Date.now();

            /** Default square edge length (align with API SEARCH_QUERY_IMAGE_SIZE); override via maxRasterPx. */
            var maxPx = askagentoAiSearchImageAdmin.maxRasterPx ? parseInt(askagentoAiSearchImageAdmin.maxRasterPx, 10) : 260;

            if (!maxPx || maxPx < 64) {
                maxPx = 260;
            }

            try {
                var dataUrl = await jpegDataUrlFromFile(f, maxPx, 0.95);
                var comma = String(dataUrl).indexOf(',');
                var b64 = comma >= 0 ? String(dataUrl).slice(comma + 1) : '';

                if (b64.length < 33) {
                    throw new Error(i18n.requestFailed || '');
                }

                var limitRaw = parseInt(askagentoAiSearchImageAdmin.imageSearchLimit, 10);
                var limit = Number.isFinite(limitRaw) ? Math.min(50, Math.max(1, limitRaw)) : 12;

                var rows = await fetchAskagentoImageSearchFromB64(b64, limit);

                uploadOut.empty();

                var elapsedSec = (Date.now() - startedAt) / 1000;
                var pingSec = elapsedSec.toFixed(1);

                uploadOut.append(
                    '<p class="askagento-ai-search-admin-ping">' +
                        escapeHtml(i18n.ping || '') +
                        ' <strong>' +
                        escapeHtml(pingSec) +
                        '</strong> ' +
                        escapeHtml(i18n.pingUnit || 's') +
                        '</p>'
                );

                if (!rows.length) {
                    uploadList.hide().empty();
                } else {
                    uploadList.show().empty();
                    rows.forEach(function (row) {
                        uploadList.append(tileHtml(row));
                    });
                }
            } catch (err) {
                var msg;

                if (err && err.name === 'AbortError') {
                    msg = i18n.timedOut || '';
                } else if (err && err.name === 'TypeError') {
                    var surl = String(askagentoAiSearchImageAdmin.searchUrl || '');

                    if (window.location.protocol === 'https:' && surl.indexOf('http://') === 0) {
                        msg =
                            (i18n.requestFailed || '') + ' ' + (i18n.httpsApiRequired || '').trim();
                    } else {
                        msg =
                            (i18n.requestFailed || '') +
                            (err.message ? ' (' + String(err.message) + ')' : '');
                    }
                } else if (err && err.message) {
                    msg = String(err.message);
                } else {
                    msg = i18n.requestFailed || '';
                }

                uploadOut.html(
                    '<p class="notice notice-error" style="padding:8px 12px;">' + escapeHtml(msg) + '</p>'
                );

                uploadList.hide().empty();
            } finally {
                inputEl.value = '';
            }
        });
    });
})(jQuery);
