/**
 * Rank Booster — Processing Module
 *
 * Polls the server for session status every 4 seconds.
 * Renders the processing log and action buttons (Summary, Preview, Push Live).
 * No direct API calls — all processing happens server-side via Action Scheduler.
 */
(function($) {
    'use strict';

    window.RankBoosterProcessing = window.RankBoosterProcessing || {};

    var pollTimer = null;
    var sessionId = null;
    var renderedLogCounts = {}; // job_id → number of log entries already rendered

    /* ════════════════════════════════════════════
       Start / stop polling
       ════════════════════════════════════════════ */

    RankBoosterProcessing.startPolling = function(sid) {
        sessionId = sid;
        renderedLogCounts = {};
        $('#rb-processing-log').empty().append(
            '<div class="rb-log-entry">Booting up…</div>'
        );
        $('#rb-locked-table-area').empty();
        $('#rb-processing-area .rb-processing-header h3').text('Processing…');
        $('#rb-abort-btn').show().prop('disabled', false).text('⛔ Abort Processing');
        $('#rb-optimize-more').parent().remove();
        poll();
    };

    RankBoosterProcessing.stopPolling = function() {
        if (pollTimer) clearTimeout(pollTimer);
        pollTimer = null;
    };

    function poll() {
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_session_status',
            nonce: rank_ajax_obj.nonce,
            session_id: sessionId,
        }, function(resp) {
            if (!resp.success) {
                console.warn('[RankBooster] Poll error:', resp.data);
                appendLogRaw('⚠ Error polling status: ' + (resp.data ? resp.data.message : 'unknown'));
                scheduleNextPoll();
                return;
            }

            // Compact status summary — only log active/problem jobs
            var jobs = resp.data.jobs || [];
            var counts = {};
            jobs.forEach(function(j) {
                counts[j.status] = (counts[j.status] || 0) + 1;
            });
            console.log('[RankBooster] Poll: ' + Object.keys(counts).map(function(s){ return s + '=' + counts[s]; }).join(' ') + ' all_complete=' + resp.data.all_complete);

            renderStatus(resp.data);

            // Update AI credits display after each poll
            if (resp.data.credits && window.RankBooster && window.RankBooster.updateCreditStatus) {
                window.RankBooster.updateCreditStatus(resp.data.credits);
            }

            if (resp.data.all_complete) {
                RankBoosterProcessing.stopPolling();
                $('#rb-abort-btn').hide();
                $('#rb-processing-area .rb-processing-header h3').text('Processing complete');
                // Unlock the table so buttons are clickable
                $('.rb-table-locked').removeClass('rb-table-locked');
                // Show "Optimize more pages" button
                if ($('#rb-optimize-more').length === 0) {
                    $('#rb-processing-area').after(
                        '<p style="margin-top:16px;"><a href="#" id="rb-optimize-more" class="button button-primary">Back to overview</a></p>'
                    );
                    $('#rb-optimize-more').on('click', function(e) {
                        e.preventDefault();
                        // Reset state
                        if (window.RankBooster && window.RankBooster.state) {
                            window.RankBooster.state.rows = [];
                            window.RankBooster.state.sessionId = null;
                        }
                        // Reset UI
                        $('#rb-processing-area').hide();
                        $('#rb-table-area').hide();
                        $('#rb-active-banner').hide();
                        $(this).parent().remove();
                        $('#rb-urls').val('');
                        $('#rb-url-input-area').show();
                        $('#rb-v8-info').show();
                    });
                }
            } else {
                // Ensure abort button stays visible while processing
                $('#rb-processing-area .rb-processing-header h3').text('Processing…');
                $('#rb-abort-btn').show().prop('disabled', false);
                scheduleNextPoll();
            }
        }).fail(function() {
            console.error('[RankBooster] Poll network error');
            appendLogRaw('⚠ Network error — retrying…');
            scheduleNextPoll();
        });
    }

    function scheduleNextPoll() {
        pollTimer = setTimeout(poll, 4000);
    }

    /* ════════════════════════════════════════════
       Render status update
       ════════════════════════════════════════════ */

    function toLocalTime(t) {
        if (!t || t.slice(-1) !== 'Z') return t; // old entries without Z display as-is
        var d = new Date(new Date().toISOString().slice(0, 10) + 'T' + t);
        return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false });
    }

    function renderStatus(data) {
        var $log = $('#rb-processing-log');

        // Render log entries for each job
        data.jobs.forEach(function(job) {
            var prevCount = renderedLogCounts[job.id] || 0;
            var entries = job.log_entries || [];

            // Render only new entries
            for (var i = prevCount; i < entries.length; i++) {
                var e = entries[i];
                var cssClass = 'rb-log-entry';
                if (e.message.indexOf('✓') === 0) cssClass += ' rb-log-success';
                else if (e.message.indexOf('✗') === 0 || e.message.indexOf('⛔') === 0) cssClass += ' rb-log-error';
                else if (e.message.indexOf('⟳') === 0) cssClass += ' rb-log-running';

                $log.append(
                    '<div class="' + cssClass + '">' +
                    '<span class="rb-log-time">[' + toLocalTime(e.time) + ']</span> ' +
                    escapeHtml(e.message) +
                    '</div>'
                );
            }
            renderedLogCounts[job.id] = entries.length;
        });

        // Auto-scroll log
        $log.scrollTop($log[0].scrollHeight);

        // Render locked table with action buttons
        renderLockedTable(data.jobs);
    }

    /* ════════════════════════════════════════════
       Locked table with action buttons
       ════════════════════════════════════════════ */

    function renderLockedTable(jobs) {
        var $area = $('#rb-locked-table-area');
        var $table = $area.find('table');

        if (!$table.length) {
            $table = $(
                '<table class="wp-list-table widefat fixed striped">' +
                '<thead><tr>' +
                '<th style="width:34%;">URL</th><th style="width:9%;">Mode</th><th style="width:8%;">Credits</th><th style="width:9%;">Status</th><th style="width:40%; text-align:right;">Actions</th>' +
                '</tr></thead><tbody></tbody></table>'
            );
            $area.append($table);
        }

        var $tbody = $table.find('tbody').empty();

        jobs.forEach(function(job) {
            var $tr = $('<tr>').attr('data-job-id', job.id);

            // URL
            $tr.append($('<td>').html('<a href="' + job.url + '" target="_blank">' + job.url + '</a>'));

            // Mode
            $tr.append($('<td>').text(job.mode === 'automatic' ? 'Automatic' : 'Manual'));

            // Credits
            $tr.append($('<td>').text(job.credits_used));

            // Status
            var statusText = job.status;
            if (job.status === 'pushed_live') statusText = 'Live';
            else if (job.status === 'completed') statusText = 'Completed';
            else if (job.status === 'processing') statusText = 'Processing…';
            else if (job.status === 'queued') statusText = 'Queued';
            else if (job.status === 'failed') statusText = 'Failed';
            else if (job.status === 'aborted') statusText = 'Aborted';

            var $status = $('<td>').text(statusText);
            if (job.status === 'failed') $status.css('color', '#d63638');
            if (job.status === 'aborted') $status.css('color', '#996800');
            $tr.append($status);

            // Actions
            var $actions = $('<td class="rb-action-btns">');

            if (job.status === 'completed' || job.status === 'pushed_live') {
                // Summary
                if (job.id) {
                    var $sumBtn = $('<button class="button button-small">Summary</button>');
                    $sumBtn.on('click', function() { showSummary(job.id); });
                    $actions.append($sumBtn);

                    // Content — view + copy final optimized HTML
                    if (job.has_draft) {
                        var $contentBtn = $('<button class="button button-small">Content</button>');
                        $contentBtn.on('click', function() { showContent(job.id); });
                        $actions.append($contentBtn);
                    }
                }
            }

            if (job.status === 'completed' && job.has_draft) {
                // Category (term) pages have no editor/preview — Push Live only.
                if (job.object_type !== 'term') {
                    // Preview
                    var $prevBtn = $('<button class="button button-small">Preview</button>');
                    $prevBtn.on('click', function() { RankBooster.previewJob(job.id); });
                    $actions.append($prevBtn);

                    // Edit Draft — opens WP editor with AI content injected.
                    // Skipped for builders that load their tree outside post
                    // meta (Breakdance) or render from custom fields; those use
                    // Preview + Push Live instead.
                    if (['breakdance', 'customfields'].indexOf(job.editor_type) === -1) {
                        var $editBtn = $('<button class="button button-small" title="Opens the WP editor with AI draft loaded. Nothing is saved until you click Update.">Edit Draft</button>');
                        $editBtn.on('click', function() {
                            RankBooster.editDraft(job.id, $editBtn, job.post_id, job.editor_type);
                        });
                        $actions.append($editBtn);
                    }
                }

                // Push Live
                var $pushBtn = $('<button class="button button-small button-primary">Push Live</button>');
                $pushBtn.on('click', function() {
                    RankBooster.pushLiveJob(job.id, $pushBtn, $tr);
                });
                $actions.append($pushBtn);
            }

            if (job.status === 'pushed_live') {
                $actions.append($('<a class="rb-live-link" href="' + job.url + '" target="_blank">View live →</a>'));
            }

            if (job.error) {
                $actions.append($('<small style="color:#d63638;">').text(job.error));
            }

            $tr.append($actions);
            $tbody.append($tr);
        });

    }

    /* ════════════════════════════════════════════
       Bulk push live
       ════════════════════════════════════════════ */

    function renderBulkPushLive(jobs) {
        var $existing = $('#rb-bulk-push-live');
        if (!$existing.length) {
            $existing = $('<div id="rb-bulk-push-live" style="padding:12px 0;">');
            $('#rb-locked-table-area').append($existing);
        }

        var $btn = $('<button class="button button-primary">Push all ' + jobs.length + ' pages live</button>');
        $btn.on('click', function() {
            $btn.prop('disabled', true).text('Pushing…');
            bulkPushLive(jobs, 0, $btn);
        });

        $existing.empty().append($btn);
    }

    function bulkPushLive(jobs, idx, $btn) {
        if (idx >= jobs.length) {
            $btn.text('All pushed live ✓').prop('disabled', true);
            // Re-poll to refresh table
            poll();
            return;
        }

        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_push_live',
            nonce: rank_ajax_obj.nonce,
            job_id: jobs[idx].id,
        }, function(resp) {
            $btn.text('Pushing… (' + (idx + 1) + '/' + jobs.length + ')');
            bulkPushLive(jobs, idx + 1, $btn);
        }).fail(function() {
            bulkPushLive(jobs, idx + 1, $btn);
        });
    }

    /* ════════════════════════════════════════════
       Summary modal
       ════════════════════════════════════════════ */

    function showSummary(jobId) {
        // Single AJAX call to get full session data including summary_html
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_session',
            nonce: rank_ajax_obj.nonce,
            session_id: sessionId,
        }, function(resp) {
            if (!resp.success) return;
            var job = resp.data.jobs.find(function(j) { return j.id === jobId; });
            if (job && job.summary_html) {
                $('#rb-summary-body').html(job.summary_html);
            } else {
                $('#rb-summary-body').html('<p>No summary available.</p>');
            }
            $('#rb-summary-modal').show();
        });
    }

    /* ════════════════════════════════════════════
       Content modal — view + copy final HTML
       ════════════════════════════════════════════ */

    function showContent(jobId) {
        $.post(rank_ajax_obj.ajax_url, {
            action: 'rank_booster_get_session',
            nonce: rank_ajax_obj.nonce,
            session_id: sessionId,
        }, function(resp) {
            if (!resp.success) return;
            var job = resp.data.jobs.find(function(j) { return j.id === jobId; });
            var html = (job && job.draft_content) ? job.draft_content : '';
            if (html) {
                $('#rb-content-rendered').html(html);
                $('#rb-content-html').val(html);
            } else {
                $('#rb-content-rendered').html('<p>No content available.</p>');
                $('#rb-content-html').val('');
            }
            $('#rb-content-copy').text('Copy HTML');
            $('#rb-content-modal').show();
        });
    }

    /* ════════════════════════════════════════════
       Abort button
       ════════════════════════════════════════════ */

    $(document).ready(function() {
        $('#rb-abort-btn').on('click', function() {
            if (!confirm('Are you sure? Already completed pages will keep their results.')) return;

            var $btn = $(this);
            $btn.prop('disabled', true).text('Aborting…');

            $.post(rank_ajax_obj.ajax_url, {
                action: 'rank_booster_abort_session',
                nonce: rank_ajax_obj.nonce,
                session_id: sessionId,
            }, function(resp) {
                RankBoosterProcessing.stopPolling();
                $btn.hide();
                // Do one final poll to refresh status (server adds the abort log entry)
                poll();
            });
        });

        // Copy the optimized content to the clipboard from the Content modal.
        // We write BOTH flavors at once so it pastes correctly everywhere:
        //   • text/html  → WYSIWYG editors (Gutenberg, TinyMCE) paste it rendered.
        //   • text/plain → plain-text editors paste the raw HTML source.
        $(document).on('click', '#rb-content-copy', function() {
            var $btn = $(this);
            var html = $('#rb-content-html').val();
            if (!html) return;

            function done() {
                $btn.text('Copied ✓');
                setTimeout(function() { $btn.text('Copy HTML'); }, 2000);
            }

            // Preferred: ClipboardItem with dual flavors (rendered + source).
            if (window.ClipboardItem && navigator.clipboard && navigator.clipboard.write) {
                var item = new ClipboardItem({
                    'text/html': new Blob([html], { type: 'text/html' }),
                    'text/plain': new Blob([html], { type: 'text/plain' }),
                });
                navigator.clipboard.write([item]).then(done).catch(fallbackCopy);
            } else {
                fallbackCopy();
            }

            // Fallback: rich copy via a contenteditable selection, which most
            // browsers translate into both text/html and text/plain on copy.
            function fallbackCopy() {
                var $rich = $('<div contenteditable="true" style="position:fixed;left:-9999px;top:0;"></div>')
                    .html(html)
                    .appendTo('body');

                var range = document.createRange();
                range.selectNodeContents($rich[0]);
                var sel = window.getSelection();
                sel.removeAllRanges();
                sel.addRange(range);

                try { document.execCommand('copy'); } catch (e) {}

                sel.removeAllRanges();
                $rich.remove();
                done();
            }
        });

        // Re-poll once when user returns to this tab (e.g. after Elementor publish).
        // This refreshes job statuses so pushed_live is reflected.
        document.addEventListener('visibilitychange', function() {
            if (!document.hidden && sessionId && !pollTimer) {
                poll();
            }
        });
    });

    /* ════════════════════════════════════════════
       Helpers
       ════════════════════════════════════════════ */

    function appendLogRaw(msg) {
        var time = new Date().toTimeString().substr(0, 8);
        $('#rb-processing-log').append(
            '<div class="rb-log-entry rb-log-error"><span class="rb-log-time">[' + time + ']</span> ' + escapeHtml(msg) + '</div>'
        );
    }

    function escapeHtml(str) {
        return $('<div>').text(str).html();
    }

})(jQuery);
