(function ($) {
    'use strict';

    function cfg() {
        return (typeof window.askagentoAiLabellingAdmin === 'object' && window.askagentoAiLabellingAdmin) || {};
    }

    function i18n(key, fallback) {
        var c = cfg();
        var dict = c.i18n || {};
        return dict[key] || fallback || '';
    }

    function ajaxUrl() {
        return cfg().ajaxUrl || (typeof window.ajaxurl !== 'undefined' ? window.ajaxurl : '');
    }

    function nonce() {
        return cfg().nonce || '';
    }

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

    function showError($out, message) {
        $out.html('<span style="color:#b32d2e;">' + escapeHtml(message) + '</span>');
    }

    function syncCanonicalToggleWrap($input) {
        var $wrap = $input.closest('.askagento-ai-text-live-switch-wrap');
        if (!$wrap.length) {
            return;
        }
        $wrap.toggleClass('askagento-ai-text-live-switch-wrap--on', $input.prop('checked'));
        $wrap.find('.askagento-ai-text-live-switch__state').text(
            $input.prop('checked')
                ? i18n('toggleOn', 'On')
                : i18n('toggleOff', 'Off')
        );
    }

    function renderCanonicalToggles(mode, filters) {
        var $list = $(canonicalFieldSelector(mode));
        var items = Array.isArray(filters) ? filters : [];
        var html = [];

        items.forEach(function (filterName, index) {
            var name = String(filterName || '').trim();
            if (!name) {
                return;
            }
            var inputId = 'askagento-ai-labelling-canonical-' + mode + '-' + index;
            html.push(
                '<div class="askagento-ai-labelling-canonical-item">' +
                    '<div class="askagento-ai-text-live-switch-wrap askagento-ai-text-live-switch-wrap--on">' +
                        '<label class="askagento-ai-text-live-switch" for="' + escapeHtml(inputId) + '">' +
                            '<input type="checkbox" class="askagento-ai-text-live-switch__input askagento-ai-labelling-canonical-input" id="' +
                            escapeHtml(inputId) +
                            '" value="' +
                            escapeHtml(name) +
                            '" checked />' +
                            '<span class="askagento-ai-text-live-switch__track" aria-hidden="true">' +
                                '<span class="askagento-ai-text-live-switch__thumb"></span>' +
                            '</span>' +
                            '<span class="askagento-ai-text-live-switch__text">' + escapeHtml(name) + '</span>' +
                        '</label>' +
                        '<span class="askagento-ai-text-live-switch__state">' + escapeHtml(i18n('toggleOn', 'On')) + '</span>' +
                    '</div>' +
                '</div>'
            );
        });

        $list.html(html.join(''));
    }

    function getSelectedCanonicalValues(mode) {
        var out = [];
        var seen = {};
        $(canonicalFieldSelector(mode) + ' .askagento-ai-labelling-canonical-input:checked').each(function () {
            var v = String($(this).val() || '').trim();
            if (!v) {
                return;
            }
            var low = v.toLowerCase();
            if (seen[low]) {
                return;
            }
            seen[low] = true;
            out.push(v);
        });
        return out;
    }

    /**
     * Spinner + label while Analyze / Generate requests are in flight.
     *
     * @param {string} message Already localized status text.
     */
    function workingMarkupAnalyzeGenerate(message) {
        var esc = escapeHtml(message || '');
        return (
            '<div class="askagento-ai-labelling-working" role="status" aria-live="polite">' +
            '<span class="askagento-ai-labelling-spinner" aria-hidden="true"></span>' +
            '<span>' + esc + '</span>' +
            '</div>'
        );
    }

    function modeSuffix(mode) {
        if (mode === 'categories') {
            return 'Categories';
        }
        if (mode === 'tags') {
            return 'Tags';
        }
        return 'Attributes';
    }

    function canonicalFieldSelector(mode) {
        if (mode === 'categories') {
            return '#askagento-ai-labelling-canonical-categories';
        }
        if (mode === 'tags') {
            return '#askagento-ai-labelling-canonical-tags';
        }
        return '#askagento-ai-labelling-canonical-attributes';
    }

    function canonicalWrapSelector(mode) {
        if (mode === 'categories') {
            return '#askagento-ai-labelling-categories-canonical-wrap';
        }
        if (mode === 'tags') {
            return '#askagento-ai-labelling-tags-canonical-wrap';
        }
        return '#askagento-ai-labelling-canonical-wrap';
    }

    function actionButtonSelector(mode, action) {
        if (mode === 'attributes') {
            return '#askagento-ai-labelling-' + action + '-btn';
        }
        return '#askagento-ai-labelling-' + mode + '-' + action + '-btn';
    }

    function actionOutputSelector(mode, action) {
        if (mode === 'attributes') {
            return '#askagento-ai-labelling-' + action + '-out';
        }
        return '#askagento-ai-labelling-' + mode + '-' + action + '-out';
    }

    function exportButtonSelector(mode) {
        if (mode === 'categories') {
            return '#askagento-export-generated-categories-json';
        }
        if (mode === 'tags') {
            return '#askagento-export-generated-tags-json';
        }
        return '#askagento-export-generated-attributes-json';
    }

    function modeLabels(mode) {
        if (mode === 'categories') {
            return {
                withLabel: i18n('withCategories', 'Products with categories'),
                withoutLabel: i18n('withoutCategories', 'Products without categories'),
                suggestedLabel: 'Suggested canonical categories',
                generatedLabel: 'generated categories',
                generatedField: 'categories',
                noMissingHint: 'No missing categories. Generate is not required.',
                previewLinePrefix: 'Categories',
                exportDefaultFilename: 'generated-categories.json'
            };
        }
        if (mode === 'tags') {
            return {
                withLabel: i18n('withTags', 'Products with tags'),
                withoutLabel: i18n('withoutTags', 'Products without tags'),
                suggestedLabel: 'Suggested canonical tags',
                generatedLabel: 'generated tags',
                generatedField: 'tags',
                noMissingHint: 'No missing tags. Generate is not required.',
                previewLinePrefix: 'Tags',
                exportDefaultFilename: 'generated-tags.json'
            };
        }
        return {
            withLabel: i18n('withAttributes', 'Products with attributes'),
            withoutLabel: i18n('withoutAttributes', 'Products without attributes'),
            suggestedLabel: 'Suggested canonical attributes',
            generatedLabel: 'generated attributes',
            generatedField: 'attributes',
            noMissingHint: 'No missing attributes. Generate is not required.',
            previewLinePrefix: 'Attributes',
            exportDefaultFilename: 'generated-attributes.json'
        };
    }

    function summaryHtml(data, action, mode) {
        var labels = modeLabels(mode);
        var withKey = 'products_with_attributes';
        var withoutKey = 'products_without_attributes';
        var suggestedKey = 'suggested_attributes';
        if (mode === 'categories') {
            withKey = 'products_with_categories';
            withoutKey = 'products_without_categories';
            suggestedKey = 'suggested_categories';
        } else if (mode === 'tags') {
            withKey = 'products_with_tags';
            withoutKey = 'products_without_tags';
            suggestedKey = 'suggested_tags';
        }
        var lines = [];
        if (action === 'analyze') {
            lines.push('<li><strong>' + escapeHtml(labels.withLabel) + ':</strong> ' + escapeHtml(data[withKey] || 0) + '</li>');
            lines.push('<li><strong>' + escapeHtml(labels.withoutLabel) + ':</strong> ' + escapeHtml(data[withoutKey] || 0) + '</li>');
            lines.push(
                '<li><strong>' +
                escapeHtml(i18n('tokensThisStep', 'Tokens (this step)')) +
                ':</strong> ' +
                escapeHtml(data.tokens_used || 0) +
                '</li>'
            );
            if (Array.isArray(data[suggestedKey]) && data[suggestedKey].length) {
                lines.push('<li><strong>' + escapeHtml(labels.suggestedLabel) + ':</strong> ' + escapeHtml(data[suggestedKey].join(', ')) + '</li>');
            }
            if (data.should_continue === false) {
                lines.push('<li><strong>Next step:</strong> ' + escapeHtml(labels.noMissingHint) + '</li>');
            }
        } else if (action === 'generate') {
            lines.push('<li><strong>' + escapeHtml(i18n('generatedProducts', 'Generated products')) + ':</strong> ' + escapeHtml(data.generated_products || 0) + '</li>');
            lines.push(
                '<li><strong>' +
                escapeHtml(i18n('tokensThisStep', 'Tokens (this step)')) +
                ':</strong> ' +
                escapeHtml(data.tokens_used || 0) +
                '</li>'
            );
            if (Array.isArray(data.generated_preview) && data.generated_preview.length) {
                lines.push('<li><strong>' + escapeHtml('Example(s):') + '</strong></li>');
                data.generated_preview.slice(0, 2).forEach(function (row, idx) {
                    var title = (row && row.title) ? row.title : ('#' + (idx + 1));
                    var previewPairs = [];
                    if (mode === 'categories') {
                        var categories = Array.isArray(row && row.categories) ? row.categories : [];
                        var cleanCategories = categories.map(function (v) { return String(v == null ? '' : v).trim(); }).filter(Boolean);
                        if (cleanCategories.length) {
                            previewPairs.push(labels.previewLinePrefix + ': ' + cleanCategories.join(', '));
                        }
                    } else if (mode === 'tags') {
                        var tags = Array.isArray(row && row.tags) ? row.tags : [];
                        var cleanTags = tags.map(function (v) { return String(v == null ? '' : v).trim(); }).filter(Boolean);
                        if (cleanTags.length) {
                            previewPairs.push(labels.previewLinePrefix + ': ' + cleanTags.join(', '));
                        }
                    } else {
                        var attrs = (row && row.attributes && typeof row.attributes === 'object') ? row.attributes : {};
                        Object.keys(attrs).forEach(function (name) {
                            var values = attrs[name];
                            if (!Array.isArray(values)) {
                                values = [values];
                            }
                            var cleanVals = values.map(function (v) { return String(v == null ? '' : v).trim(); }).filter(Boolean);
                            if (cleanVals.length) {
                                previewPairs.push(name + ': ' + cleanVals.join(', '));
                            }
                        });
                    }
                    if (previewPairs.length) {
                        lines.push('<li><strong>' + escapeHtml('Preview ' + (idx + 1) + ' (' + title + ')') + ':</strong> ' + escapeHtml(previewPairs.join(' | ')) + '</li>');
                    }
                });
            }
        } else if (action === 'upload') {
            var shop = data.shop && typeof data.shop === 'object' ? data.shop : null;
            var updatedWoo = shop && typeof shop.updated_products !== 'undefined' && shop.updated_products !== null
                ? parseInt(shop.updated_products, 10)
                : NaN;
            var failedWoo = shop && typeof shop.failed_products !== 'undefined' && shop.failed_products !== null
                ? parseInt(shop.failed_products, 10)
                : NaN;
            var batchTotal = data.upload_batch_products;
            if ((batchTotal === undefined || batchTotal === null) && isFinite(updatedWoo) && isFinite(failedWoo)) {
                batchTotal = updatedWoo + failedWoo;
            }
            if (batchTotal !== undefined && batchTotal !== null && isFinite(parseInt(batchTotal, 10))) {
                lines.push(
                    '<li><strong>' +
                    escapeHtml(i18n('uploadBatchProducts', 'Products in upload batch')) +
                    ':</strong> ' +
                    escapeHtml(String(parseInt(batchTotal, 10))) +
                    '</li>'
                );
            }
            if (isFinite(updatedWoo)) {
                lines.push(
                    '<li><strong>' +
                    escapeHtml(i18n('wooUpdated', 'Applied in WooCommerce')) +
                    ':</strong> ' +
                    escapeHtml(String(updatedWoo)) +
                    '</li>'
                );
            }
            if (isFinite(failedWoo)) {
                lines.push(
                    '<li><strong>' +
                    escapeHtml(i18n('wooFailed', 'Could not apply in WooCommerce')) +
                    ':</strong> ' +
                    escapeHtml(String(failedWoo)) +
                    '</li>'
                );
            }
            if (shop && Array.isArray(shop.failed_ids) && shop.failed_ids.length) {
                var fid = shop.failed_ids.map(function (id) { return String(id); }).join(', ');
                lines.push(
                    '<li><strong>' +
                    escapeHtml(i18n('wooFailedIds', 'Failed product IDs')) +
                    ':</strong> ' +
                    escapeHtml(fid) +
                    '</li>'
                );
            }
            if (shop && shop.failed_ids && shop.failed_ids.length && shop.failed_reasons && typeof shop.failed_reasons === 'object') {
                shop.failed_ids.forEach(function (id) {
                    var key = String(id);
                    if (Object.prototype.hasOwnProperty.call(shop.failed_reasons, key)) {
                        lines.push(
                            '<li><strong>' +
                            escapeHtml(i18n('wooFailedDetail', 'Reason')) +
                            ' (' + escapeHtml(key) +
                            '):</strong> ' +
                            escapeHtml(String(shop.failed_reasons[key])) +
                            '</li>'
                        );
                    }
                });
            }
            var uploaded = data.uploaded_products;
            if (uploaded !== undefined && uploaded !== null && isFinite(parseInt(uploaded, 10))) {
                lines.push(
                    '<li><strong>' +
                    escapeHtml(i18n('catalogueUploaded', 'Saved to catalogue')) +
                    ':</strong> ' +
                    escapeHtml(String(parseInt(uploaded, 10))) +
                    '</li>'
                );
            }
        }
        return '<div class="askagento-status-ok">✓ ' + escapeHtml((data.action || action) + ' completed') + '</div><ul>' + lines.join('') + '</ul>';
    }

    /**
     * Generate one batch (server caps at LABEL_GENERATE_MAX_PER_CALL) and stop.
     * Each call persists its results server-side and skips already-done products,
     * so clicking Generate again processes the next batch. Upload is enabled after
     * every batch so the merchant can apply what has been generated so far.
     */
    function doGenerate(mode, $button, $out, canonicalKey, selected) {
        var url = ajaxUrl();
        var n = nonce();
        var postData = {
            action: 'askagento_ai_labelling_action',
            nonce: n,
            mode: mode,
            label_action: 'generate'
        };
        postData[canonicalKey] = selected;

        $.post(url, postData, function (resp) {
            if (resp && resp.success && resp.data) {
                var batchGenerated = parseInt(resp.data.generated_products || 0, 10);
                var remaining = parseInt(resp.data.remaining_products || 0, 10);

                $out.html(summaryHtml(resp.data, 'generate', mode));

                // Apply this batch anytime — Upload exports all generated rows so far.
                $(actionButtonSelector(mode, 'upload')).prop('disabled', false);

                // One batch per click: prompt to run Generate again while products remain.
                if (resp.data.should_continue && remaining > 0) {
                    var tmpl = i18n(
                        'batchGeneratedRunAgain',
                        '%1$d products generated in this batch. %2$d still need labelling. ' +
                        'Upload this batch now, or click Generate again to process the next batch.'
                    );
                    var note = tmpl
                        .replace('%1$d', String(batchGenerated))
                        .replace('%2$d', String(remaining));
                    $out.append(
                        '<p class="askagento-ai-labelling-batch-note">' + escapeHtml(note) + '</p>'
                    );
                }
            } else {
                var msg = (resp && resp.data && resp.data.message)
                    ? resp.data.message
                    : i18n('requestFailed', 'Request failed.');
                showError($out, msg);
            }
            $button.prop('disabled', false);
        }).fail(function () {
            showError($out, i18n('requestFailed', 'Request failed.'));
            $button.prop('disabled', false);
        });
    }

    function requestAction(action, mode, $button, $out) {
        var url = ajaxUrl();
        var n = nonce();
        if (!url || !n) {
            showError($out, i18n('missingConfig', 'Missing configuration.'));
            return;
        }

        var payload = {
            action: 'askagento_ai_labelling_action',
            nonce: n,
            mode: mode,
            label_action: action
        };

        if (action === 'generate') {
            var canonicalKey = 'canonical_attributes';
            if (mode === 'categories') {
                canonicalKey = 'canonical_categories';
            } else if (mode === 'tags') {
                canonicalKey = 'canonical_tags';
            }
            var selected = getSelectedCanonicalValues(mode);
            if (!selected.length) {
                showError($out, i18n('selectOneGenerate', 'Select at least one item before Generate.'));
                return;
            }
            var workingKeyGen = 'workingGenerate';
            if (mode !== 'attributes') {
                workingKeyGen += modeSuffix(mode);
            }
            $button.prop('disabled', true);
            $out.html(workingMarkupAnalyzeGenerate(i18n(workingKeyGen, 'Working…')));
            doGenerate(mode, $button, $out, canonicalKey, selected);
            return;
        }

        var workingKey = 'working' + action.charAt(0).toUpperCase() + action.slice(1);
        if (mode !== 'attributes') {
            workingKey += modeSuffix(mode);
        }
        $button.prop('disabled', true);
        $out.html('<span>' + escapeHtml(i18n(workingKey, 'Working…')) + '</span>');

        $.post(url, payload, function (resp) {
            if (resp && resp.success && resp.data) {
                var withoutKey = 'products_without_attributes';
                var suggestedKey = 'suggested_attributes';
                if (mode === 'categories') {
                    withoutKey = 'products_without_categories';
                    suggestedKey = 'suggested_categories';
                } else if (mode === 'tags') {
                    withoutKey = 'products_without_tags';
                    suggestedKey = 'suggested_tags';
                }
                var $canonicalWrap = $(canonicalWrapSelector(mode));
                var $generateBtn = $(actionButtonSelector(mode, 'generate'));
                var $uploadBtn = $(actionButtonSelector(mode, 'upload'));

                $out.html(summaryHtml(resp.data, action, mode));
                if (action === 'analyze') {
                    var without = parseInt(resp.data[withoutKey] || 0, 10);
                    if (isFinite(without) && without > 0) {
                        if (Array.isArray(resp.data[suggestedKey]) && resp.data[suggestedKey].length) {
                            renderCanonicalToggles(mode, resp.data[suggestedKey]);
                        } else {
                            renderCanonicalToggles(mode, []);
                        }
                        $canonicalWrap.show();
                        $generateBtn.prop('disabled', false);
                        // Upload is enabled only after Generate completes successfully for this tab.
                        $uploadBtn.prop('disabled', true);
                    } else {
                        $canonicalWrap.hide();
                        $generateBtn.prop('disabled', true);
                        $uploadBtn.prop('disabled', true);
                    }
                }
                return;
            }
            var msg = (resp && resp.data && resp.data.message) ? resp.data.message : i18n('requestFailed', 'Request failed.');
            showError($out, msg);
        }).fail(function () {
            showError($out, i18n('requestFailed', 'Request failed.'));
        }).always(function () {
            $button.prop('disabled', false);
        });
    }

    function triggerJsonDownload(contents, filename) {
        try {
            var blob = new Blob([contents], { type: 'application/json;charset=utf-8' });
            var url = window.URL.createObjectURL(blob);
            var a = document.createElement('a');
            a.href = url;
            a.download = filename || 'generated-attributes.json';
            a.style.display = 'none';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            window.URL.revokeObjectURL(url);
        } catch (e) {}
    }

    function bindExportButton(mode) {
        var selector = exportButtonSelector(mode);
        var $btn = $(selector);
        if (!$btn.length) {
            return;
        }
        $btn.on('click', function () {
            var $out = $(actionOutputSelector(mode, 'generate'));
            var url = ajaxUrl();
            var n = nonce();
            var labels = modeLabels(mode);
            if (!url || !n) {
                showError($out, i18n('missingConfig', 'Missing configuration.'));
                return;
            }
            if ($btn.prop('disabled')) {
                return;
            }
            $btn.prop('disabled', true);
            $out.html('<span>' + escapeHtml('Preparing JSON download…') + '</span>');

            $.post(url, {
                action: 'askagento_ai_labelling_action',
                nonce: n,
                mode: mode,
                label_action: 'export'
            }, function (resp) {
                if (!resp || !resp.success || !resp.data) {
                    var message = (resp && resp.data && resp.data.message) ? resp.data.message : i18n('requestFailed', 'Request failed.');
                    showError($out, message);
                    return;
                }
                var body = JSON.stringify(resp.data, null, 2);
                var filename = (resp.data.filename && String(resp.data.filename).trim()) ? String(resp.data.filename).trim() : labels.exportDefaultFilename;
                triggerJsonDownload(body, filename);
                $out.html('<span class="askagento-status-ok">✓ ' + escapeHtml('File download started: ' + filename) + '</span>');
            }).fail(function (xhr) {
                var message = i18n('requestFailed', 'Request failed.');
                var text = xhr && xhr.responseText ? String(xhr.responseText) : '';
                if (text) {
                    try {
                        var parsed = JSON.parse(text);
                        if (parsed && parsed.data && parsed.data.message) {
                            message = parsed.data.message;
                        }
                    } catch (e) {}
                }
                showError($out, message);
            }).always(function () {
                $btn.prop('disabled', false);
            });
        });
    }

    function bindActionButton(mode, action) {
        var $btn = $(actionButtonSelector(mode, action));
        if (!$btn.length) {
            return;
        }
        if (action === 'generate' || action === 'upload') {
            $btn.prop('disabled', true);
        }
        $btn.on('click', function () {
            requestAction(action, mode, $btn, $(actionOutputSelector(mode, action)));
        });
    }

    $(function () {
        bindActionButton('attributes', 'analyze');
        bindActionButton('attributes', 'generate');
        bindActionButton('attributes', 'upload');
        bindActionButton('categories', 'analyze');
        bindActionButton('categories', 'generate');
        bindActionButton('categories', 'upload');
        bindActionButton('tags', 'analyze');
        bindActionButton('tags', 'generate');
        bindActionButton('tags', 'upload');
        bindExportButton('attributes');
        bindExportButton('categories');
        bindExportButton('tags');

        $(document).on('change', '.askagento-ai-labelling-canonical-input', function () {
            syncCanonicalToggleWrap($(this));
        });

        ['attributes', 'categories', 'tags'].forEach(function (mode) {
            $(canonicalFieldSelector(mode)).empty();
            $(canonicalWrapSelector(mode)).hide();
        });
    });
})(jQuery);
