<?php
/**
 * Post Content Scanner Renderer - Main Orchestration
 *
 * Renders the Post Content Scanner UI section on the Media Manager page.
 * State management + render delegation to components and assets.
 *
 * @package StaticQ
 * @since 3.3.0
 */

if (!defined('ABSPATH')) {
    exit;
}

require_once __DIR__ . '/class-sqmedia-post-content-scanner-renderer-components.php';

class SQMedia_Post_Content_Scanner_Renderer {

    const STATUS_NOT_SCANNED = 'not_scanned';
    const STATUS_SCANNING = 'scanning';
    const STATUS_PAUSED = 'paused';
    const STATUS_CLEAN = 'clean';
    const STATUS_ISSUES = 'issues';
    const STATUS_FIXING = 'fixing';

    private SQMedia_Database $db;
    private SQMedia_Post_Content_Scanner_Renderer_Components $components;

    public function __construct() {
        $this->db = sqmedia()->get_database();
        $this->components = new SQMedia_Post_Content_Scanner_Renderer_Components($this, $this->db);
    }

    /**
     * Render the complete Post Content Scanner section
     */
    public function render(): void {
        $state = $this->get_state();
        wp_enqueue_style('sqmedia-post-content-scanner', SQMEDIA_PLUGIN_URL . 'admin/css/sqmedia-post-content-scanner.css', [], SQMEDIA_VERSION);
        ?>
        <div class="sqmedia-section sqmedia-post-content-scanner">
            <h2>📝 <?php esc_html_e('Post Content Scanner', 'staticq-media'); ?></h2>
            <?php $this->components->render_card($state); ?>
        </div>
        <?php $this->render_scripts($state); ?>
        <?php
    }

    /**
     * Get current scanner state
     */
    public function get_state(): array {
        // Check for running/paused scan
        $active = $this->db->get_active_scan('post_content');
        if ($active) {
            $status_map = [
                'pending' => self::STATUS_SCANNING,
                'running' => self::STATUS_SCANNING,
                'scanning' => self::STATUS_SCANNING,
                'paused' => self::STATUS_PAUSED,
                'fixing' => self::STATUS_FIXING,
            ];
            return [
                'status' => $status_map[$active->status] ?? self::STATUS_SCANNING,
                'scan_id' => $active->scan_id,
                'total_scanned' => (int) $active->total_items,
                'processed' => (int) $active->processed_items,
                'results' => $active->results,
            ];
        }

        // Check for last completed scan
        $last = $this->get_last_scan();
        if (!$last) {
            return ['status' => self::STATUS_NOT_SCANNED, 'scan_id' => null, 'results' => null];
        }

        $results = $last->results;
        $issue_counts = $this->db->get_scan_item_counts($last->scan_id);
        $total_issues = array_sum($issue_counts);

        // Compute fixable issues
        $unfixable = [SQMedia_Post_Content_Scanner::CAT_DELETED_ATTACHMENT, SQMedia_Post_Content_Scanner::CAT_BROKEN_URL];
        $fixable_issues = $total_issues;
        foreach ($unfixable as $cat) {
            $fixable_issues -= ($issue_counts[$cat] ?? 0);
        }

        $posts_with_issues = $this->db->get_scan_attachments_with_issues($last->scan_id);

        $status = $total_issues === 0 ? self::STATUS_CLEAN : self::STATUS_ISSUES;

        return [
            'status' => $status,
            'scan_id' => $last->scan_id,
            'scanned_at' => $last->scan_completed ?? $last->scan_started,
            'total_scanned' => (int) $last->total_items,
            'duration' => $this->calculate_duration($last->scan_started, $last->scan_completed),
            'results' => $results,
            'issue_counts' => $issue_counts,
            'total_issues' => $total_issues,
            'fixable_issues' => $fixable_issues,
            'posts_with_issues' => $posts_with_issues,
        ];
    }

    /**
     * Get last completed post_content scan
     */
    private function get_last_scan(): ?object {
        global $wpdb;
        $table = SQMedia_Database::get_table(SQMedia_Database::TABLE_SCANS);

        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $row = $wpdb->get_row(
            "SELECT * FROM {$table}
             WHERE scan_type = 'post_content'
             AND status = 'completed'
             ORDER BY scan_completed DESC
             LIMIT 1"
        );
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter

        if ($row) {
            $row->results = json_decode($row->results, true) ?: [];
        }
        return $row;
    }

