(function () {
    'use strict';

    var cfg = window.WPSNQueueLive || {};
    var endpointUrl = cfg.endpointUrl || cfg.ajaxUrl || window.ajaxurl || '';
    var nonce = cfg.nonce || '';
    var profiles = cfg.profiles || {};
    var defaultProfile = cfg.defaultProfile || 'medium';
    var i18n = cfg.i18n || {};

    if (!endpointUrl || !nonce || !profiles) {
        return;
    }

    function text(key, fallback) {
        return Object.prototype.hasOwnProperty.call(i18n, key) ? String(i18n[key]) : fallback;
    }

    function format(template, values) {
        var out = String(template || '');
        Object.keys(values || {}).forEach(function (key) {
            out = out.replace(new RegExp('\\{' + key + '\\}', 'g'), String(values[key]));
        });
        return out;
    }

    function updateQueueCounts(counts) {
        ['pending', 'running', 'failed', 'done'].forEach(function (key) {
            var value = counts && Object.prototype.hasOwnProperty.call(counts, key) ? counts[key] : 0;
            document.querySelectorAll('[data-wpsn-queue-count="' + key + '"]').forEach(function (node) {
                node.textContent = String(value);
            });
        });
    }

    function readStoredProfile() {
        try {
            var stored = window.localStorage.getItem('wpsnQueueLiveProfile');
            return stored && Object.prototype.hasOwnProperty.call(profiles, stored) ? stored : '';
        } catch (err) {
            return '';
        }
    }

    function storeProfile(profile) {
        try {
            window.localStorage.setItem('wpsnQueueLiveProfile', profile);
        } catch (err) {
            // ignore storage errors
        }
    }

    function controller(root) {
        this.root = root;
        this.sessionId = root.getAttribute('data-session-id') || '';
        this.autoStart = root.getAttribute('data-auto-start') === '1';
        this.progressBar = root.querySelector('.wpsn-queue-live-progress-bar');
        this.statsText = root.querySelector('.wpsn-queue-live-stats');
        this.statusText = root.querySelector('.wpsn-queue-live-status');
        this.profileSelect = root.querySelector('.wpsn-queue-live-profile');
        this.profileDesc = root.querySelector('.wpsn-queue-live-profile-desc');
        this.toggleBtn = root.querySelector('.wpsn-queue-live-toggle');
        this.timer = null;
        this.inFlight = false;
        this.running = false;

        var defaultFromNode = root.getAttribute('data-default-profile') || defaultProfile;
        var preferred = profiles[defaultFromNode] ? defaultFromNode : readStoredProfile();
        if (!profiles[preferred]) {
            preferred = profiles[defaultProfile] ? defaultProfile : 'medium';
        }
        this.profile = preferred;

        if (this.profileSelect) {
            this.profileSelect.value = this.profile;
            this.profileSelect.addEventListener('change', this.onProfileChange.bind(this));
        }
        if (this.toggleBtn) {
            this.toggleBtn.addEventListener('click', this.onToggle.bind(this));
        }

        this.renderProfileDescription();
        this.renderToggle();

        if (this.autoStart) {
            this.start();
        } else {
            this.fetchStatusOnly();
        }
    }

    controller.prototype.profileConfig = function () {
        return profiles[this.profile] || profiles[defaultProfile] || {
            intervalSeconds: 12,
            maxJobs: 0,
            autoRun: false
        };
    };

    controller.prototype.renderProfileDescription = function () {
        if (!this.profileDesc) {
            return;
        }
        var profile = this.profileConfig();
        var description = profile.description || format(text('profileSummary', '{label}: every {seconds}s · up to {jobs} jobs / cycle.'), {
            label: profile.label || this.profile,
            seconds: profile.intervalSeconds || 12,
            jobs: profile.maxJobs || 0
        });
        this.profileDesc.textContent = description;
    };

    controller.prototype.renderToggle = function () {
        if (!this.toggleBtn) {
            return;
        }
        this.toggleBtn.textContent = this.running ? text('stop', 'Pause live run') : text('start', 'Start live run');
    };

    controller.prototype.setStatus = function (message) {
        if (this.statusText) {
            this.statusText.textContent = String(message || '');
        }
    };

    controller.prototype.setStats = function (session) {
        if (!this.statsText || !session) {
            return;
        }
        this.statsText.textContent = 'Processed ' + (session.terminal || 0) + ' of ' + (session.queued_jobs || 0) + ' queued jobs · pending ' + (session.pending || 0) + ' · running ' + (session.running || 0) + ' · failed ' + (session.failed || 0);
    };

    controller.prototype.setProgress = function (session) {
        if (!this.progressBar || !session) {
            return;
        }
        var percent = session.percent || 0;
        if (percent < 0) {
            percent = 0;
        }
        if (percent > 100) {
            percent = 100;
        }
        this.progressBar.style.width = String(percent) + '%';
    };

    controller.prototype.onProfileChange = function () {
        if (this.profileSelect && profiles[this.profileSelect.value]) {
            this.profile = this.profileSelect.value;
            storeProfile(this.profile);
        }
        this.renderProfileDescription();
        if (this.running) {
            this.schedule(300);
        } else {
            this.fetchStatusOnly();
        }
    };

    controller.prototype.onToggle = function () {
        if (this.running) {
            this.stop();
            this.setStatus(text('paused', 'Live worker paused.'));
            return;
        }
        this.start();
    };

    controller.prototype.start = function () {
        if (!this.sessionId) {
            return;
        }
        this.running = true;
        this.renderToggle();
        this.schedule(0);
    };

    controller.prototype.stop = function () {
        this.running = false;
        this.renderToggle();
        if (this.timer) {
            window.clearTimeout(this.timer);
            this.timer = null;
        }
    };

    controller.prototype.schedule = function (delayMs) {
        var self = this;
        if (!this.running) {
            return;
        }
        if (this.timer) {
            window.clearTimeout(this.timer);
        }
        this.timer = window.setTimeout(function () {
            self.tick();
        }, Math.max(0, delayMs || 0));
    };

    controller.prototype.fetchStatusOnly = function () {
        this.request('wpsn_queue_live_status');
    };

    controller.prototype.tick = function () {
        var profile = this.profileConfig();
        var action = profile.autoRun ? 'wpsn_queue_live_tick' : 'wpsn_queue_live_status';
        this.request(action);
    };

    controller.prototype.request = function (action) {
        var self = this;
        if (this.inFlight) {
            return;
        }
        this.inFlight = true;

        var body = new URLSearchParams();
        body.set('action', action);
        body.set('nonce', nonce);
        body.set('session_id', this.sessionId);
        body.set('profile', this.profile);

        fetch(endpointUrl, {
            method: 'POST',
            credentials: 'same-origin',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
            },
            body: body.toString()
        })
            .then(function (response) {
                return response.text().then(function (raw) {
                    var payload = null;

                    if (raw) {
                        try {
                            payload = JSON.parse(raw);
                        } catch (err) {
                            var parseError = new Error('invalid_json');
                            parseError.httpStatus = response.status || 0;
                            throw parseError;
                        }
                    }

                    if (!response.ok) {
                        var httpMessage = payload && payload.data && payload.data.message ? String(payload.data.message) : ('HTTP ' + String(response.status || 0));
                        var httpError = new Error(httpMessage);
                        httpError.httpStatus = response.status || 0;
                        throw httpError;
                    }

                    if (!payload || payload.success !== true || !payload.data) {
                        var invalidMessage = payload && payload.data && payload.data.message ? String(payload.data.message) : 'invalid_payload';
                        var invalidError = new Error(invalidMessage);
                        invalidError.httpStatus = response.status || 0;
                        throw invalidError;
                    }

                    return payload;
                });
            })
            .then(function (payload) {
                self.applyPayload(payload.data, action === 'wpsn_queue_live_tick');
            })
            .catch(function (error) {
                var profile = self.profileConfig();
                var retrySeconds = Math.max(profile.intervalSeconds || 12, 10);
                var reason = '';

                if (error && error.message) {
                    if (error.message === 'invalid_json') {
                        reason = text('invalidJson', 'invalid JSON response');
                    } else if (error.message !== 'invalid_payload') {
                        reason = String(error.message);
                    } else if (error.httpStatus) {
                        reason = 'HTTP ' + String(error.httpStatus);
                    }
                }

                if (reason) {
                    self.setStatus(format(text('statusErrorDetailed', 'Live update failed ({reason}). Retrying in {seconds}s…'), {
                        reason: reason,
                        seconds: retrySeconds
                    }));
                } else {
                    self.setStatus(text('statusError', 'Live update failed. Retrying shortly…'));
                }

                if (self.running) {
                    self.schedule(retrySeconds * 1000);
                }
            })
            .finally(function () {
                self.inFlight = false;
            });
    };

    controller.prototype.applyPayload = function (data, wasTick) {
        var profile = this.profileConfig();
        var seconds = profile.intervalSeconds || 12;
        var status = data.status || {};
        var session = status.session || null;

        updateQueueCounts(status.counts || {});

        if (session && session.exists) {
            this.setProgress(session);
            this.setStats(session);
        } else if (this.sessionId) {
            this.stop();
            this.setStatus('Bulk session not found.');
            return;
        }

        if (status.paused) {
            this.stop();
            this.setStatus(text('queuePaused', 'Queue is paused — live worker stopped.'));
            return;
        }

        if (session && session.complete) {
            this.stop();
            this.setStatus(text('completed', 'Queue session completed.'));
            return;
        }

        if (wasTick && data.ran) {
            this.setStatus(format(text('lastBatch', 'Last batch: {processed} jobs in {elapsed} ms. Next update in {seconds}s.'), {
                processed: data.processed || 0,
                elapsed: data.elapsed_ms || 0,
                seconds: seconds
            }));
        } else if (!profile.autoRun) {
            this.setStatus(format(text('nextStatus', 'Next status check in {seconds}s.'), {
                seconds: seconds
            }));
        } else if (this.running) {
            this.setStatus(text('running', 'Live worker is running…'));
        } else {
            this.setStatus(text('paused', 'Live worker paused.'));
        }

        if (this.running) {
            this.schedule(seconds * 1000);
        }
    };

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('[data-wpsn-queue-live="1"]').forEach(function (root) {
            new controller(root);
        });
    });
}());
