/**
 * Cleanup Removed Plugins Admin JavaScript
 */
(function($) {
    'use strict';

    // State management
    const state = {
        currentTab: 'tables',
        tables: [],
        options: [],
        crons: [],
        scanned: false,
        truncated: { options: false },
        ignored: { tables: 0, options: 0, crons: 0 },
        sort: {
            tables: { column: null, direction: 'asc' },
            options: { column: null, direction: 'asc' },
            crons: { column: null, direction: 'asc' }
        }
    };

    // Initialize on document ready
    $(document).ready(function() {
        initTabs();
        initBulkActions();
        initModal();
        initOptionsFilter();
        initTablesFilter();
        initScanButton();
        initSorting();

        // Check URL for tab parameter
        const urlParams = new URLSearchParams(window.location.search);
        const tabParam = urlParams.get('tab');
        if (tabParam && $('.crp-tab[data-tab="' + tabParam + '"]').length) {
            $('.crp-tab[data-tab="' + tabParam + '"]').trigger('click');
        }

        // Auto-scan on page load
        performScan();
    });

    /**
     * Initialize tab navigation
     */
    function initTabs() {
        $('.crp-tab').on('click', function() {
            const tab = $(this).data('tab');

            // Update active state
            $('.crp-tab').removeClass('active');
            $(this).addClass('active');

            // Show correct content
            $('.crp-tab-content').removeClass('active');
            $('#tab-' + tab).addClass('active');

            state.currentTab = tab;

            // Update URL parameter
            const url = new URL(window.location.href);
            url.searchParams.set('tab', tab);
            window.history.replaceState({}, '', url);
        });
    }

    /**
     * Initialize scan button
     */
    function initScanButton() {
        $('#crp-scan-btn').on('click', function() {
            performScan();
        });
    }

    /**
     * Perform database scan
     */
    function performScan() {
        const $btn = $('#crp-scan-btn');

        if ($btn.hasClass('scanning')) {
            return;
        }

        $btn.addClass('scanning')
            .prop('disabled', true)
            .html('<span class="dashicons dashicons-update spin"></span> ' + switchboardCRP.i18n.scanning);

        // Show loading state in all tables
        showLoadingState();

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_scan',
                nonce: switchboardCRP.nonce
            },
            success: function(response) {
                if (response.success) {
                    state.tables = response.data.tables || [];
                    state.options = response.data.options || [];
                    state.crons = response.data.crons || [];
                    state.scanned = true;
                    state.truncated = response.data.truncated || { options: false };
                    state.ignored = response.data.ignored || { tables: 0, options: 0, crons: 0 };

                    // Update stats
                    updateStats(response.data.summary);

                    // Render all results
                    renderTables();
                    renderOptions();
                    renderCrons();

                    showToast(switchboardCRP.i18n.scanComplete || 'Scan complete!', 'success');
                } else {
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                    showEmptyState();
                }
            },
            error: function() {
                showToast(switchboardCRP.i18n.error, 'error');
                showEmptyState();
            },
            complete: function() {
                $btn.removeClass('scanning')
                    .prop('disabled', false)
                    .html('<span class="dashicons dashicons-search"></span> ' + (switchboardCRP.i18n.rescan || 'Rescan Database'));
            }
        });
    }

    /**
     * Show loading state in all tables
     */
    function showLoadingState() {
        const loadingHtml = '<tr class="loading-row"><td colspan="7" class="loading-cell"><span class="spinner is-active"></span> ' + switchboardCRP.i18n.scanning + '</td></tr>';

        $('#tables-list tbody').html(loadingHtml);
        $('#options-list tbody').html(loadingHtml.replace('colspan="7"', 'colspan="6"'));
        $('#crons-list tbody').html(loadingHtml);
    }

    /**
     * Show empty state when no data
     */
    function showEmptyState() {
        const emptyHtml = '<tr class="empty-row"><td colspan="7" class="empty-cell"><div class="empty-state"><span class="dashicons dashicons-warning"></span><p>' + switchboardCRP.i18n.error + '</p></div></td></tr>';

        $('#tables-list tbody').html(emptyHtml);
        $('#options-list tbody').html(emptyHtml.replace('colspan="7"', 'colspan="6"'));
        $('#crons-list tbody').html(emptyHtml);
    }

    /**
     * Update statistics display
     */
    function updateStats(summary) {
        $('#stat-tables-count').text(summary.tables_count);
        $('#stat-tables-size').text(formatSize(summary.tables_size));
        $('#stat-options-count').text(summary.options_count);
        $('#stat-options-size').text(formatSize(summary.options_size));
        $('#stat-crons-count').text(summary.crons_count);
        $('#stat-last-scan').text(summary.last_scan || 'Just now');

        // Update tab counts
        $('#tab-tables-count').text(summary.tables_count);
        $('#tab-options-count').text(summary.options_count);
        $('#tab-crons-count').text(summary.crons_count);
    }

    /**
     * Render orphaned tables
     */
    function renderTables() {
        const $tbody = $('#tables-list tbody');
        const tables = state.tables;

        if (tables.length === 0) {
            $tbody.html('<tr class="empty-row"><td colspan="7" class="empty-cell"><div class="empty-state"><span class="dashicons dashicons-yes-alt" style="color: #22c55e;"></span><p>' + (switchboardCRP.i18n.noTables || 'No orphaned tables found!') + '</p></div></td></tr>');
            $('#tables-bulk-actions').hide();
            return;
        }

        let html = '';
        for (const table of tables) {
            const sourceClass = table.source ? (table.source.guessed ? 'unknown' : 'known') : 'unknown';
            const sourceName = table.source ? table.source.name : 'Unknown';
            const riskClass = table.risk || 'medium';
            const riskTooltip = getRiskTooltip(riskClass);
            const guessedPrefix = table.source && table.source.guessed_prefix ? table.source.guessed_prefix : '';
            const isGuessed = table.source && table.source.guessed;

            // Build source cell with optional link dropdown
            let sourceCell = `<span class="source-badge ${sourceClass}">${escapeHtml(sourceName)}</span>`;
            if (isGuessed && guessedPrefix) {
                sourceCell += renderLinkDropdown(guessedPrefix, 'table');
            }

            html += `
                <tr class="crp-item" data-table="${escapeHtml(table.name)}" data-prefix="${escapeHtml(guessedPrefix)}" data-source="${escapeHtml(sourceName)}" data-rows="${table.rows}" data-size="${table.size}" data-risk="${riskClass}">
                    <td class="check-column"><input type="checkbox" class="table-checkbox" value="${escapeHtml(table.name)}"></td>
                    <td><code>${escapeHtml(table.name)}</code></td>
                    <td>${sourceCell}</td>
                    <td>${formatNumber(table.rows)}</td>
                    <td data-bytes="${table.size}">${formatSize(table.size)}</td>
                    <td><span class="risk-badge ${riskClass}" title="${escapeHtml(riskTooltip)}">${riskClass}</span></td>
                    <td class="crp-actions">
                        <button type="button" class="crp-action-btn-small delete delete-table-btn" data-table="${escapeHtml(table.name)}" title="Delete">
                            <span class="dashicons dashicons-trash"></span>
                        </button>
                        <button type="button" class="crp-action-btn-small ignore ignore-table-btn" data-table="${escapeHtml(table.name)}" title="Ignore">
                            <span class="dashicons dashicons-hidden"></span>
                        </button>
                    </td>
                </tr>
            `;
        }

        $tbody.html(html);
        $('#tables-bulk-actions').show();

        // Bind event handlers
        bindTableHandlers();
        bindLinkDropdownHandlers();

        // Populate source filter and show ignored indicator
        populateTableSourceFilter();
        showIgnoredIndicator();
    }

    /**
     * Render link-to-plugin dropdown for unknown prefixes
     */
    function renderLinkDropdown(prefix, type) {
        const plugins = switchboardCRP.activePlugins || [];
        let options = `<option value="">${switchboardCRP.i18n.linkToPlugin || 'Link to plugin...'}</option>`;
        for (const plugin of plugins) {
            options += `<option value="${escapeHtml(plugin.file)}">${escapeHtml(plugin.name)}</option>`;
        }

        return `
            <div class="crp-link-dropdown">
                <select class="crp-link-select" data-prefix="${escapeHtml(prefix)}" data-type="${type}" title="${switchboardCRP.i18n.linkToPlugin || 'Link to active plugin'}">
                    ${options}
                </select>
            </div>
        `;
    }

    /**
     * Bind link dropdown handlers
     */
    function bindLinkDropdownHandlers() {
        $('.crp-link-select').off('change').on('change', function() {
            const $select = $(this);
            const prefix = $select.data('prefix');
            const pluginFile = $select.val();
            const itemType = $select.data('type');

            if (!prefix || !pluginFile) return;

            $select.prop('disabled', true);

            $.ajax({
                url: switchboardCRP.ajaxurl,
                type: 'POST',
                data: {
                    action: 'switchboard_crp_link_prefix',
                    nonce: switchboardCRP.nonce,
                    prefix: prefix,
                    plugin_file: pluginFile
                },
                success: function(response) {
                    if (response.success) {
                        showToast(switchboardCRP.i18n.prefixLinked || 'Prefix linked - items removed', 'success');
                        // Remove all rows with this prefix locally instead of re-scanning
                        removeItemsByPrefix(prefix, itemType);
                    } else {
                        showToast(response.data.message || switchboardCRP.i18n.error, 'error');
                        $select.prop('disabled', false);
                    }
                },
                error: function() {
                    showToast(switchboardCRP.i18n.error, 'error');
                    $select.prop('disabled', false);
                }
            });
        });
    }

    /**
     * Remove all items matching a prefix from the UI (local update)
     */
    function removeItemsByPrefix(prefix, type) {
        const $rows = $(`tr.crp-item[data-prefix="${prefix}"]`);
        const count = $rows.length;

        $rows.fadeOut(300, function() {
            $(this).remove();
        });

        // Update state and counts after animation
        setTimeout(function() {
            // Determine which tabs to update based on the prefix match
            ['tables', 'options', 'crons'].forEach(function(tabType) {
                const removed = $(`#${tabType}-list tr.crp-item[data-prefix="${prefix}"]`).length;
                if (removed > 0 || type === tabType.slice(0, -1)) {
                    updateTabCount(tabType, -count);
                    checkEmptyState(tabType);
                }
            });
        }, 350);
    }

    /**
     * Bind table action handlers
     */
    function bindTableHandlers() {
        $('.delete-table-btn').off('click').on('click', function() {
            const table = $(this).data('table');
            const $row = $(this).closest('tr');
            showConfirmModal(
                switchboardCRP.i18n.confirmDeleteTable || `Delete table "${table}"? This will permanently remove the table and all its data.`,
                function() { deleteTable(table, $row); },
                switchboardCRP.i18n.confirmDeleteTitle || 'Delete Table'
            );
        });

        $('.ignore-table-btn').off('click').on('click', function() {
            const table = $(this).data('table');
            ignoreItem('table', table, $(this).closest('tr'));
        });
    }

    /**
     * Render orphaned options
     */
    function renderOptions() {
        const $tbody = $('#options-list tbody');
        const options = state.options;

        if (options.length === 0) {
            $tbody.html('<tr class="empty-row"><td colspan="6" class="empty-cell"><div class="empty-state"><span class="dashicons dashicons-yes-alt" style="color: #22c55e;"></span><p>' + (switchboardCRP.i18n.noOptions || 'No orphaned options found!') + '</p></div></td></tr>');
            $('#options-bulk-actions').hide();
            return;
        }

        let html = '';
        for (const option of options) {
            const sourceClass = option.source ? (option.source.guessed ? 'unknown' : 'known') : 'unknown';
            const sourceName = option.source ? option.source.name : 'Unknown';
            const autoloadClass = option.autoload === 'yes' ? 'yes' : 'no';
            const guessedPrefix = option.source && option.source.guessed_prefix ? option.source.guessed_prefix : '';
            const isGuessed = option.source && option.source.guessed;

            // Build source cell with optional link dropdown
            let sourceCell = `<span class="source-badge ${sourceClass}">${escapeHtml(sourceName)}</span>`;
            if (isGuessed && guessedPrefix) {
                sourceCell += renderLinkDropdown(guessedPrefix, 'option');
            }

            html += `
                <tr class="crp-item" data-option="${escapeHtml(option.name)}" data-prefix="${escapeHtml(guessedPrefix)}" data-size="${option.size}" data-source="${escapeHtml(sourceName)}">
                    <td class="check-column"><input type="checkbox" class="option-checkbox" value="${escapeHtml(option.name)}"></td>
                    <td><code title="${escapeHtml(option.name)}">${escapeHtml(truncate(option.name, 50))}</code></td>
                    <td>${sourceCell}</td>
                    <td data-bytes="${option.size}">${formatSize(option.size)}</td>
                    <td><span class="autoload-badge ${autoloadClass}">${option.autoload}</span></td>
                    <td class="crp-actions">
                        <button type="button" class="crp-action-btn-small preview preview-option-btn" data-option="${escapeHtml(option.name)}" title="Preview">
                            <span class="dashicons dashicons-visibility"></span>
                        </button>
                        <button type="button" class="crp-action-btn-small delete delete-option-btn" data-option="${escapeHtml(option.name)}" title="Delete">
                            <span class="dashicons dashicons-trash"></span>
                        </button>
                        <button type="button" class="crp-action-btn-small ignore ignore-option-btn" data-option="${escapeHtml(option.name)}" title="Ignore">
                            <span class="dashicons dashicons-hidden"></span>
                        </button>
                    </td>
                </tr>
            `;
        }

        $tbody.html(html);
        $('#options-bulk-actions').show();

        // Bind event handlers
        bindOptionHandlers();
        bindLinkDropdownHandlers();

        // Populate source filter dropdown
        populateSourceFilter();

        // Show truncation warning if results were limited
        showTruncationWarning('options');
    }

    /**
     * Bind option action handlers
     */
    function bindOptionHandlers() {
        $('.preview-option-btn').off('click').on('click', function() {
            const option = $(this).data('option');
            previewOption(option);
        });

        $('.delete-option-btn').off('click').on('click', function() {
            const option = $(this).data('option');
            const $row = $(this).closest('tr');
            showConfirmModal(
                switchboardCRP.i18n.confirmDeleteOption || `Delete option "${option}"?`,
                function() { deleteOptions([option], $row); },
                switchboardCRP.i18n.confirmDeleteTitle || 'Delete Option'
            );
        });

        $('.ignore-option-btn').off('click').on('click', function() {
            const option = $(this).data('option');
            ignoreItem('option', option, $(this).closest('tr'));
        });
    }

    /**
     * Render zombie cron jobs
     */
    function renderCrons() {
        const $tbody = $('#crons-list tbody');
        const crons = state.crons;

        if (crons.length === 0) {
            $tbody.html('<tr class="empty-row"><td colspan="7" class="empty-cell"><div class="empty-state"><span class="dashicons dashicons-yes-alt" style="color: #22c55e;"></span><p>' + (switchboardCRP.i18n.noCrons || 'No zombie cron jobs found!') + '</p></div></td></tr>');
            $('#crons-bulk-actions').hide();
            return;
        }

        let html = '';
        for (const cron of crons) {
            const sourceClass = cron.source ? (cron.source.guessed ? 'unknown' : 'known') : 'unknown';
            const sourceName = cron.source ? cron.source.name : 'Unknown';
            const statusClass = cron.has_callback ? 'has-callback' : 'no-callback';
            const statusText = cron.has_callback ? 'Has Callback' : 'No Callback';
            const statusTooltip = cron.has_callback
                ? (switchboardCRP.i18n.riskCronHasCallback || 'Has active callback - may still be in use')
                : (switchboardCRP.i18n.riskCronNoCallback || 'No registered callback - safe to remove');
            const guessedPrefix = cron.source && cron.source.guessed_prefix ? cron.source.guessed_prefix : '';
            const isGuessed = cron.source && cron.source.guessed;

            // Build source cell with optional link dropdown
            let sourceCell = `<span class="source-badge ${sourceClass}">${escapeHtml(sourceName)}</span>`;
            if (isGuessed && guessedPrefix) {
                sourceCell += renderLinkDropdown(guessedPrefix, 'cron');
            }

            html += `
                <tr class="crp-item" data-cron="${escapeHtml(cron.hook)}" data-timestamp="${cron.timestamp}" data-prefix="${escapeHtml(guessedPrefix)}">
                    <td class="check-column"><input type="checkbox" class="cron-checkbox" value="${escapeHtml(cron.hook)}"></td>
                    <td><code title="${escapeHtml(cron.hook)}">${escapeHtml(truncate(cron.hook, 40))}</code></td>
                    <td>${sourceCell}</td>
                    <td>${escapeHtml(cron.schedule)}</td>
                    <td>${escapeHtml(cron.next_run)}</td>
                    <td><span class="status-badge ${statusClass}" title="${escapeHtml(statusTooltip)}">${statusText}</span></td>
                    <td class="crp-actions">
                        <button type="button" class="crp-action-btn-small delete delete-cron-btn" data-cron="${escapeHtml(cron.hook)}" data-timestamp="${cron.timestamp}" title="Delete">
                            <span class="dashicons dashicons-trash"></span>
                        </button>
                        <button type="button" class="crp-action-btn-small ignore ignore-cron-btn" data-cron="${escapeHtml(cron.hook)}" title="Ignore">
                            <span class="dashicons dashicons-hidden"></span>
                        </button>
                    </td>
                </tr>
            `;
        }

        $tbody.html(html);
        $('#crons-bulk-actions').show();

        // Bind event handlers
        bindCronHandlers();
        bindLinkDropdownHandlers();
    }

    /**
     * Bind cron action handlers
     */
    function bindCronHandlers() {
        $('.delete-cron-btn').off('click').on('click', function() {
            const hook = $(this).data('cron');
            const timestamp = $(this).data('timestamp');
            const $row = $(this).closest('tr');
            showConfirmModal(
                switchboardCRP.i18n.confirmDeleteCron || `Delete scheduled task "${hook}"?`,
                function() { deleteCron(hook, timestamp, $row); },
                switchboardCRP.i18n.confirmDeleteTitle || 'Delete Cron Job'
            );
        });

        $('.ignore-cron-btn').off('click').on('click', function() {
            const hook = $(this).data('cron');
            ignoreItem('cron', hook, $(this).closest('tr'));
        });
    }

    /**
     * Initialize bulk actions
     */
    function initBulkActions() {
        // Select all handlers - only toggle visible rows
        $('#tables-select-all').on('change', function() {
            const checked = $(this).prop('checked');
            $('#tables-list tbody tr.crp-item:visible .table-checkbox').prop('checked', checked);
        });

        $('#options-select-all').on('change', function() {
            const checked = $(this).prop('checked');
            $('#options-list tbody tr.crp-item:visible .option-checkbox').prop('checked', checked);
        });

        $('#crons-select-all').on('change', function() {
            const checked = $(this).prop('checked');
            $('#crons-list tbody tr.crp-item:visible .cron-checkbox').prop('checked', checked);
        });

        // Bulk delete handlers - only collect from visible rows
        $('#delete-selected-tables').on('click', function() {
            const selected = $('#tables-list tbody tr.crp-item:visible .table-checkbox:checked').map(function() {
                return $(this).val();
            }).get();

            if (selected.length === 0) {
                showToast(switchboardCRP.i18n.noSelection, 'warning');
                return;
            }

            showConfirmModal(
                (switchboardCRP.i18n.confirmBulkTables || 'Delete %d selected tables?').replace('%d', selected.length),
                function() { bulkDelete('tables', selected); },
                switchboardCRP.i18n.confirmBulkTitle || 'Delete Selected'
            );
        });

        $('#delete-selected-options').on('click', function() {
            const selected = $('#options-list tbody tr.crp-item:visible .option-checkbox:checked').map(function() {
                return $(this).val();
            }).get();

            if (selected.length === 0) {
                showToast(switchboardCRP.i18n.noSelection, 'warning');
                return;
            }

            showConfirmModal(
                (switchboardCRP.i18n.confirmBulkOptions || 'Delete %d selected options?').replace('%d', selected.length),
                function() { bulkDelete('options', selected); },
                switchboardCRP.i18n.confirmBulkTitle || 'Delete Selected'
            );
        });

        $('#delete-selected-crons').on('click', function() {
            const selected = $('#crons-list tbody tr.crp-item:visible .cron-checkbox:checked').map(function() {
                return $(this).val();
            }).get();

            if (selected.length === 0) {
                showToast(switchboardCRP.i18n.noSelection, 'warning');
                return;
            }

            showConfirmModal(
                (switchboardCRP.i18n.confirmBulkCrons || 'Delete %d selected cron jobs?').replace('%d', selected.length),
                function() { bulkDelete('crons', selected); },
                switchboardCRP.i18n.confirmBulkTitle || 'Delete Selected'
            );
        });
    }

    /**
     * Populate the source filter dropdown with unique sources from options
     */
    function populateSourceFilter() {
        const $select = $('#options-source-filter');
        const currentVal = $select.val();

        // Collect unique source names
        const sources = new Set();
        state.options.forEach(function(option) {
            const name = option.source ? option.source.name : '';
            if (name && name !== 'Unknown') {
                sources.add(name);
            }
        });

        // Reset to default options
        $select.find('option:not([value=""]):not([value="__none__"])').remove();

        // Add sorted sources
        Array.from(sources).sort().forEach(function(source) {
            $select.append($('<option>').val(source).text(source));
        });

        // Restore previous selection if still valid
        if (currentVal && $select.find('option[value="' + currentVal + '"]').length) {
            $select.val(currentVal);
        }
    }

    /**
     * Apply combined text + source filter to options list
     */
    function applyOptionsFilter() {
        const textFilter = $('#options-search').val().toLowerCase();
        const sourceFilter = $('#options-source-filter').val();

        $('#options-list tbody tr.crp-item').each(function() {
            const $row = $(this);
            const optionName = ($row.data('option') || '').toLowerCase();
            const rowSource = $row.data('source') || '';

            // Text match
            const textMatch = !textFilter || optionName.indexOf(textFilter) !== -1;

            // Source match
            let sourceMatch = true;
            if (sourceFilter === '__none__') {
                sourceMatch = !rowSource || rowSource === 'Unknown';
            } else if (sourceFilter) {
                sourceMatch = rowSource === sourceFilter;
            }

            $row.toggle(textMatch && sourceMatch);
        });
    }

    /**
     * Initialize options filter
     */
    function initOptionsFilter() {
        $('#options-search').on('input', function() {
            applyOptionsFilter();
        });

        $('#options-source-filter').on('change', function() {
            applyOptionsFilter();
        });
    }

    /**
     * Populate the source filter dropdown with unique sources from tables
     */
    function populateTableSourceFilter() {
        const $select = $('#tables-source-filter');
        const currentVal = $select.val();

        const sources = new Set();
        state.tables.forEach(function(table) {
            const name = table.source ? table.source.name : '';
            if (name && name !== 'Unknown') {
                sources.add(name);
            }
        });

        $select.find('option:not([value=""]):not([value="__none__"])').remove();

        Array.from(sources).sort().forEach(function(source) {
            $select.append($('<option>').val(source).text(source));
        });

        if (currentVal && $select.find('option[value="' + currentVal + '"]').length) {
            $select.val(currentVal);
        }
    }

    /**
     * Apply combined text + source filter to tables list
     */
    function applyTablesFilter() {
        const textFilter = $('#tables-search').val().toLowerCase();
        const sourceFilter = $('#tables-source-filter').val();

        $('#tables-list tbody tr.crp-item').each(function() {
            const $row = $(this);
            const tableName = ($row.data('table') || '').toLowerCase();
            const rowSource = $row.data('source') || '';

            const textMatch = !textFilter || tableName.indexOf(textFilter) !== -1;

            let sourceMatch = true;
            if (sourceFilter === '__none__') {
                sourceMatch = !rowSource || rowSource === 'Unknown';
            } else if (sourceFilter) {
                sourceMatch = rowSource === sourceFilter;
            }

            $row.toggle(textMatch && sourceMatch);
        });
    }

    /**
     * Initialize tables filter
     */
    function initTablesFilter() {
        $('#tables-search').on('input', function() {
            applyTablesFilter();
        });

        $('#tables-source-filter').on('change', function() {
            applyTablesFilter();
        });
    }

    /**
     * Initialize column sorting
     */
    function initSorting() {
        $(document).on('click', '.sb-module-table th.sortable', function() {
            const $th = $(this);
            const $table = $th.closest('table');
            const tableId = $table.attr('id');
            const sortKey = $th.data('sort');
            const tabType = tableId.replace('-list', '');

            // Determine sort direction
            let direction = 'asc';
            if ($th.hasClass('asc')) {
                direction = 'desc';
            }

            // Update sort state
            state.sort[tabType] = { column: sortKey, direction: direction };

            // Update header classes
            $table.find('th.sortable').removeClass('asc desc');
            $th.addClass(direction);

            // Sort the rows
            sortTable($table, sortKey, direction);
        });
    }

    /**
     * Sort table rows
     */
    function sortTable($table, sortKey, direction) {
        const $tbody = $table.find('tbody');
        const $rows = $tbody.find('tr.crp-item').get();

        $rows.sort(function(a, b) {
            let valA, valB;

            switch(sortKey) {
                case 'name':
                    valA = $(a).find('code').first().text().toLowerCase();
                    valB = $(b).find('code').first().text().toLowerCase();
                    break;
                case 'rows':
                    valA = parseInt($(a).data('rows')) || 0;
                    valB = parseInt($(b).data('rows')) || 0;
                    break;
                case 'size':
                    valA = parseInt($(a).find('td[data-bytes]').data('bytes')) || parseInt($(a).data('size')) || 0;
                    valB = parseInt($(b).find('td[data-bytes]').data('bytes')) || parseInt($(b).data('size')) || 0;
                    break;
                case 'risk':
                    const riskOrder = { low: 1, medium: 2, high: 3 };
                    valA = riskOrder[$(a).data('risk')] || 2;
                    valB = riskOrder[$(b).data('risk')] || 2;
                    break;
                case 'autoload':
                    valA = $(a).find('.autoload-badge').text().toLowerCase();
                    valB = $(b).find('.autoload-badge').text().toLowerCase();
                    break;
                case 'schedule':
                    valA = $(a).find('td').eq(3).text().toLowerCase();
                    valB = $(b).find('td').eq(3).text().toLowerCase();
                    break;
                case 'next_run':
                    valA = $(a).data('timestamp') || 0;
                    valB = $(b).data('timestamp') || 0;
                    break;
                case 'status':
                    valA = $(a).find('.status-badge').hasClass('has-callback') ? 1 : 0;
                    valB = $(b).find('.status-badge').hasClass('has-callback') ? 1 : 0;
                    break;
                default:
                    valA = $(a).find('td').eq(1).text().toLowerCase();
                    valB = $(b).find('td').eq(1).text().toLowerCase();
            }

            // Compare values
            let result;
            if (typeof valA === 'number' && typeof valB === 'number') {
                result = valA - valB;
            } else {
                result = String(valA).localeCompare(String(valB));
            }

            return direction === 'desc' ? -result : result;
        });

        // Reattach sorted rows
        $.each($rows, function(_, row) {
            $tbody.append(row);
        });
    }

    /**
     * Initialize modal
     */
    function initModal() {
        $('.crp-modal-close, .crp-modal-backdrop').on('click', function() {
            $('.crp-modal').hide();
        });

        $('.crp-confirm-cancel').on('click', function() {
            $('#crp-confirm-modal').hide();
        });

        $(document).on('keydown', function(e) {
            if (e.key === 'Escape') {
                $('.crp-modal').hide();
            }
        });
    }

    /**
     * Show confirmation modal
     * @param {string} message - The confirmation message
     * @param {function} onConfirm - Callback when confirmed
     * @param {string} title - Optional custom title
     */
    function showConfirmModal(message, onConfirm, title) {
        const $modal = $('#crp-confirm-modal');
        const $btn = $('#crp-confirm-btn');

        if (title) {
            $('#crp-confirm-title').text(title);
        }
        $('#crp-confirm-message').text(message);

        // Remove any previous click handlers
        $btn.off('click').on('click', function() {
            $modal.hide();
            if (typeof onConfirm === 'function') {
                onConfirm();
            }
        });

        $modal.show();
    }

    /**
     * Delete a single table
     */
    function deleteTable(table, $row) {
        $row.addClass('deleting');

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_delete_table',
                nonce: switchboardCRP.nonce,
                table: table
            },
            success: function(response) {
                if (response.success) {
                    $row.fadeOut(300, function() {
                        $(this).remove();
                        updateTabCount('tables', -1);
                        checkEmptyState('tables');
                    });
                    showToast(switchboardCRP.i18n.deleted, 'success');
                } else {
                    $row.removeClass('deleting');
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                }
            },
            error: function() {
                $row.removeClass('deleting');
                showToast(switchboardCRP.i18n.error, 'error');
            }
        });
    }

    /**
     * Delete options
     */
    function deleteOptions(options, $row) {
        if ($row) {
            $row.addClass('deleting');
        }

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_delete_options',
                nonce: switchboardCRP.nonce,
                options: options
            },
            success: function(response) {
                if (response.success) {
                    if ($row) {
                        $row.fadeOut(300, function() {
                            $(this).remove();
                            updateTabCount('options', -1);
                            checkEmptyState('options');
                        });
                    }
                    showToast(response.data?.message || switchboardCRP.i18n.deleted, 'success');
                } else {
                    if ($row) {
                        $row.removeClass('deleting');
                    }
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                }
            },
            error: function() {
                if ($row) {
                    $row.removeClass('deleting');
                }
                showToast(switchboardCRP.i18n.error, 'error');
            }
        });
    }

    /**
     * Delete a cron job
     */
    function deleteCron(hook, timestamp, $row) {
        $row.addClass('deleting');

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_delete_cron',
                nonce: switchboardCRP.nonce,
                hook: hook,
                timestamp: timestamp
            },
            success: function(response) {
                if (response.success) {
                    $row.fadeOut(300, function() {
                        $(this).remove();
                        updateTabCount('crons', -1);
                        checkEmptyState('crons');
                    });
                    showToast(switchboardCRP.i18n.deleted, 'success');
                } else {
                    $row.removeClass('deleting');
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                }
            },
            error: function() {
                $row.removeClass('deleting');
                showToast(switchboardCRP.i18n.error, 'error');
            }
        });
    }

    /**
     * Bulk delete items
     */
    function bulkDelete(type, items) {
        const data = {
            action: 'switchboard_crp_bulk_cleanup',
            nonce: switchboardCRP.nonce
        };

        data[type] = items;

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: data,
            success: function(response) {
                if (response.success) {
                    // Remove rows
                    const selector = type === 'tables' ? 'table' : (type === 'options' ? 'option' : 'cron');
                    for (const item of items) {
                        $(`tr[data-${selector}="${item}"]`).remove();
                    }

                    updateTabCount(type, -items.length);
                    checkEmptyState(type);

                    // Uncheck select all
                    $(`#${type}-select-all`).prop('checked', false);

                    showToast(response.data?.message || switchboardCRP.i18n.deleted, 'success');
                } else {
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                }
            },
            error: function() {
                showToast(switchboardCRP.i18n.error, 'error');
            }
        });
    }

    /**
     * Ignore an item
     */
    function ignoreItem(type, item, $row) {
        $row.addClass('ignoring');

        const data = {
            action: 'switchboard_crp_save_settings',
            nonce: switchboardCRP.nonce
        };

        data['ignore_' + type] = item;

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: data,
            success: function(response) {
                if (response.success) {
                    $row.fadeOut(300, function() {
                        $(this).remove();
                        updateTabCount(type + 's', -1);
                        checkEmptyState(type + 's');
                    });
                    showToast(switchboardCRP.i18n.ignored || 'Item will be ignored in future scans', 'info');
                } else {
                    $row.removeClass('ignoring');
                    showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                }
            },
            error: function() {
                $row.removeClass('ignoring');
                showToast(switchboardCRP.i18n.error, 'error');
            }
        });
    }

    /**
     * Preview an option value
     */
    function previewOption(optionName) {
        $('#preview-option-name').text(optionName);
        $('#preview-option-value').text('Loading...');
        $('#crp-preview-modal').show();

        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_get_option_value',
                nonce: switchboardCRP.nonce,
                option_name: optionName
            },
            success: function(response) {
                if (response.success) {
                    $('#preview-option-value').text(response.data.value);
                } else {
                    $('#preview-option-value').text('Error loading value');
                }
            },
            error: function() {
                $('#preview-option-value').text('Error loading value');
            }
        });
    }

    /**
     * Update tab count
     */
    function updateTabCount(type, delta) {
        const $tabCount = $(`#tab-${type}-count`);
        const $statCount = $(`#stat-${type}-count`);

        const currentTab = parseInt($tabCount.text()) || 0;
        $tabCount.text(Math.max(0, currentTab + delta));

        const currentStat = parseInt($statCount.text()) || 0;
        $statCount.text(Math.max(0, currentStat + delta));
    }

    /**
     * Check if table is empty and show empty state
     */
    function checkEmptyState(type) {
        const $tbody = $(`#${type}-list tbody`);
        if ($tbody.find('tr.crp-item').length === 0) {
            const messages = {
                tables: switchboardCRP.i18n.noTables || 'No orphaned tables found!',
                options: switchboardCRP.i18n.noOptions || 'No orphaned options found!',
                crons: switchboardCRP.i18n.noCrons || 'No zombie cron jobs found!'
            };
            const colspan = type === 'options' ? 6 : 7;

            $tbody.html(`<tr class="empty-row"><td colspan="${colspan}" class="empty-cell"><div class="empty-state"><span class="dashicons dashicons-yes-alt" style="color: #22c55e;"></span><p>${messages[type]}</p></div></td></tr>`);
            $(`#${type}-bulk-actions`).hide();
        }
    }

    /**
     * Show toast notification
     */
    function showToast(message, type = 'info') {
        const $toast = $('#crp-toast');

        $toast.removeClass('success error warning info').addClass(type);
        $toast.find('.toast-message').text(message);
        $toast.addClass('show');

        setTimeout(function() {
            $toast.removeClass('show');
        }, 4000);
    }

    /**
     * Format file size
     */
    function formatSize(bytes) {
        if (!bytes || bytes === 0) return '0 B';
        const k = 1024;
        const sizes = ['B', 'KB', 'MB', 'GB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }

    /**
     * Format number with commas
     */
    function formatNumber(num) {
        return parseInt(num || 0).toLocaleString();
    }

    /**
     * Truncate string
     */
    function truncate(str, length) {
        if (!str || str.length <= length) return str;
        return str.substring(0, length) + '...';
    }

    /**
     * Escape HTML
     */
    function escapeHtml(text) {
        if (typeof text !== 'string') return text;
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    /**
     * Get risk level tooltip text
     */
    function getRiskTooltip(risk) {
        const tooltips = {
            low: switchboardCRP.i18n.riskLow || 'Low risk: Source plugin identified but inactive',
            medium: switchboardCRP.i18n.riskMedium || 'Medium risk: Source unknown - verify before deleting',
            high: switchboardCRP.i18n.riskHigh || 'High risk: May be used by active components'
        };
        return tooltips[risk] || tooltips.medium;
    }

    /**
     * Show ignored items modal
     */
    function showIgnoredItems() {
        // Fetch ignored items from server
        $.ajax({
            url: switchboardCRP.ajaxurl,
            type: 'POST',
            data: {
                action: 'switchboard_crp_get_ignored',
                nonce: switchboardCRP.nonce
            },
            success: function(response) {
                if (response.success) {
                    renderIgnoredModal(response.data);
                } else {
                    showToast(switchboardCRP.i18n.error || 'Error', 'error');
                }
            },
            error: function() {
                showToast(switchboardCRP.i18n.error || 'Error', 'error');
            }
        });
    }

    /**
     * Render ignored items modal content
     */
    function renderIgnoredModal(data) {
        const tables = data.tables || [];
        const options = data.options || [];
        const crons = data.crons || [];

        if (tables.length === 0 && options.length === 0 && crons.length === 0) {
            showToast(switchboardCRP.i18n.noIgnoredItems || 'No ignored items', 'info');
            return;
        }

        let html = '<div class="crp-ignored-list">';

        if (tables.length > 0) {
            html += `<h4>Tables (${tables.length})</h4><ul>`;
            for (const table of tables) {
                html += `<li><code>${escapeHtml(table)}</code> <button type="button" class="button-link crp-unignore-btn" data-type="table" data-item="${escapeHtml(table)}">${switchboardCRP.i18n.unignore || 'Un-ignore'}</button></li>`;
            }
            html += '</ul>';
        }

        if (options.length > 0) {
            html += `<h4>Options (${options.length})</h4><ul>`;
            for (const option of options) {
                html += `<li><code>${escapeHtml(option)}</code> <button type="button" class="button-link crp-unignore-btn" data-type="option" data-item="${escapeHtml(option)}">${switchboardCRP.i18n.unignore || 'Un-ignore'}</button></li>`;
            }
            html += '</ul>';
        }

        if (crons.length > 0) {
            html += `<h4>Cron Jobs (${crons.length})</h4><ul>`;
            for (const cron of crons) {
                html += `<li><code>${escapeHtml(cron)}</code> <button type="button" class="button-link crp-unignore-btn" data-type="cron" data-item="${escapeHtml(cron)}">${switchboardCRP.i18n.unignore || 'Un-ignore'}</button></li>`;
            }
            html += '</ul>';
        }

        html += '</div>';

        // Update preview modal to show ignored items
        $('#crp-preview-modal .crp-modal-header h3').text(switchboardCRP.i18n.ignoredItems || 'Ignored Items');
        $('#crp-preview-modal .crp-modal-body').html(html);
        $('#crp-preview-modal').show();

        // Bind unignore handlers
        $('.crp-unignore-btn').off('click').on('click', function() {
            const $btn = $(this);
            const type = $btn.data('type');
            const item = $btn.data('item');

            $btn.prop('disabled', true).text('...');

            $.ajax({
                url: switchboardCRP.ajaxurl,
                type: 'POST',
                data: {
                    action: 'switchboard_crp_unignore',
                    nonce: switchboardCRP.nonce,
                    type: type,
                    item: item
                },
                success: function(response) {
                    if (response.success) {
                        $btn.closest('li').fadeOut(200, function() { $(this).remove(); });
                        showToast(switchboardCRP.i18n.unignored || 'Item will appear in future scans', 'success');
                    } else {
                        $btn.prop('disabled', false).text(switchboardCRP.i18n.unignore || 'Un-ignore');
                        showToast(response.data?.message || switchboardCRP.i18n.error, 'error');
                    }
                },
                error: function() {
                    $btn.prop('disabled', false).text(switchboardCRP.i18n.unignore || 'Un-ignore');
                    showToast(switchboardCRP.i18n.error, 'error');
                }
            });
        });
    }

    /**
     * Show truncation warning if needed
     */
    function showTruncationWarning(type) {
        if (state.truncated[type]) {
            const $container = $(`#tab-${type}`).find('.sb-module-card-header');
            if ($container.find('.crp-truncation-warning').length === 0) {
                $container.append(`
                    <div class="crp-truncation-warning">
                        <span class="dashicons dashicons-info"></span>
                        ${switchboardCRP.i18n.optionsTruncated || 'Showing first 200 results. Clean up some items and re-scan to see more.'}
                    </div>
                `);
            }
        }
    }

    /**
     * Show ignored count indicator
     */
    function showIgnoredIndicator() {
        const total = state.ignored.tables + state.ignored.options + state.ignored.crons;
        if (total > 0) {
            const $header = $('.sb-module-header-right');
            if ($header.find('.crp-ignored-indicator').length === 0) {
                const label = (switchboardCRP.i18n.ignoredCount || '%d ignored').replace('%d', total);
                $header.prepend(`
                    <button type="button" class="crp-ignored-indicator button button-secondary" id="show-ignored-btn">
                        <span class="dashicons dashicons-hidden"></span>
                        ${label}
                    </button>
                `);

                $('#show-ignored-btn').on('click', showIgnoredItems);
            } else {
                const label = (switchboardCRP.i18n.ignoredCount || '%d ignored').replace('%d', total);
                $header.find('.crp-ignored-indicator').html(`<span class="dashicons dashicons-hidden"></span> ${label}`);
            }
        }
    }

})(jQuery);