    /**
     * Calculate scan duration string
     */
    private function calculate_duration(?string $start, ?string $end): string {
        if (!$start || !$end) {
            return '';
        }
        $diff = strtotime($end) - strtotime($start);
        if ($diff < 0) {
            return '';
        }
        if ($diff < 60) {
            // translators: %s: number of seconds
            return sprintf(__('%ss', 'staticq-media'), $diff);
        }
        if ($diff < 3600) {
            $minutes = floor($diff / 60);
            $seconds = $diff % 60;
            // translators: %1$s: minutes, %2$s: seconds
            return sprintf(__('%1$sm %2$ss', 'staticq-media'), $minutes, $seconds);
        }
        $hours = floor($diff / 3600);
        $minutes = floor(($diff % 3600) / 60);
        // translators: %1$s: hours, %2$s: minutes
        return sprintf(__('%1$sh %2$sm', 'staticq-media'), $hours, $minutes);
    }

    /**
     * Render inline JavaScript for the Post Content Scanner
     */
    private function render_scripts(array $state): void {
        $status = $state['status'];
        $scan_id = $state['scan_id'] ?? '';
        ob_start();
        ?>
        jQuery(document).ready(function($) {
            var pcsStatus = '<?php echo esc_js($status); ?>';
            var pcsScanId = '<?php echo esc_js($scan_id); ?>';
            var pcsPolling = false;
            var pcsCurrentCategory = '';
            var pcsCurrentPage = 1;

            // Start scan
            $(document).on('click', '#sqmedia-pcs-start-scan', function() {
                if (!window.sqStartOperation('<?php esc_html_e('Post Content Scanner', 'staticq-media'); ?>')) return;
                var $btn = $(this);
                $btn.prop('disabled', true);
                $('#sqmedia-pcs-card').attr('data-status', 'scanning');

                $.post(ajaxurl, {
                    action: 'sqmedia_start_post_content_scan',
                    nonce: sqmediaAdmin.nonce
                }, function(response) {
                    if (response.success) {
                        pcsScanId = response.data.scan_id;
                        pcsStatus = 'scanning';
                        pcsShowScanningUI(0, response.data.total || 0, 0);
                        pcsPoll();
                    } else {
                        alert(response.data || '<?php esc_html_e('Error starting scan', 'staticq-media'); ?>');
                        $btn.prop('disabled', false);
                        window.sqEndOperation();
                    }
                }).fail(function() {
                    alert('<?php esc_html_e('Request failed', 'staticq-media'); ?>');
                    $btn.prop('disabled', false);
                    window.sqEndOperation();
                });
            });

            // Rescan
            $(document).on('click', '#sqmedia-pcs-rescan', function() {
                if (!window.sqStartOperation('<?php esc_html_e('Post Content Scanner', 'staticq-media'); ?>')) return;
                $('#sqmedia-pcs-card').attr('data-status', 'scanning');

                $.post(ajaxurl, {
                    action: 'sqmedia_start_post_content_scan',
                    nonce: sqmediaAdmin.nonce
                }, function(response) {
                    if (response.success) {
                        pcsScanId = response.data.scan_id;
                        pcsStatus = 'scanning';
                        pcsShowScanningUI(0, response.data.total || 0, 0);
                        pcsPoll();
                    } else {
                        alert(response.data || '<?php esc_html_e('Error starting scan', 'staticq-media'); ?>');
                        window.sqEndOperation();
                        location.reload();
                    }
                });
            });

            // Cancel
            $(document).on('click', '#sqmedia-pcs-cancel', function() {
                $.post(ajaxurl, {
                    action: 'sqmedia_cancel_post_content_scan',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function() {
                    window.sqEndOperation();
                    location.reload();
                });
            });

            // Pause
            $(document).on('click', '#sqmedia-pcs-pause', function() {
                $.post(ajaxurl, {
                    action: 'sqmedia_pause_post_content_scan',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function() {
                    pcsStatus = 'paused';
                    pcsPolling = false;
                    $('#sqmedia-pcs-pause').hide();
                    $('#sqmedia-pcs-resume').show();
                    $('#sqmedia-pcs-progress-fill').addClass('sqmedia-progress-paused');
                });
            });

            // Resume
            $(document).on('click', '#sqmedia-pcs-resume', function() {
                $.post(ajaxurl, {
                    action: 'sqmedia_resume_post_content_scan',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function() {
                    pcsStatus = 'scanning';
                    $('#sqmedia-pcs-resume').hide();
                    $('#sqmedia-pcs-pause').show();
                    $('#sqmedia-pcs-progress-fill').removeClass('sqmedia-progress-paused');
                    pcsPoll();
                });
            });

            // Fix All
            $(document).on('click', '#sqmedia-pcs-fix-all', function() {
                if (!window.sqStartOperation('<?php esc_html_e('Post Content Fix', 'staticq-media'); ?>')) return;
                var $btn = $(this);
                $btn.prop('disabled', true);

                $.post(ajaxurl, {
                    action: 'sqmedia_start_post_content_fix',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function(response) {
                    if (response.success) {
                        pcsStatus = 'fixing';
                        $('#sqmedia-pcs-card').attr('data-status', 'fixing');
                        pcsShowFixingUI(0, response.data.total || 0);
                        pcsPollFix();
                    } else {
                        alert(response.data || '<?php esc_html_e('Error starting fix', 'staticq-media'); ?>');
                        $btn.prop('disabled', false);
                        window.sqEndOperation();
                    }
                });
            });

            // Stop Fix
            $(document).on('click', '#sqmedia-pcs-stop-fix', function() {
                $.post(ajaxurl, {
                    action: 'sqmedia_stop_post_content_fix',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function() {
                    window.sqEndOperation();
                    location.reload();
                });
            });

            // View Details toggle
            $(document).on('click', '#sqmedia-pcs-view-details', function() {
                var $panel = $('#sqmedia-pcs-details-panel');
                $panel.toggle();
                if ($panel.is(':visible') && !$panel.data('loaded')) {
                    pcsLoadDetails('', 1);
                    $panel.data('loaded', true);
                }
            });

            // Tab switching
            $(document).on('click', '.sqmedia-pcs-tab', function() {
                var cat = $(this).data('category');
                $('.sqmedia-pcs-tab').removeClass('active');
                $(this).addClass('active');
                pcsCurrentCategory = cat;
                pcsLoadDetails(cat, 1);
            });

            // Expand/collapse post details
            $(document).on('click', '.sqmedia-pcs-expand-btn', function() {
                var $btn = $(this);
                var postId = $btn.data('post-id');
                var $detailRow = $('.sqmedia-pcs-detail-row[data-post-id="' + postId + '"]');
                $detailRow.toggle();
                $btn.text($detailRow.is(':visible') ? '▼' : '▶');
            });

            // Fix single post
            $(document).on('click', '.sqmedia-pcs-fix-single', function() {
                var $btn = $(this);
                var postId = $btn.data('post-id');
                var $row = $btn.closest('tr');
                $btn.prop('disabled', true).text('...');

                $.post(ajaxurl, {
                    action: 'sqmedia_fix_single_post_content',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId,
                    post_id: postId
                }, function(response) {
                    if (response.success) {
                        $row.addClass('sqmedia-row-fixed');
                        $btn.text('✓');
                        setTimeout(function() {
                            var $detailRow = $row.next('.sqmedia-pcs-detail-row');
                            if ($detailRow.length) $detailRow.remove();
                            $row.fadeOut(300, function() {
                                $row.remove();
                                pcsLoadDetails(pcsCurrentCategory, pcsCurrentPage);
                            });
                        }, 500);
                    } else {
                        $btn.replaceWith('<span style="color:#d63638;font-size:12px;">' + (response.data || '<?php esc_html_e('Error', 'staticq-media'); ?>') + '</span>');
                    }
                }).fail(function() {
                    $btn.replaceWith('<span style="color:#d63638;font-size:12px;"><?php esc_html_e('Request failed', 'staticq-media'); ?></span>');
                });
            });

            // Pagination
            $(document).on('click', '.sqmedia-pcs-page-btn', function() {
                var page = $(this).data('page');
                pcsLoadDetails(pcsCurrentCategory, page);
            });

            // Polling: process batch + update progress
            function pcsPoll() {
                if (pcsPolling || pcsStatus !== 'scanning') return;
                pcsPolling = true;

                $.post(ajaxurl, {
                    action: 'sqmedia_process_post_content_batch',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function(response) {
                    pcsPolling = false;
                    if (!response.success) {
                        alert(response.data || '<?php esc_html_e('Error during scan', 'staticq-media'); ?>');
                        window.sqEndOperation();
                        location.reload();
                        return;
                    }
                    var d = response.data;
                    pcsUpdateProgress(d.processed || 0, d.total || 0, d.progress || 0);

                    if (d.done) {
                        window.sqEndOperation();
                        setTimeout(function() { location.reload(); }, 500);
                    } else if (pcsStatus === 'scanning') {
                        setTimeout(pcsPoll, 500);
                    }
                }).fail(function() {
                    pcsPolling = false;
                    if (pcsStatus === 'scanning') {
                        setTimeout(pcsPoll, 2000);
                    }
                });
            }

            // Fix polling
            function pcsPollFix() {
                $.post(ajaxurl, {
                    action: 'sqmedia_process_post_content_fix_batch',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId
                }, function(response) {
                    if (!response.success) {
                        window.sqEndOperation();
                        location.reload();
                        return;
                    }
                    var d = response.data;
                    pcsUpdateFixProgress(d.processed || 0, d.total || 0, d.fixed || 0);
                    if (d.done) {
                        window.sqEndOperation();
                        setTimeout(function() { location.reload(); }, 500);
                    } else {
                        setTimeout(pcsPollFix, 300);
                    }
                }).fail(function() {
                    setTimeout(pcsPollFix, 2000);
                });
            }

            function pcsShowScanningUI(processed, total, progress) {
                $('#sqmedia-pcs-body').html(
                    '<div class="sqmedia-progress-container">' +
                    '  <div class="sqmedia-progress-bar"><div class="sqmedia-progress-fill" id="sqmedia-pcs-progress-fill" style="width: ' + progress + '%">' + progress + '%</div></div>' +
                    '</div>' +
                    '<p id="sqmedia-pcs-progress-text">' + processed + ' / ' + total + ' <?php esc_html_e('posts', 'staticq-media'); ?></p>' +
                    '<div class="sqmedia-button-group" style="margin-top: 10px;">' +
                    '  <button type="button" class="button" id="sqmedia-pcs-pause"><?php esc_html_e('Pause', 'staticq-media'); ?></button>' +
                    '  <button type="button" class="button" id="sqmedia-pcs-resume" style="display:none;"><?php esc_html_e('Resume', 'staticq-media'); ?></button>' +
                    '  <button type="button" class="button" id="sqmedia-pcs-cancel"><?php esc_html_e('Cancel', 'staticq-media'); ?></button>' +
                    '</div>'
                );
            }

            function pcsShowFixingUI(processed, total) {
                var progress = total > 0 ? Math.round((processed / total) * 100) : 0;
                $('#sqmedia-pcs-body').html(
                    '<div class="sqmedia-progress-container">' +
                    '  <div class="sqmedia-progress-bar"><div class="sqmedia-progress-fill" id="sqmedia-pcs-fix-progress-fill" style="width: ' + progress + '%">' + progress + '%</div></div>' +
                    '</div>' +
                    '<p id="sqmedia-pcs-fix-text"><?php esc_html_e('Fixing...', 'staticq-media'); ?> ' + processed + ' / ' + total + '</p>' +
                    '<div class="sqmedia-button-group" style="margin-top: 10px;">' +
                    '  <button type="button" class="button" id="sqmedia-pcs-stop-fix"><?php esc_html_e('Stop', 'staticq-media'); ?></button>' +
                    '</div>'
                );
            }

            function pcsUpdateProgress(processed, total, progress) {
                $('#sqmedia-pcs-progress-fill').css('width', progress + '%').text(progress + '%');
                $('#sqmedia-pcs-progress-text').text(processed + ' / ' + total + ' <?php esc_html_e('posts', 'staticq-media'); ?>');
            }

            function pcsUpdateFixProgress(processed, total, fixed) {
                var progress = total > 0 ? Math.round((processed / total) * 100) : 0;
                $('#sqmedia-pcs-fix-progress-fill').css('width', progress + '%').text(progress + '%');
                $('#sqmedia-pcs-fix-text').text('<?php esc_html_e('Fixing...', 'staticq-media'); ?> ' + processed + ' / ' + total + ' (<?php esc_html_e('fixed:', 'staticq-media'); ?> ' + fixed + ')');
            }

            function pcsLoadDetails(category, page) {
                page = page || 1;
                pcsCurrentCategory = category;
                pcsCurrentPage = page;
                var $list = $('#sqmedia-pcs-details-list');
                $list.html('<p><?php esc_html_e('Loading...', 'staticq-media'); ?></p>');

                $.post(ajaxurl, {
                    action: 'sqmedia_get_post_content_scan_details',
                    nonce: sqmediaAdmin.nonce,
                    scan_id: pcsScanId,
                    category: category,
                    page: page
                }, function(response) {
                    if (!response.success) {
                        $list.html('<p><?php esc_html_e('Error loading details.', 'staticq-media'); ?></p>');
                        return;
                    }
                    var data = response.data;
                    if (!data.items || data.items.length === 0) {
                        $list.html('<p><?php esc_html_e('No issues found.', 'staticq-media'); ?></p>');
                        return;
                    }
                    pcsRenderDetailsTable(data);
                });
            }

            function pcsRenderDetailsTable(data) {
                var $list = $('#sqmedia-pcs-details-list');
                var html = '<table class="wp-list-table widefat striped"><thead><tr>' +
                    '<th style="width:30px;padding:8px 4px;"></th>' +
                    '<th style="width:50px;"><?php esc_html_e('ID', 'staticq-media'); ?></th>' +
                    '<th><?php esc_html_e('Post', 'staticq-media'); ?></th>' +
                    '<th><?php esc_html_e('Issues', 'staticq-media'); ?></th>' +
                    '<th style="width:80px;"><?php esc_html_e('Actions', 'staticq-media'); ?></th>' +
                    '</tr></thead><tbody>';

                data.items.forEach(function(item) {
                    var link = item.edit_url
                        ? '<a href="' + item.edit_url + '" target="_blank">' + pcsEsc(item.post_title) + '</a>'
                        : pcsEsc(item.post_title);

                    // Issue badges
                    var badges = '';
                    item.badges.forEach(function(b) {
                        var cls = b.fixable ? 'sqmedia-cascade-warning' : 'sqmedia-cascade-error';
                        badges += '<span class="sqmedia-pcs-badge ' + cls + '">' +
                            pcsCategoryLabel(b.category) +
                            (b.count > 1 ? ' ×' + b.count : '') +
                            '</span> ';
                    });

                    // Fix button
                    var actions = '';
                    if (item.has_fixable) {
                            actions = '<button type="button" class="button button-small sqmedia-pcs-fix-single" data-post-id="' + item.post_id + '"><?php esc_html_e('Fix', 'staticq-media'); ?></button>';
                    } else {
                        actions = '<span style="color:#999;">—</span>';
                    }

                    // Post row
                    html += '<tr class="sqmedia-pcs-post-row" data-post-id="' + item.post_id + '">' +
                        '<td style="padding:8px 4px;text-align:center;"><button type="button" class="sqmedia-pcs-expand-btn" data-post-id="' + item.post_id + '" style="background:none;border:none;cursor:pointer;font-size:14px;padding:0;line-height:1;">▶</button></td>' +
                        '<td>' + item.post_id + '</td>' +
                        '<td>' + link + '</td>' +
                        '<td>' + badges + '</td>' +
                        '<td>' + actions + '</td>' +
                        '</tr>';

                    // Detail row (hidden until expanded)
                    html += '<tr class="sqmedia-pcs-detail-row" data-post-id="' + item.post_id + '" style="display:none;background:#f9f9f9;">' +
                        '<td></td><td colspan="4">' + pcsRenderIssueDetails(item.issues) + '</td>' +
                        '</tr>';
                });

                html += '</tbody></table>';

                // Pagination
                if (data.pages > 1) {
                    html += pcsRenderPagination(data.page, data.pages);
                }

                $list.html(html);
            }

            function pcsRenderIssueDetails(issues) {
                var html = '<div style="padding:4px 0;">';
                issues.forEach(function(issue) {
                    var icon = '', cls = '', text = '';
                    switch (issue.category) {
                        case 'pcs_wrong_domain':
                            icon = '⚠'; cls = 'warning';
                            text = '<?php esc_html_e('Wrong Domain', 'staticq-media'); ?>';
                            if (issue.count > 1) text += ' ×' + issue.count;
                            if (issue.domains && issue.domains.length) {
                                text += ': ' + issue.domains.map(function(d) { return '<code>' + pcsEsc(d) + '</code>'; }).join(', ');
                            }
                            break;
                        case 'pcs_stale_size':
                            icon = '⚠'; cls = 'warning';
                            text = '<?php esc_html_e('Stale Size', 'staticq-media'); ?>: <code>' + pcsEsc(issue.detail.referenced_file || '') + '</code>';
                            if (issue.detail.replacement_file) {
                                text += ' → <code>' + pcsEsc(issue.detail.replacement_file) + '</code>';
                                if (issue.detail.replacement_size) {
                                    text += ' (' + pcsEsc(issue.detail.replacement_size) + ')';
                                }
                            }
                            break;
                        case 'pcs_deleted_attachment':
                            icon = '✗'; cls = 'info';
                            text = '<?php esc_html_e('Deleted Attachment', 'staticq-media'); ?> (ID: ' + (issue.detail.attachment_id || '?') + ')';
                            break;
                        case 'pcs_broken_url':
                            icon = '✗'; cls = 'info';
                            text = '<?php esc_html_e('Broken URL', 'staticq-media'); ?>: <code>' + pcsEsc(issue.detail.url || '') + '</code>';
                            break;
                    }
                    var color = cls === 'warning' ? '#dba617' : '#999';
                    html += '<div style="padding:3px 0;color:#333;">' +
                        '<span style="color:' + color + ';margin-right:6px;">' + icon + '</span>' + text +
                        '</div>';
                });
                html += '</div>';
                return html;
            }

            function pcsRenderPagination(currentPage, totalPages) {
                var html = '<div style="margin-top:10px;text-align:center;">';
                for (var p = 1; p <= totalPages; p++) {
                    if (p === currentPage) {
                        html += '<span class="button button-small" style="font-weight:bold;margin:2px;" disabled>' + p + '</span>';
                    } else {
                        html += '<button type="button" class="button button-small sqmedia-pcs-page-btn" data-page="' + p + '" style="margin:2px;">' + p + '</button>';
                    }
                }
                html += '</div>';
                return html;
            }

            function pcsCategoryLabel(cat) {
                var labels = {
                    'pcs_wrong_domain': '<?php esc_html_e('Wrong Domain', 'staticq-media'); ?>',
                    'pcs_deleted_attachment': '<?php esc_html_e('Deleted Attachment', 'staticq-media'); ?>',
                    'pcs_stale_size': '<?php esc_html_e('Stale Size', 'staticq-media'); ?>',
                    'pcs_broken_url': '<?php esc_html_e('Broken URL', 'staticq-media'); ?>'
                };
                return labels[cat] || cat;
            }

            function pcsEsc(str) {
                var el = document.createElement('span');
                el.textContent = str;
                return el.innerHTML;
            }

            // Auto-resume if scanning/fixing on page load
            <?php if ($status === self::STATUS_SCANNING): ?>
            (function() {
                window.sqActiveOperation = '<?php esc_html_e('Post Content Scanner', 'staticq-media'); ?>';
                pcsShowScanningUI(
                    <?php echo (int) ($state['processed'] ?? 0); ?>,
                    <?php echo (int) ($state['total_scanned'] ?? 0); ?>,
                    <?php
                    $total = (int) ($state['total_scanned'] ?? 0);
                    $processed = (int) ($state['processed'] ?? 0);
                    echo (int) ($total > 0 ? round(($processed / $total) * 100) : 0);
                    ?>
                );
                pcsPoll();
            })();
            <?php endif; ?>

            <?php if ($status === self::STATUS_FIXING): ?>
            (function() {
                var fix = <?php echo wp_json_encode($state['results']['fix'] ?? ['total' => 0, 'processed' => 0]); ?>;
                window.sqActiveOperation = '<?php esc_html_e('Post Content Fix', 'staticq-media'); ?>';
                pcsShowFixingUI(fix.processed || 0, fix.total || 0);
                pcsPollFix();
            })();
            <?php endif; ?>

            <?php if ($status === self::STATUS_PAUSED): ?>
            (function() {
                window.sqActiveOperation = '<?php esc_html_e('Post Content Scanner', 'staticq-media'); ?>';
                pcsShowScanningUI(
                    <?php echo (int) ($state['processed'] ?? 0); ?>,
                    <?php echo (int) ($state['total_scanned'] ?? 0); ?>,
                    <?php
                    $total = (int) ($state['total_scanned'] ?? 0);
                    $processed = (int) ($state['processed'] ?? 0);
                    echo (int) ($total > 0 ? round(($processed / $total) * 100) : 0);
                    ?>
                );
                pcsStatus = 'paused';
                $('#sqmedia-pcs-pause').hide();
                $('#sqmedia-pcs-resume').show();
                $('#sqmedia-pcs-progress-fill').addClass('sqmedia-progress-paused');
            })();
            <?php endif; ?>
        });
        <?php
        wp_add_inline_script('sqmedia-admin', ob_get_clean());
    }
}
