(function($) {
    'use strict';

    function toneForPublication(value) {
        if (value === 'published') return 'aysa-tone-green';
        if (value === 'scheduled') return 'aysa-tone-blue';
        return 'aysa-tone-yellow';
    }

    function toneForSeo(value) {
        return value === 'optimized' ? 'aysa-tone-green' : 'aysa-tone-red';
    }

    function toneForScope(value) {
        if (value === 'content_rewrite') return 'aysa-tone-blue';
        if (value === 'meta_only') return 'aysa-tone-yellow';
        return 'aysa-tone-neutral';
    }

    function labelize(value) {
        return String(value || '')
            .replace(/_/g, ' ')
            .replace(/\b\w/g, function(chr) { return chr.toUpperCase(); });
    }

    $(function() {
        var root = document.getElementById('aysa-onpage-v2-root');
        if (!root) {
            return;
        }

        var state = {
            projectId: Number(root.dataset.projectId || 0),
            entityGroup: 'page',
            view: 'all',
            search: '',
            page: 1,
            perPage: 50,
            runId: 0,
            afterEventId: 0,
            polling: null,
            currentEntityKey: '',
            activeRun: null,
            lastRunStatusNotified: ''
        };

        var ajaxUrl = (window.ajaxurl || '');
        var nonce = (document.getElementById('aysa-onpage-v2-nonce') || {}).value
            || (window.aysa_params && window.aysa_params.nonce)
            || '';
        var workspace = window.aysaOnPageWorkspaceInitial || {};

        var summaryEl = document.getElementById('aysa-op-v2-summary');
        var tabsEl = document.getElementById('aysa-op-v2-tabs');
        var filtersEl = document.getElementById('aysa-op-v2-filters');
        var searchEl = document.getElementById('aysa-op-v2-search');
        var theadEl = document.querySelector('#aysa-op-v2-table thead');
        var tbodyEl = document.querySelector('#aysa-op-v2-table tbody');
        var statusEl = document.getElementById('aysa-op-v2-status');
        var filterDescriptionEl = document.getElementById('aysa-op-v2-filter-description');
        var progressWrapEl = document.getElementById('aysa-op-v2-progress');
        var progressLabelEl = document.getElementById('aysa-op-v2-progress-label');
        var progressMetaEl = document.getElementById('aysa-op-v2-progress-meta');
        var progressPillEl = document.getElementById('aysa-op-v2-progress-pill');
        var paginationMetaEl = document.getElementById('aysa-op-v2-pagination-meta');
        var pagePrevEl = document.getElementById('aysa-op-v2-page-prev');
        var pageNextEl = document.getElementById('aysa-op-v2-page-next');

        var drawerEl = document.getElementById('aysa-op-v2-drawer');
        var drawerTitleEl = document.getElementById('aysa-op-v2-drawer-title');
        var drawerSubtitleEl = document.getElementById('aysa-op-v2-drawer-subtitle');
        var drawerGridEl = document.getElementById('aysa-op-v2-drawer-grid');
        var drawerHistoryEl = document.getElementById('aysa-op-v2-drawer-history');
        var drawerDecisionEl = document.getElementById('aysa-op-v2-drawer-decision');
        var drawerKeywordsEl = document.getElementById('aysa-op-v2-drawer-keywords');
        state.latestBilling = null;

        function notify(message, kind) {
            if (!statusEl) return;
            statusEl.style.display = 'block';
            statusEl.className = 'notice inline ' + (kind === 'error' ? 'notice-error' : 'notice-success');
            statusEl.querySelector('p').textContent = message;
        }

        function hideNotice() {
            if (statusEl) {
                statusEl.style.display = 'none';
            }
        }

        function request(action, payload) {
            payload = payload || {};
            payload.action = action;
            payload.nonce = nonce;
            payload.project_id = state.projectId;
            return $.post(ajaxUrl, payload);
        }

        function isOwnershipView() {
            return state.entityGroup === 'keyword_ownership';
        }

        function renderSummary(data) {
            var summary = data.summary || {};
            var cards = [
                { label: 'All Entities', value: summary.all || 0 },
                { label: 'SEO Optimized', value: summary.optimized || 0 },
                { label: 'SEO Not Optimized', value: summary.not_optimized || 0 },
                { label: 'To Be Published', value: summary.to_be_published || 0 },
                { label: 'Keyword Mapping Needed', value: summary.keyword_mapping_needed || 0 },
                { label: 'Keyword Validation', value: summary.keyword_validation_ready || 0 },
                { label: 'Meta Ready', value: summary.meta_ready || 0 },
                { label: 'Content Rewrite', value: summary.content_rewrite || 0 },
                { label: 'Apply Queue', value: summary.apply_queue || 0 },
                { label: 'Meta Applied', value: summary.meta_applied || 0 }
            ];
            summaryEl.innerHTML = cards.map(function(card) {
                return '<div class="aysa-op-v2-card"><div>' + card.label + '</div><div class="aysa-op-v2-card-value">' + card.value + '</div></div>';
            }).join('');
        }

        function renderTabs(data) {
            var groups = [
                ['page', 'Pages'],
                ['article', 'Articles'],
                ['ecommerce_category', 'Ecommerce Categories'],
                ['product', 'Products'],
                ['other', 'Others'],
                ['keyword_ownership', 'Keyword Ownership']
            ];
            var counts = (data.summary && data.summary.groups) || {};
            tabsEl.innerHTML = groups.map(function(group) {
                var key = group[0];
                var label = group[1];
                var active = state.entityGroup === key ? ' is-active' : '';
                return '<button type="button" class="aysa-op-v2-tab' + active + '" data-entity-group="' + key + '">' + label + ' <span>(' + (counts[key] || 0) + ')</span></button>';
            }).join('');
        }

        function renderFilters(data) {
            var filters = data.filters || {};
            var items = isOwnershipView()
                ? [
                    ['all', 'All'],
                    ['unique', 'Unique'],
                    ['conflict', 'Conflicts'],
                    ['needs_review', 'Needs Review']
                ]
                : [
                    ['all', 'All'],
                    ['optimized', 'SEO Optimized'],
                    ['not_optimized', 'SEO Not Optimized'],
                    ['to_be_published', 'To Be Published'],
                    ['keyword_mapping_needed', 'Keyword Mapping Needed'],
                    ['mapping_review', 'Mapping Review'],
                    ['keyword_validation_ready', 'Keyword Validation'],
                    ['meta_ready', 'Meta Ready'],
                    ['meta_applied', 'Meta Applied'],
                    ['rewrite_recommended', 'Rewrite Recommended'],
                    ['rewrite_review', 'Rewrite Review'],
                    ['apply_queue', 'Apply Queue'],
                    ['content_rewrite', 'Content Rewrite'],
                    ['meta_only', 'Meta Only']
                ];
            filtersEl.innerHTML = items.map(function(item) {
                var key = item[0];
                var label = item[1];
                var active = state.view === key ? ' is-active' : '';
                return '<button type="button" class="aysa-op-v2-chip' + active + '" data-filter-view="' + key + '">' + label + ' <span>(' + (filters[key] || 0) + ')</span></button>';
            }).join('');
        }

        function renderTableHeader() {
            if (!theadEl) return;
            var headers = isOwnershipView()
                ? ['Keyword', 'Owner URL', 'Owner Title', 'Owner Group', 'Status', 'Conflict Count', 'Next Step', 'Actions']
                : ['URL', 'Title', 'Publication State', 'SEO State', 'Optimization Scope', 'Main Keyword', 'Next Step', 'Actions'];
            theadEl.innerHTML = '<tr>' + headers.map(function(label) {
                return '<th>' + label + '</th>';
            }).join('') + '</tr>';
        }

        function renderRows(data) {
            var rows = data.rows || [];
            if (!rows.length) {
                tbodyEl.innerHTML = '<tr><td colspan="8" style="padding:24px;text-align:center;color:#646970;">No entities in this view.</td></tr>';
                return;
            }

            if (isOwnershipView()) {
                tbodyEl.innerHTML = rows.map(function(row) {
                    var actionHtml = '<button type="button" class="button button-small" data-row-action="open_owner">Open Owner</button>';
                    return '' +
                        '<tr class="aysa-op-v2-row" data-entity-key="' + String(row.owner_entity_key || row.entity_key || '') + '" data-ownership-key="' + String(row.ownership_key || '') + '" data-owner-group="' + String(row.owner_entity_group || row.entity_group || 'other') + '">' +
                            '<td>' + String(row.main_keyword || '—') + '</td>' +
                            '<td><a href="' + String(row.owner_url || row.url || '#') + '" target="_blank" rel="noreferrer noopener">' + String(row.owner_url || row.url || '') + '</a></td>' +
                            '<td>' + String(row.owner_title || row.title || '') + '</td>' +
                            '<td>' + labelize(row.owner_entity_group || row.entity_group || 'other') + '</td>' +
                            '<td><span class="aysa-op-v2-pill ' + (String(row.status || '') === 'unique' ? 'aysa-tone-green' : 'aysa-tone-yellow') + '">' + labelize(row.status || 'unique') + '</span></td>' +
                            '<td>' + String(row.conflict_count || 0) + '</td>' +
                            '<td>' + String(row.next_step || '—') + '</td>' +
                            '<td>' + actionHtml + '</td>' +
                        '</tr>';
                }).join('');
                return;
            }

            tbodyEl.innerHTML = rows.map(function(row) {
                var actionHtml = buildRowActionHtml(row);
                return '' +
                    '<tr class="aysa-op-v2-row" data-entity-key="' + String(row.entity_key || '') + '">' +
                        '<td><a href="' + String(row.url || '#') + '" target="_blank" rel="noreferrer noopener">' + String(row.url || '') + '</a></td>' +
                        '<td>' + String(row.title || '') + '</td>' +
                        '<td><span class="aysa-op-v2-pill ' + toneForPublication(row.publication_state) + '">' + labelize(row.publication_state) + '</span></td>' +
                        '<td><span class="aysa-op-v2-pill ' + toneForSeo(row.seo_state) + '">' + labelize(row.seo_state) + '</span></td>' +
                        '<td><span class="aysa-op-v2-pill ' + toneForScope(row.optimization_scope) + '">' + labelize(row.optimization_scope) + '</span></td>' +
                        '<td>' + String(row.main_keyword || '—') + '</td>' +
                        '<td>' + String(row.next_step || '—') + '</td>' +
                        '<td>' + actionHtml + '</td>' +
                    '</tr>';
            }).join('');
        }

        function buildRowActionHtml(row) {
            var actions = [];
            if (String(row.mapping_state || '') === 'mapping_review') {
                actions.push('<button type="button" class="button button-small" data-row-action="accept_mapping">Accept</button>');
                actions.push('<button type="button" class="button button-small" data-row-action="reject_mapping">Reject</button>');
            }
            if (String(row.meta_state || '') === 'generated') {
                actions.push('<button type="button" class="button button-small" data-row-action="apply_meta">Apply Meta</button>');
            }
            if (String(row.rewrite_state || '') === 'generated' || String(row.rewrite_state || '') === 'review_required' || String(row.output_state || '') === 'review_ready') {
                actions.push('<button type="button" class="button button-small" data-row-action="apply_rewrite">Apply Rewrite</button>');
            }
            if (String(row.main_keyword || '').trim() !== '' && String(row.mapping_state || '') !== 'mapping_review' && String(row.meta_state || '') === 'none' && String(row.rewrite_state || '') === 'not_needed') {
                actions.push('<button type="button" class="button button-small" data-row-action="validate_keywords">Validate</button>');
            }
            if (!actions.length) {
                actions.push('<button type="button" class="button button-small" data-row-action="refresh">Refresh</button>');
            } else {
                actions.push('<button type="button" class="button button-small" data-row-action="skip">Skip</button>');
            }
            return actions.join(' ');
        }

        function renderWorkspace(data) {
            workspace = data || {};
            var pagination = workspace.pagination || {};
            state.page = Number(pagination.page || state.page || 1);
            state.perPage = Number(pagination.per_page || state.perPage || 50);
            if (searchEl) {
                searchEl.value = state.search;
            }
            renderSummary(workspace);
            renderTabs(workspace);
            renderFilters(workspace);
            renderTableHeader();
            renderRows(workspace);
            renderPagination(workspace);
            renderProgress(state.activeRun || workspace.run || {});
            if (filterDescriptionEl) {
                filterDescriptionEl.textContent = isOwnershipView()
                    ? ('Keyword ownership filtered by ' + labelize(state.view) + (state.search ? (' and search "' + state.search + '"') : '') + '.')
                    : (labelize(state.entityGroup) + ' filtered by ' + labelize(state.view) + (state.search ? (' and search "' + state.search + '"') : '') + '.');
            }
            toggleRunButtons();
        }

        function renderPagination(data) {
            var pagination = data.pagination || {};
            var page = Number(pagination.page || 1);
            var pages = Number(pagination.pages || 1);
            var total = Number(pagination.total || 0);
            var perPage = Number(pagination.per_page || state.perPage || 50);
            var start = total ? (((page - 1) * perPage) + 1) : 0;
            var end = total ? Math.min(total, page * perPage) : 0;

            if (paginationMetaEl) {
                paginationMetaEl.textContent = total
                    ? ('Showing ' + start + '–' + end + ' of ' + total + ' entities. Page ' + page + ' of ' + pages + '.')
                    : 'No entities in this view.';
            }
            if (pagePrevEl) {
                pagePrevEl.disabled = page <= 1;
            }
            if (pageNextEl) {
                pageNextEl.disabled = page >= pages;
            }
        }

        function renderProgress(run) {
            if (!run || !run.status || run.status === 'idle') {
                progressWrapEl.style.display = 'none';
                return;
            }
            progressWrapEl.style.display = 'block';
            progressLabelEl.textContent = 'On-page run #' + String(run.run_id || run.id || 0);
            var billing = state.latestBilling || {};
            var billingText = billing.billing_scope ? (' Billing: ' + String(billing.billing_scope) + ' (' + String(billing.estimated_credits_cents || 0) + 'c est.)') : '';
            progressMetaEl.textContent = String(run.current_milestone || 'Run in progress.') + billingText;
            progressPillEl.className = 'aysa-op-v2-pill ' + (run.status === 'completed' ? 'aysa-tone-green' : (run.status === 'failed' ? 'aysa-tone-red' : 'aysa-tone-blue'));
            progressPillEl.textContent = labelize(run.status);
        }

        function syncActiveRun(run) {
            if (!run || !run.id) {
                state.activeRun = null;
                state.runId = 0;
                return;
            }

            state.activeRun = $.extend({}, state.activeRun || {}, run);
            state.runId = Number(run.id || state.runId || 0);
            renderProgress(state.activeRun);
        }

        function maybeNotifyRunStatus(run) {
            if (!run || !run.id || !run.status) {
                return;
            }

            var fingerprint = [String(run.id || 0), String(run.status || ''), String(run.current_milestone || '')].join(':');
            if (fingerprint === state.lastRunStatusNotified) {
                return;
            }
            state.lastRunStatusNotified = fingerprint;

            if (run.status === 'completed') {
                notify('On-page run #' + String(run.id) + ' completed.', 'success');
                return;
            }
            if (run.status === 'failed') {
                notify('On-page run #' + String(run.id) + ' failed.', 'error');
                return;
            }

            if (run.current_milestone) {
                notify('On-page run #' + String(run.id) + ': ' + String(run.current_milestone), 'success');
            }
        }

        function loadWorkspace(refresh) {
            return request('aysa_onpage_workspace', {
                entity_group: state.entityGroup,
                filters: JSON.stringify({ view: state.view, q: state.search }),
                page: state.page,
                per_page: state.perPage,
                refresh: refresh ? 1 : 0
            }).done(function(response) {
                if (!response || !response.success) {
                    notify((response && response.data) || 'Unable to load workspace.', 'error');
                    return;
                }
                hideNotice();
                renderWorkspace(response.data.workspace || {});
            }).fail(function(xhr) {
                notify((xhr.responseJSON && xhr.responseJSON.data) || 'Unable to load workspace.', 'error');
            });
        }

        function openDrawer(entityKey) {
            if (isOwnershipView()) {
                openOwnershipDrawer(entityKey);
                return;
            }
            state.currentEntityKey = entityKey || '';
            request('aysa_onpage_detail', { entity_key: state.currentEntityKey }).done(function(response) {
                if (!response || !response.success) {
                    notify((response && response.data) || 'Unable to load entity detail.', 'error');
                    return;
                }
                var detail = response.data.detail || {};
                var inventory = detail.inventory || {};
                var history = detail.seo_history || {};
                var keywords = detail.keywords || [];
                var metaPackage = detail.meta_package || {};
                var rewriteDecision = detail.rewrite_decision || {};
                var rewritePackage = detail.rewrite_package || {};

                drawerTitleEl.textContent = inventory.title || 'Entity Detail';
                drawerSubtitleEl.textContent = inventory.url || '';
                drawerGridEl.innerHTML = [
                    ['Entity Group', labelize(inventory.entity_group)],
                    ['Publication', labelize(inventory.publication_state)],
                    ['Mapping State', labelize(inventory.mapping_state)],
                    ['SEO State', labelize(inventory.seo_state)],
                    ['Optimization Scope', labelize(inventory.optimization_scope)],
                    ['Meta State', labelize(inventory.meta_state)],
                    ['Rewrite State', labelize(inventory.rewrite_state)],
                    ['Output State', labelize(inventory.output_state)],
                    ['Main Keyword', inventory.main_keyword || '—'],
                    ['Keyword Owner', inventory.keyword_owner_url || inventory.keyword_owner_entity_key || '—'],
                    ['Conflict Keyword', inventory.keyword_conflict_keyword || '—'],
                    ['Confidence', inventory.confidence_score || '—'],
                    ['Next Step', inventory.next_step || '—']
                ].map(function(item) {
                    return '<div class="aysa-op-v2-drawer-card"><div class="description">' + item[0] + '</div><strong>' + item[1] + '</strong></div>';
                }).join('');

                var historyBlocks = [];
                if (metaPackage && Object.keys(metaPackage).length) {
                    historyBlocks.push([
                        '<p><strong>Generated Meta Title:</strong> ' + String(metaPackage.meta_title || '—') + '</p>',
                        '<p><strong>Generated Meta Description:</strong> ' + String(metaPackage.meta_description || '—') + '</p>',
                        '<p><strong>H1 Suggestion:</strong> ' + String(metaPackage.h1_suggestion || '—') + '</p>'
                    ].join(''));
                }
                if (history && Object.keys(history).length) {
                    historyBlocks.push([
                        '<p><strong>Applied Meta Title:</strong> ' + String(history.meta_title || '—') + '</p>',
                        '<p><strong>Applied Meta Description:</strong> ' + String(history.meta_description || '—') + '</p>',
                        '<p><strong>Applied Content Title:</strong> ' + String(history.content_title || '—') + '</p>',
                        '<p><strong>Applied Content Description:</strong> ' + String(history.content_description || '—').slice(0, 300) + '</p>'
                    ].join(''));
                }
                drawerHistoryEl.innerHTML = historyBlocks.length ? historyBlocks.join('') : '<p class="description">No generated or applied AYSA output found for this entity.</p>';

                var decisionBlocks = [
                    '<p><strong>Reason:</strong> ' + String(inventory.decision_reason || '—') + '</p>',
                    '<p><strong>Comparison Result:</strong> ' + String(inventory.comparison_result || '—') + '</p>',
                    '<p><strong>Conflict Reason:</strong> ' + String(inventory.keyword_conflict_reason || '—') + '</p>',
                    '<p><strong>Run ID:</strong> ' + String(inventory.worker_run_id || '—') + '</p>'
                ];
                if (rewriteDecision && Object.keys(rewriteDecision).length) {
                    decisionBlocks.push('<hr style="margin:12px 0;">');
                    decisionBlocks.push('<p><strong>Rewrite Needed:</strong> ' + String(rewriteDecision.rewrite_needed ? 'Yes' : 'No') + '</p>');
                    decisionBlocks.push('<p><strong>Rewrite Mode:</strong> ' + String(rewriteDecision.rewrite_mode || 'conservative') + '</p>');
                    decisionBlocks.push('<p><strong>Rewrite Reason:</strong> ' + String(rewriteDecision.rewrite_reason || rewriteDecision.decision_reason || '—') + '</p>');
                    decisionBlocks.push('<p><strong>Content Gaps:</strong> ' + ((rewriteDecision.content_gaps || []).join(', ') || '—') + '</p>');
                    decisionBlocks.push('<p><strong>Recommended Sections:</strong> ' + ((rewriteDecision.recommended_sections || []).join(', ') || '—') + '</p>');
                }
                if (rewritePackage && Object.keys(rewritePackage).length) {
                    decisionBlocks.push('<hr style="margin:12px 0;">');
                    decisionBlocks.push('<p><strong>Draft Content Title:</strong> ' + String(rewritePackage.content_title || '—') + '</p>');
                    decisionBlocks.push('<p><strong>Draft Summary:</strong> ' + String(rewritePackage.content_description || '—') + '</p>');
                    decisionBlocks.push('<p><strong>Suggested Headings:</strong> ' + ((rewritePackage.suggested_headings || []).join(', ') || '—') + '</p>');
                    decisionBlocks.push('<p><strong>FAQ Candidates:</strong> ' + ((rewritePackage.faq_candidates || []).join(', ') || '—') + '</p>');
                    decisionBlocks.push('<p><strong>Draft Confidence:</strong> ' + String(rewritePackage.confidence_score || '—') + '</p>');
                }
                drawerDecisionEl.innerHTML = decisionBlocks.join('');
                var keywordPills = keywords.length ? keywords.map(function(keyword) {
                    return '<span class="aysa-op-v2-pill aysa-tone-neutral" style="margin-right:6px;margin-bottom:6px;">' + keyword + '</span>';
                }).join('') : '';
                var rewritePreview = rewritePackage && rewritePackage.rewritten_content
                    ? '<div style="margin-top:12px;"><strong>Draft Preview</strong><div class="description" style="margin-top:6px;max-height:280px;overflow:auto;border:1px solid #e0e2e7;border-radius:8px;padding:12px;background:#fff;">' + String(rewritePackage.rewritten_content) + '</div></div>'
                    : '';
                drawerKeywordsEl.innerHTML = (keywordPills || '<p class="description">No mapped keywords.</p>') + rewritePreview;
                drawerEl.classList.add('is-open');
            }).fail(function(xhr) {
                notify((xhr.responseJSON && xhr.responseJSON.data) || 'Unable to load entity detail.', 'error');
            });
        }

        function openOwnershipDrawer(entityKey) {
            var rows = workspace.rows || [];
            var row = rows.find(function(item) {
                return String(item.owner_entity_key || item.entity_key || '') === String(entityKey || '');
            });
            if (!row) {
                return;
            }

            state.currentEntityKey = String(row.owner_entity_key || row.entity_key || '');
            drawerTitleEl.textContent = row.main_keyword || 'Keyword Ownership';
            drawerSubtitleEl.textContent = row.owner_url || row.url || '';
            drawerGridEl.innerHTML = [
                ['Owner Title', row.owner_title || row.title || '—'],
                ['Owner URL', row.owner_url || row.url || '—'],
                ['Owner Group', labelize(row.owner_entity_group || row.entity_group || 'other')],
                ['Status', labelize(row.status || 'unique')],
                ['Conflict Count', String(row.conflict_count || 0)],
                ['Next Step', row.next_step || '—']
            ].map(function(item) {
                return '<div class="aysa-op-v2-drawer-card"><div class="description">' + item[0] + '</div><strong>' + item[1] + '</strong></div>';
            }).join('');

            var conflicts = row.conflicting_entities || [];
            drawerHistoryEl.innerHTML = conflicts.length ? conflicts.map(function(conflict) {
                var url = String(conflict.url || '');
                return '<p><strong>' + String(conflict.title || '—') + '</strong><br><span class="description">' +
                    labelize(conflict.entity_group || 'other') + ' · ' + labelize(conflict.mapping_state || 'unknown') +
                    '</span><br><a href="' + url + '" target="_blank" rel="noreferrer noopener">' + url + '</a></p>';
            }).join('') : '<p class="description">No conflicting entities for this keyword.</p>';
            drawerDecisionEl.innerHTML = [
                '<p><strong>Owner Entity Key:</strong> ' + String(row.owner_entity_key || row.entity_key || '—') + '</p>',
                '<p><strong>Status:</strong> ' + String(row.status || 'unique') + '</p>'
            ].join('');
            drawerKeywordsEl.innerHTML = '<span class="aysa-op-v2-pill aysa-tone-neutral">' + String(row.main_keyword || '—') + '</span>';
            drawerEl.classList.add('is-open');
        }

        function closeDrawer() {
            drawerEl.classList.remove('is-open');
        }

        function startRun(runType, selection) {
            if (isOwnershipView()) {
                notify('Worker runs are disabled in Keyword Ownership view. Switch to an entity tab to run actions.', 'error');
                return;
            }
            request('aysa_onpage_start_run', {
                entity_group: state.entityGroup,
                filters: JSON.stringify({ view: state.view, q: state.search }),
                page: state.page,
                per_page: state.perPage,
                run_type: runType,
                selection: selection || []
            }).done(function(response) {
                if (!response || !response.success) {
                    notify((response && response.data && response.data.message) || 'Unable to start run.', 'error');
                    return;
                }
                hideNotice();
                var status = response.data.status || {};
                var run = status.run || {};
                state.latestBilling = status.billing || null;
                state.lastRunStatusNotified = '';
                syncActiveRun(run);
                state.afterEventId = 0;
                renderWorkspace(response.data.workspace || workspace);
                maybeNotifyRunStatus(run);
                startPolling();
            }).fail(function(xhr) {
                var data = xhr.responseJSON && xhr.responseJSON.data;
                notify((data && data.message) || 'Unable to start run.', 'error');
            });
        }

        function runBatchAction(batchAction, selection) {
            if (isOwnershipView()) {
                notify('Batch actions are disabled in Keyword Ownership view. Switch to an entity tab to continue.', 'error');
                return;
            }
            request('aysa_onpage_batch_action', {
                entity_group: state.entityGroup,
                filters: JSON.stringify({ view: state.view, q: state.search }),
                page: state.page,
                per_page: state.perPage,
                batch_action: batchAction,
                selection: selection || []
            }).done(function(response) {
                if (!response || !response.success) {
                    notify((response && response.data && response.data.message) || 'Unable to apply batch action.', 'error');
                    return;
                }
                hideNotice();
                renderWorkspace(response.data.workspace || workspace);
                var result = response.data.result || {};
                notify(
                    'Batch ' + labelize(batchAction) + ': applied ' + String(result.applied || 0)
                    + ', failed ' + String(result.failed || 0)
                    + ', skipped ' + String(result.skipped || 0) + '.',
                    'success'
                );
            }).fail(function(xhr) {
                var data = xhr.responseJSON && xhr.responseJSON.data;
                notify((data && data.message) || 'Unable to apply batch action.', 'error');
            });
        }

        function runEntityAction(rowAction) {
            if (isOwnershipView()) {
                if (rowAction === 'open_owner' && state.currentEntityKey) {
                    var ownerRow = document.querySelector('.aysa-op-v2-row[data-entity-key="' + CSS.escape(state.currentEntityKey) + '"]');
                    var ownerGroup = ownerRow ? String(ownerRow.getAttribute('data-owner-group') || 'page') : 'page';
                    closeDrawer();
                    state.entityGroup = ownerGroup;
                    state.view = 'all';
                    state.search = '';
                    loadWorkspace(false).done(function() {
                        openDrawer(state.currentEntityKey);
                    });
                }
                return;
            }
            request('aysa_onpage_entity_action', {
                entity_group: state.entityGroup,
                filters: JSON.stringify({ view: state.view, q: state.search }),
                page: state.page,
                per_page: state.perPage,
                entity_key: state.currentEntityKey,
                row_action: rowAction
            }).done(function(response) {
                if (!response || !response.success) {
                    notify((response && response.data && response.data.message) || 'Unable to apply entity action.', 'error');
                    return;
                }
                hideNotice();
                if (response.data.status) {
                    var run = response.data.status.run || {};
                    state.runId = Number(run.id || 0);
                    state.afterEventId = 0;
                    startPolling();
                }
                if (response.data.workspace) {
                    renderWorkspace(response.data.workspace);
                }
                if (response.data.detail) {
                    openDrawer(state.currentEntityKey);
                }
            }).fail(function(xhr) {
                var data = xhr.responseJSON && xhr.responseJSON.data;
                notify((data && data.message) || 'Unable to apply entity action.', 'error');
            });
        }

        function pollStatus() {
            if (!state.runId) return;
            request('aysa_onpage_run_status', {
                entity_group: state.entityGroup,
                filters: JSON.stringify({ view: state.view, q: state.search }),
                page: state.page,
                per_page: state.perPage,
                run_id: state.runId,
                after_event_id: state.afterEventId
            }).done(function(response) {
                if (!response || !response.success) {
                    return;
                }
                var status = response.data.status || {};
                var run = status.run || {};
                state.latestBilling = status.billing || state.latestBilling;
                 syncActiveRun(run);
                if (response.data.workspace) {
                    renderWorkspace(response.data.workspace);
                }
                var events = status.events || [];
                if (events.length) {
                    state.afterEventId = Number(events[events.length - 1].id || state.afterEventId);
                }
                maybeNotifyRunStatus(run);
                if (!run.id || run.status === 'completed' || run.status === 'failed') {
                    stopPolling();
                    loadWorkspace(true);
                }
            });
        }

        function startPolling() {
            stopPolling();
            state.polling = window.setInterval(pollStatus, 3000);
            pollStatus();
        }

        function stopPolling() {
            if (state.polling) {
                window.clearInterval(state.polling);
                state.polling = null;
            }
            if (state.activeRun && (state.activeRun.status === 'completed' || state.activeRun.status === 'failed')) {
                state.activeRun = null;
            }
        }

        tabsEl.addEventListener('click', function(event) {
            var target = event.target.closest('[data-entity-group]');
            if (!target) return;
            state.entityGroup = target.getAttribute('data-entity-group') || 'page';
            state.view = 'all';
            state.page = 1;
            loadWorkspace(false);
        });

        filtersEl.addEventListener('click', function(event) {
            var target = event.target.closest('[data-filter-view]');
            if (!target) return;
            state.view = target.getAttribute('data-filter-view') || 'all';
            state.page = 1;
            loadWorkspace(false);
        });

        if (searchEl) {
            var searchTimer = null;
            searchEl.addEventListener('input', function() {
                state.search = String(searchEl.value || '').trim();
                state.page = 1;
                if (searchTimer) {
                    window.clearTimeout(searchTimer);
                }
                searchTimer = window.setTimeout(function() {
                    loadWorkspace(false);
                }, 250);
            });
        }

        if (pagePrevEl) {
            pagePrevEl.addEventListener('click', function() {
                if (state.page <= 1) return;
                state.page -= 1;
                loadWorkspace(false);
            });
        }

        if (pageNextEl) {
            pageNextEl.addEventListener('click', function() {
                var pagination = workspace.pagination || {};
                var pages = Number(pagination.pages || 1);
                if (state.page >= pages) return;
                state.page += 1;
                loadWorkspace(false);
            });
        }

        tbodyEl.addEventListener('click', function(event) {
            var actionEl = event.target.closest('[data-row-action]');
            if (actionEl) {
                event.preventDefault();
                event.stopPropagation();
                var actionRow = event.target.closest('.aysa-op-v2-row');
                if (actionRow) {
                    state.currentEntityKey = actionRow.getAttribute('data-entity-key') || '';
                }
                runEntityAction(actionEl.getAttribute('data-row-action') || 'refresh');
                return;
            }
            var row = event.target.closest('.aysa-op-v2-row');
            if (!row) return;
            openDrawer(row.getAttribute('data-entity-key') || '');
        });

        drawerEl.addEventListener('click', function(event) {
            if (event.target.closest('[data-close="1"]')) {
                closeDrawer();
            }
            var actionEl = event.target.closest('[data-row-action]');
            if (actionEl) {
                runEntityAction(actionEl.getAttribute('data-row-action') || 'refresh');
            }
        });

        $('#aysa-op-v2-refresh').on('click', function() { loadWorkspace(true); });
        $('#aysa-op-v2-refresh-status').on('click', function() { pollStatus(); });
        $('#aysa-op-v2-mapping-sync').on('click', function() { startRun('mapping_sync', []); });
        $('#aysa-op-v2-mapping-autofill').on('click', function() { startRun('mapping_autofill', []); });
        $('#aysa-op-v2-validate-keywords').on('click', function() { startRun('keyword_validate_for_page', []); });
        $('#aysa-op-v2-generate-meta').on('click', function() { startRun('meta_generate', []); });
        $('#aysa-op-v2-decide-rewrite').on('click', function() { startRun('rewrite_decide', []); });
        $('#aysa-op-v2-generate-rewrite').on('click', function() { startRun('rewrite_generate', []); });
        $('#aysa-op-v2-apply-meta').on('click', function() { runBatchAction('apply_meta', []); });
        $('#aysa-op-v2-apply-rewrite').on('click', function() { runBatchAction('apply_rewrite', []); });
        $('#aysa-op-v2-reconcile').on('click', function() { startRun('output_reconcile', []); });

        function toggleRunButtons() {
            var disabled = isOwnershipView();
            ['#aysa-op-v2-mapping-sync', '#aysa-op-v2-mapping-autofill', '#aysa-op-v2-validate-keywords', '#aysa-op-v2-generate-meta', '#aysa-op-v2-decide-rewrite', '#aysa-op-v2-generate-rewrite', '#aysa-op-v2-apply-meta', '#aysa-op-v2-apply-rewrite', '#aysa-op-v2-reconcile'].forEach(function(selector) {
                var el = document.querySelector(selector);
                if (!el) return;
                el.disabled = disabled;
            });
        }

        renderWorkspace(workspace);
        loadWorkspace(false);
        if (workspace.run && workspace.run.id && workspace.run.status && workspace.run.status !== 'completed' && workspace.run.status !== 'failed') {
            state.runId = Number(workspace.run.id || 0);
            startPolling();
        }
    });
})(jQuery);
