/**
 * Sitemap Module
 * Handles Schemafy sitemap settings, autosave, and status UI.
 */
(function($) {
    'use strict';

    window.SchemafySitemap = {
        saving: false,
        queuedSettings: null,
        queuedOptions: null,
        saveTimer: null,
        revision: 0,
        retryDelay: 700,

        text: function(key, fallback) {
            if (typeof schemafy_ajax !== 'undefined' && schemafy_ajax.i18n && schemafy_ajax.i18n[key]) {
                return schemafy_ajax.i18n[key];
            }

            return fallback;
        },

        init: function() {
            if ($('#schemafy-tab-sitemap').length === 0) {
                return;
            }

            // Revision 0 = "no snapshot yet"; the server accepts it and the silent
            // status fetch below syncs the real server revision. Never seed from
            // Date.now(): a client clock behind the server's stored revision makes
            // every save look stale and the enable toggle silently reverts.
            this.revision = 0;
            this.bindEvents();
            this.syncSourceRows();
            this.updateStatePreview(this.currentEnabled(), false);
            this.refreshStatus(true);
        },

        bindEvents: function() {
            $(document).off('.schemafySitemap');

            $(document).on('click.schemafySitemap', '#schemafy-sitemap-power', () => this.togglePower());
            $(document).on('click.schemafySitemap', '#schemafy-refresh-sitemap-status', () => this.refreshStatus());
            $(document).on('click.schemafySitemap', '#schemafy-copy-sitemap-url', () => this.copySitemapUrl());

            $(document).on('change.schemafySitemap', '.schemafy-sitemap-post-type, .schemafy-sitemap-taxonomy, #schemafy-sitemap-lastmod, #schemafy-sitemap-redirect-legacy', (event) => {
                this.syncSourceRow($(event.currentTarget));
                this.scheduleAutosave();
            });

            $(document).on('input.schemafySitemap change.schemafySitemap', '#schemafy-sitemap-per-page', () => {
                this.scheduleAutosave();
            });
        },

        currentEnabled: function() {
            return $('#schemafy-sitemap-power').attr('aria-pressed') === 'true';
        },

        collectSettings: function(overrideEnabled) {
            const postTypes = $('.schemafy-sitemap-post-type:checked').map(function() {
                return $(this).val();
            }).get();

            const taxonomies = $('.schemafy-sitemap-taxonomy:checked').map(function() {
                return $(this).val();
            }).get();

            let perPage = parseInt($('#schemafy-sitemap-per-page').val(), 10);
            if (!perPage) {
                perPage = 1000;
            }

            perPage = Math.max(100, Math.min(50000, perPage));

            return {
                enabled: typeof overrideEnabled === 'boolean' ? (overrideEnabled ? 1 : 0) : (this.currentEnabled() ? 1 : 0),
                per_page: perPage,
                include_lastmod: $('#schemafy-sitemap-lastmod').is(':checked') ? 1 : 0,
                redirect_legacy: $('#schemafy-sitemap-redirect-legacy').is(':checked') ? 1 : 0,
                post_types: postTypes,
                taxonomies: taxonomies
            };
        },

        togglePower: function() {
            if (this.saving) {
                return;
            }

            window.clearTimeout(this.saveTimer);

            const nextEnabled = !this.currentEnabled();
            const settings = this.collectSettings(nextEnabled);

            if (!this.canSave(settings, true)) {
                return;
            }

            this.updateStatePreview(nextEnabled, true);
            this.persistSettings(settings, { notify: true, reason: 'toggle' });
        },

        scheduleAutosave: function() {
            this.syncSourceRows();
            window.clearTimeout(this.saveTimer);
            this.setSaveState('pending', this.text('sitemap_changes_pending', 'Changes pending'));

            this.saveTimer = window.setTimeout(() => {
                const settings = this.collectSettings();

                if (!this.canSave(settings, false)) {
                    return;
                }

                this.persistSettings(settings, { notify: false, reason: 'autosave' });
            }, 600);
        },

        canSave: function(settings, shouldNotify) {
            if (settings.enabled && settings.post_types.length === 0 && settings.taxonomies.length === 0) {
                const message = this.text('sitemap_select_source_before_enable', 'Select at least one content source before enabling the sitemap.');
                this.setSaveState('error', this.text('sitemap_select_source_short', 'Select a source'));

                if (shouldNotify) {
                    this.notify(message, 'warning');
                }

                return false;
            }

            return true;
        },

        persistSettings: function(settings, options) {
            options = options || {};

            if (this.saving) {
                this.queuedSettings = $.extend(true, {}, settings);
                this.queuedOptions = $.extend(true, {}, options, { notify: false });
                this.setSaveState('pending', this.text('sitemap_changes_queued', 'Changes queued'));
                return;
            }

            const revision = this.nextRevision();
            const payload = $.extend(true, {}, settings, { revision: revision });
            let retryDelay = 0;

            this.saving = true;
            this.setSaving(true);
            this.setSaveState('saving', this.text('saving', 'Saving...'));

            $.ajax({
                url: schemafy_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'schemafy_save_sitemap_settings',
                    nonce: schemafy_ajax.nonce,
                    revision: payload.revision,
                    enabled: payload.enabled,
                    per_page: payload.per_page,
                    include_lastmod: payload.include_lastmod,
                    redirect_legacy: payload.redirect_legacy,
                    post_types: payload.post_types,
                    taxonomies: payload.taxonomies
                }
            }).done((response) => {
                if (response && response.success) {
                    const data = response.data || {};
                    this.applyStatus(data.status || data);
                    this.setSaveState('saved', data.stale ? this.text('sitemap_already_current', 'Already current') : this.text('sitemap_saved_short', 'Saved'));

                    if (options.notify) {
                        this.notify(this.successMessage(data), 'success');
                    }

                    return;
                }

                const data = this.responseData(response);
                this.handleSaveError(data, options);
            }).fail((xhr) => {
                const data = this.xhrData(xhr);

                if (data.code === 'busy') {
                    retryDelay = this.retryDelay;
                    this.queuedSettings = $.extend(true, {}, settings);
                    this.queuedOptions = $.extend(true, {}, options, { notify: false });
                    this.setSaveState('pending', this.text('sitemap_retrying', 'Retrying...'));

                    if (data.status) {
                        this.applyStatus(data.status);
                    }

                    return;
                }

                this.handleSaveError(data, options);
            }).always(() => {
                this.saving = false;
                this.setSaving(false);

                if (!this.queuedSettings) {
                    return;
                }

                const queuedSettings = this.queuedSettings;
                const queuedOptions = this.queuedOptions || {};
                this.queuedSettings = null;
                this.queuedOptions = null;

                window.setTimeout(() => {
                    this.persistSettings(queuedSettings, queuedOptions);
                }, retryDelay);
            });
        },

        refreshStatus: function(silent) {
            if (this.saving) {
                return;
            }

            const $btn = $('#schemafy-refresh-sitemap-status');
            $btn.addClass('schemafy-spin');

            $.ajax({
                url: schemafy_ajax.ajax_url,
                type: 'POST',
                data: {
                    action: 'schemafy_get_sitemap_status',
                    nonce: schemafy_ajax.nonce
                },
                success: (response) => {
                    if (response && response.success) {
                        this.applyStatus(response.data);

                        if (!silent) {
                            this.setSaveState('saved', this.text('sitemap_status_refreshed_short', 'Status refreshed'));
                            this.notify(this.text('sitemap_status_refreshed', 'Sitemap status refreshed.'), 'success');
                        }
                    } else if (!silent) {
                        this.setSaveState('error', this.text('sitemap_refresh_failed', 'Refresh failed'));
                        this.notify(this.text('sitemap_error_refreshing_status', 'Error refreshing sitemap status.'), 'error');
                    }
                },
                error: () => {
                    if (!silent) {
                        this.setSaveState('error', this.text('sitemap_refresh_failed', 'Refresh failed'));
                        this.notify(this.text('sitemap_network_error_refreshing_status', 'Network error while refreshing sitemap status.'), 'error');
                    }
                },
                complete: () => {
                    $btn.removeClass('schemafy-spin');
                }
            });
        },

        applyStatus: function(status) {
            if (!status) {
                return;
            }

            const settings = status.settings || {};
            const enabled = typeof status.enabled !== 'undefined'
                ? status.enabled === true || status.enabled === 1 || status.enabled === '1'
                : !!parseInt(settings.enabled, 10);

            this.updateStatePreview(enabled, false);

            if (settings.revision) {
                this.revision = Math.max(this.revision, parseInt(settings.revision, 10) || 0);
            }

            if (settings.post_types) {
                this.setCheckedValues('.schemafy-sitemap-post-type', settings.post_types);
            }

            if (settings.taxonomies) {
                this.setCheckedValues('.schemafy-sitemap-taxonomy', settings.taxonomies);
            }

            if (typeof settings.per_page !== 'undefined') {
                $('#schemafy-sitemap-per-page').val(settings.per_page);
            }

            if (typeof settings.include_lastmod !== 'undefined') {
                $('#schemafy-sitemap-lastmod').prop('checked', !!parseInt(settings.include_lastmod, 10));
            }

            if (typeof settings.redirect_legacy !== 'undefined') {
                $('#schemafy-sitemap-redirect-legacy').prop('checked', !!parseInt(settings.redirect_legacy, 10));
            }

            this.syncSourceRows();

            if (status.index_url) {
                $('#schemafy-sitemap-index-url').text(status.index_url);
                $('#schemafy-open-sitemap-url').attr('href', status.index_url);
            }

            if (status.totals) {
                $('#schemafy-sitemap-total-urls').text(this.formatNumber(status.totals.urls || 0));
                $('#schemafy-sitemap-total-files').text(this.formatNumber(status.totals.sitemaps || 0));
                $('#schemafy-sitemap-total-sources').text(this.formatNumber(status.totals.sources || 0));
            }

            if (status.conflicts) {
                this.renderConflicts(status.conflicts);
            }
        },

        updateStatePreview: function(enabled, pending) {
            const $state = $('#schemafy-sitemap-state');
            const $power = $('#schemafy-sitemap-power');
            const $icon = $power.find('.schemafy-sitemap-power-icon .dashicons');

            $state.toggleClass('is-on', enabled).toggleClass('is-off', !enabled);
            $('#schemafy-sitemap-state-text').text(enabled ? this.text('status_active', 'Active') : this.text('status_inactive', 'Inactive'));

            $('.schemafy-sitemap-shell').attr('data-sitemap-enabled', enabled ? '1' : '0');
            $power
                .toggleClass('is-on', enabled)
                .toggleClass('is-off', !enabled)
                .attr('aria-pressed', enabled ? 'true' : 'false')
                .attr('data-enabled', enabled ? '1' : '0');

            $('#schemafy-sitemap-power-label').text(enabled ? this.text('sitemap_deactivate', 'Deactivate sitemap') : this.text('sitemap_activate', 'Activate sitemap'));
            $('#schemafy-sitemap-power-meta').text(pending ? this.text('saving', 'Saving...') : this.text('sitemap_autosaves_immediately', 'Autosaves immediately'));

            $icon
                .removeClass('dashicons-controls-play dashicons-controls-pause')
                .addClass(enabled ? 'dashicons-controls-pause' : 'dashicons-controls-play');
        },

        setSaving: function(isSaving) {
            const $power = $('#schemafy-sitemap-power');
            const selector = [
                '#schemafy-sitemap-power',
                '.schemafy-sitemap-post-type',
                '.schemafy-sitemap-taxonomy',
                '#schemafy-sitemap-per-page',
                '#schemafy-sitemap-lastmod',
                '#schemafy-sitemap-redirect-legacy'
            ].join(',');

            $(selector).prop('disabled', isSaving);
            $power.toggleClass('is-saving', isSaving).attr('aria-busy', isSaving ? 'true' : 'false');

            if (isSaving) {
                $('#schemafy-sitemap-power-meta').text(this.text('saving', 'Saving...'));
            } else {
                $('#schemafy-sitemap-power-meta').text(this.text('sitemap_autosaves_immediately', 'Autosaves immediately'));
            }
        },

        setSaveState: function(state, text) {
            const iconMap = {
                saved: 'dashicons-saved',
                pending: 'dashicons-clock',
                saving: 'dashicons-update-alt schemafy-spin',
                error: 'dashicons-warning'
            };

            const $indicator = $('#schemafy-sitemap-save-indicator');
            const $icon = $indicator.find('.dashicons');

            $indicator
                .removeClass('is-saved is-pending is-saving is-error')
                .addClass('is-' + state);

            $icon
                .removeClass('dashicons-saved dashicons-clock dashicons-update-alt dashicons-warning schemafy-spin')
                .addClass(iconMap[state] || iconMap.saved);

            $('#schemafy-sitemap-save-text').text(text || this.text('sitemap_ready', 'Ready'));
        },

        setCheckedValues: function(selector, values) {
            const selected = (values || []).map(function(value) {
                return String(value);
            });

            $(selector).each(function() {
                const $input = $(this);
                $input.prop('checked', selected.indexOf(String($input.val())) !== -1);
            });
        },

        syncSourceRows: function() {
            $('.schemafy-sitemap-post-type, .schemafy-sitemap-taxonomy').each((index, element) => {
                this.syncSourceRow($(element));
            });
        },

        syncSourceRow: function($input) {
            if (!$input || !$input.length) {
                return;
            }

            $input.closest('.schemafy-sitemap-source-row').toggleClass('is-selected', $input.is(':checked'));
        },

        successMessage: function(data) {
            const actions = data && data.actions ? data.actions : [];

            if (actions.length > 0) {
                return this.text('sitemap_active_conflicts_disabled', 'Schemafy sitemap is active. Duplicate sitemap modules were disabled.');
            }

            return data && data.message ? data.message : this.text('sitemap_settings_saved', 'Sitemap settings saved.');
        },

        handleSaveError: function(data, options) {
            const message = data.message || this.text('sitemap_error_saving_settings', 'Error saving sitemap settings.');
            this.setSaveState('error', this.text('sitemap_save_failed', 'Save failed'));

            if (data.status) {
                this.applyStatus(data.status);
            } else {
                window.setTimeout(() => this.refreshStatus(), 0);
            }

            if (options.notify !== false) {
                this.notify(message, data.code === 'empty_sources' ? 'warning' : 'error');
            }
        },

        responseData: function(response) {
            if (!response || typeof response.data === 'undefined') {
                return {};
            }

            if (typeof response.data === 'string') {
                return { message: response.data };
            }

            return response.data || {};
        },

        xhrData: function(xhr) {
            if (xhr && xhr.responseJSON) {
                return this.responseData(xhr.responseJSON);
            }

            if (xhr && xhr.responseText) {
                const responseText = String(xhr.responseText).trim();

                try {
                    return this.responseData(JSON.parse(responseText));
                } catch (e) {
                    const cleaned = responseText
                        .replace(/<script[\s\S]*?<\/script>/gi, '')
                        .replace(/<style[\s\S]*?<\/style>/gi, '')
                        .replace(/<[^>]+>/g, ' ')
                        .replace(/\s+/g, ' ')
                        .trim();

                    if (cleaned) {
                        return {
                            message: cleaned.substring(0, 220)
                        };
                    }
                }
            }

            return { message: this.text('sitemap_network_error_saving_settings', 'Network error while saving sitemap settings.') };
        },

        nextRevision: function() {
            // Send the last server revision we know about — the server validates
            // it against the stored one and generates the next revision itself.
            // Client clocks must never produce revision values (see init()).
            return this.revision;
        },

        renderConflicts: function(conflicts) {
            const active = conflicts.filter(function(plugin) {
                return !!plugin.active;
            });

            const $list = $('#schemafy-sitemap-conflicts');
            if (active.length === 0) {
                $list.html(
                    '<div class="schemafy-sitemap-conflict">' +
                        '<div>' +
                            '<div class="schemafy-sitemap-conflict-name">' + this.escapeHtml(this.text('sitemap_no_duplicate_generators', 'No duplicate sitemap generators detected')) + '</div>' +
                            '<div class="schemafy-sitemap-conflict-mode">' + this.escapeHtml(this.text('sitemap_no_duplicate_protection', 'Schemafy will still protect the sitemap index URL when active.')) + '</div>' +
                        '</div>' +
                        '<span class="schemafy-sitemap-pill clear">' + this.escapeHtml(this.text('clean_label', 'Clean')) + '</span>' +
                    '</div>'
                );
                return;
            }

            const html = active.map((plugin) => {
                return (
                    '<div class="schemafy-sitemap-conflict">' +
                        '<div>' +
                            '<div class="schemafy-sitemap-conflict-name">' + this.escapeHtml(plugin.name) + '</div>' +
                            '<div class="schemafy-sitemap-conflict-mode">' + this.escapeHtml(plugin.mode) + '</div>' +
                        '</div>' +
                        '<span class="schemafy-sitemap-pill detected">' + this.escapeHtml(this.text('detected_label', 'Detected')) + '</span>' +
                    '</div>'
                );
            }).join('');

            $list.html(html);
        },

        copySitemapUrl: function() {
            const url = $('#schemafy-sitemap-index-url').text().trim();
            if (!url) {
                return;
            }

            if (navigator.clipboard && navigator.clipboard.writeText) {
                navigator.clipboard.writeText(url)
                    .then(() => this.notify(this.text('sitemap_url_copied', 'Sitemap URL copied.'), 'success'))
                    .catch(() => this.fallbackCopy(url));
                return;
            }

            this.fallbackCopy(url);
        },

        fallbackCopy: function(value) {
            const $input = $('<input type="text" readonly>').val(value).css({
                position: 'fixed',
                left: '-9999px',
                top: '-9999px'
            });

            $('body').append($input);
            $input[0].select();

            try {
                document.execCommand('copy');
                this.notify(this.text('sitemap_url_copied', 'Sitemap URL copied.'), 'success');
            } catch (e) {
                this.notify(this.text('sitemap_url_copy_failed', 'Could not copy sitemap URL.'), 'error');
            }

            $input.remove();
        },

        notify: function(message, type) {
            if (window.SchemafyUtilities && typeof window.SchemafyUtilities.showNotification === 'function') {
                window.SchemafyUtilities.showNotification(message, type || 'info');
                return;
            }

            if (window.SchemafyNotifications && typeof window.SchemafyNotifications.show === 'function') {
                window.SchemafyNotifications.show(message, type || 'info');
            }
        },

        formatNumber: function(value) {
            const number = parseInt(value, 10) || 0;
            return number.toLocaleString();
        },

        escapeHtml: function(value) {
            return window.SchemafyUtilities.escapeHtml(value || '');
        }
    };

})(jQuery);
