<?php
/**
 * Name: Regenerate Thumbnails
 * Description: Regenerate image thumbnails for all existing images or selected images after changing thumbnail sizes, switching themes, or adding new custom image sizes
 * Category: Media
 * Icon: -
 * UseCases: [
 *   {
 *     "title": "Theme Switch Recovery",
 *     "description": "Regenerate thumbnails after switching themes that use different image sizes to fix broken or improperly sized images."
 *   },
 *   {
 *     "title": "Fix Missing Thumbnails",
 *     "description": "Recreate missing thumbnail files after server migration or accidental deletion without re-uploading 500+ original images."
 *   },
 *   {
 *     "title": "New Image Size Addition",
 *     "description": "Generate thumbnails for newly added custom image size across all existing media to populate WooCommerce or blog layouts."
 *   }
 * ]
 * Added: 2025-08-08
 * Tags: thumbnails, images, regenerate, media, batch
 * WhereToFind: {
 *   "location": "Switchboard Settings",
 *   "url": "",
 *   "instructions": "Select images and regenerate all thumbnail sizes in module settings. Useful after changing image dimensions or switching themes.",
 *   "newTab": false
 * }
 */

// Prevent direct access
if (!defined('ABSPATH')) exit;

class SwitchboardRegenerateThumbnails {

    public function __construct() {
        add_action('wp_ajax_switchboard_regenerate_thumbnail', [$this, 'ajax_regenerate']);
        add_action('wp_ajax_switchboard_regenerate_get_image_sizes', [$this, 'ajax_get_image_sizes']);
    }

    /**
     * Register data locations for cleanup system
     *
     * @return array Data storage locations
     */
    public function register_data_locations() {
        return [
            'options' => [],
            'option_patterns' => [],
            'tables' => [],
            'post_meta' => [],
            'user_meta' => [],
        ];
    }

    /**
     * Render settings panel for Regenerate Thumbnails
     * 
     * Displays comprehensive batch processing interface for regenerating all image thumbnails with:
     * - Statistics card showing total number of images to process
     * - Dynamic loading and display of all registered image sizes (WordPress defaults, theme/plugin, custom)
     * - Image sizes table with dimensions, crop settings, and type classification
     * - Start/Stop buttons for controlling the batch regeneration process
     * - Real-time progress bar showing percentage completion
     * - Live activity log displaying each image being processed with success/failure status
     * - Browser navigation prevention during active regeneration to avoid interruption
     * - Scrolling log output for monitoring large batch operations
     * 
     * The interface uses AJAX to load available image sizes on page load via switchboard_get_image_sizes
     * action. The regeneration process iterates through all image attachments sequentially, calling
     * switchboard_regenerate_thumbnail for each one. Progress updates happen in real-time via jQuery
     * DOM manipulation. The JavaScript prevents page navigation while processing is active using the
     * beforeunload event. Users can stop the process mid-way, and the interface tracks completion
     * state. The log displays timestamped entries for each image with color-coded success/failure
     * indicators. This tool is essential after adding custom image sizes, changing theme dimensions,
     * or migrating content, as it ensures all necessary thumbnail variations exist for every image.
     * 
     * @param array $settings Current module settings (not used - this is a tool without persistent settings)
     * @return void Outputs HTML directly
     */
    public function render_settings($settings = []) {
        $attachments = get_posts([
            'post_type' => 'attachment',
            'post_mime_type' => 'image',
            'posts_per_page' => -1,
            'fields' => 'ids'
        ]);

        $total = count($attachments);

        $html = '
            <input type="hidden" name="module" value="regenerate-thumbnails">

            <!-- Stats -->
            <div class="sb-sp-card" style="margin-bottom: 24px;">
                <div class="sb-sp-card-body" style="display: flex; justify-content: space-between; align-items: center;">
                    <div>
                        <p style="margin: 0; font-size: 13px; color: #6b7280;">Total Images</p>
                        <p style="margin: 0; font-size: 24px; font-weight: 600; color: #111827;">'. number_format($total) . '</p>
                    </div>
                    <span class="dashicons dashicons-images-alt2" style="font-size: 48px; color: #9ca3af;"></span>
                </div>
            </div>

            <!-- Image Sizes -->
            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">Registered Image Sizes</h3>
                <p class="sb-sp-description">All image sizes that will be regenerated for each image.</p>

                <div id="image-sizes-list">
                    <div style="text-align: center; padding: 20px;">
                        <span class="dashicons dashicons-update" style="font-size: 24px; animation: spin 1s linear infinite;"></span>
                        <p style="margin-top: 8px; font-size: 13px; color: #6b7280;">Loading...</p>
                    </div>
                </div>
            </div>

            <hr class="sb-sp-divider">

            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">Regenerate Thumbnails</h3>
                <p class="sb-sp-description">Click the button below to start regenerating thumbnails for all ' . number_format($total) . ' images. This process may take several minutes depending on the number of images.</p>

                <div class="sb-sp-button-group" style="margin-top: 16px;">
                    <button type="button" id="start-regenerate" class="button button-primary">
                        <span class="dashicons dashicons-image-rotate" style="vertical-align: middle; margin-right: 4px;"></span> Start Regenerating
                    </button>
                    <button type="button" id="stop-regenerate" class="button button-secondary hidden">
                        <span class="dashicons dashicons-no" style="vertical-align: middle; margin-right: 4px;"></span> Stop
                    </button>
                </div>
            </div>

            <div id="regenerate-status" class="sb-sp-card hidden" style="margin-bottom: 24px;">
                <div class="sb-sp-card-body">
                    <p style="margin: 0 0 12px 0;"><strong>Progress:</strong> <span id="progress-count">0</span> / ' . $total . '</p>
                    <div class="sb-sp-progress-bar-container">
                        <div id="progress-bar" class="sb-sp-progress-bar" style="width: 0%;"></div>
                    </div>
                    <p id="current-image" style="margin: 8px 0 0 0; font-size: 13px; color: #6b7280;"></p>
                </div>
            </div>

            <div id="regenerate-log" class="sb-sp-card hidden" style="margin-bottom: 24px;">
                <div class="sb-sp-card-body">
                    <h4 class="sb-sp-heading-sm" style="margin: 0 0 12px 0;">Activity Log</h4>
                    <div id="log-content" style="max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; line-height: 1.6; background: #f9fafb; padding: 12px; border-radius: 6px; border: 1px solid #e5e7eb;"></div>
                </div>
            </div>
            
            <style>
                @keyframes spin {
                    from { transform: rotate(0deg); }
                    to { transform: rotate(360deg); }
                }
            </style>

            <script>
            jQuery(document).ready(function($) {
                // Ensure ajaxurl is available
                var ajaxUrl = (typeof switchboardSettings !== "undefined" && switchboardSettings.ajaxurl)
                    ? switchboardSettings.ajaxurl
                    : "' . admin_url('admin-ajax.php') . '";

                // Load image sizes
                $.ajax({
                    url: ajaxUrl,
                    type: "POST",
                    data: {
                        action: "switchboard_regenerate_get_image_sizes",
                        nonce: switchboardSettings.settings_nonce
                    },
                    success: function(response) {
                        if (response.success && response.data.sizes) {
                            var html = "<div class=\"sb-sp-card\">";
                            html += "<div class=\"sb-sp-card-body\">";
                            html += "<table class=\"widefat\" style=\"margin: 0; border: 0; border-collapse: collapse;\">";
                            html += "<thead>";
                            html += "<tr style=\"background: #f9fafb; border-bottom: 2px solid #e5e7eb;\">";
                            html += "<th style=\"padding: 12px 16px; text-align: left; font-weight: 600; color: #374151; font-size: 13px; border: 0;\">Size Name</th>";
                            html += "<th style=\"padding: 12px 16px; text-align: left; font-weight: 600; color: #374151; font-size: 13px; border: 0;\">Dimensions</th>";
                            html += "<th style=\"padding: 12px 16px; text-align: left; font-weight: 600; color: #374151; font-size: 13px; border: 0;\">Crop</th>";
                            html += "</tr>";
                            html += "</thead>";
                            html += "<tbody>";

                            $.each(response.data.sizes, function(i, size) {
                                var dimensions = size.width + " × " + size.height + " px";
                                if (size.width == 0 && size.height == 0) {
                                    dimensions = "<em>Full Size</em>";
                                } else if (size.width == 0) {
                                    dimensions = "Auto × " + size.height;
                                } else if (size.height == 0) {
                                    dimensions = size.width + " × Auto";
                                }

                                html += "<tr style=\"border-bottom: 1px solid #f3f4f6;\">";
                                html += "<td style=\"padding: 12px 16px; border: 0;\">";
                                html += "<div>";
                                html += "<div style=\"margin-bottom: 4px;\">";
                                html += "<strong style=\"color: #111827; font-size: 14px;\">" + size.label + "</strong>";
                                if (size.type === "Custom (Switchboard)") {
                                    html += " <span class=\"sb-sp-badge\" style=\"background: #dbeafe; color: #1e40af; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 500;\">Custom</span>";
                                }
                                html += "</div>";
                                html += "<code style=\"font-size: 11px; color: #6b7280; background: #f3f4f6; padding: 2px 6px; border-radius: 3px; font-family: monospace;\">" + size.name + "</code>";
                                html += "</div>";
                                html += "</td>";
                                html += "<td style=\"padding: 12px 16px; color: #374151; font-size: 14px; border: 0;\">" + dimensions + "</td>";
                                html += "<td style=\"padding: 12px 16px; color: #374151; font-size: 14px; border: 0;\">" + size.crop + "</td>";
                                html += "</tr>";
                            });

                            html += "</tbody></table></div></div>";
                            html += "<p class=\"sb-sp-description\" style=\"margin-top: 12px;\">Total: <strong>" + response.data.sizes.length + " sizes</strong> will be regenerated</p>";

                            $("#image-sizes-list").html(html);
                        } else {
                            var errorMsg = "Failed to load image sizes";
                            if (response.data && response.data.message) {
                                errorMsg = response.data.message;
                            }
                            $("#image-sizes-list").html("<div class=\"sb-sp-info-box sb-sp-info-box-tip\"><h4 class=\"sb-sp-heading-sm\">Error</h4><p class=\"sb-sp-description\" style=\"margin: 0;\">" + errorMsg + "</p></div>");
                        }
                    },
                    error: function(xhr, status, error) {
                        var errorMsg = "Failed to load image sizes";
                        if (xhr.responseJSON && xhr.responseJSON.data && xhr.responseJSON.data.message) {
                            errorMsg = xhr.responseJSON.data.message;
                        } else if (xhr.status === 403) {
                            errorMsg = "Permission denied. Please refresh the page and try again.";
                        } else if (xhr.status === 0) {
                            errorMsg = "Network error. Please check your connection.";
                        } else if (xhr.responseText) {
                            errorMsg = "Error: " + xhr.responseText.substring(0, 200);
                        }
                        $("#image-sizes-list").html("<div class=\"sb-sp-info-box sb-sp-info-box-tip\"><h4 class=\"sb-sp-heading-sm\">Error</h4><p class=\"sb-sp-description\" style=\"margin: 0;\">" + errorMsg + "</p></div>");
                    }
                });
                
                // Regenerate functionality
                var attachments = ' . wp_json_encode($attachments) . ';
                var currentIndex = 0;
                var isRunning = false;

                // Warn user before leaving page during regeneration
                $(window).on("beforeunload", function(e) {
                    if (isRunning) {
                        var message = "Thumbnail regeneration is in progress. Leaving this page will stop the process. Are you sure you want to leave?";
                        e.preventDefault();
                        e.returnValue = message;
                        return message;
                    }
                });

                $("#start-regenerate").on("click", function() {
                    if (!confirm("This will regenerate thumbnails for all ' . $total . ' images. This may take a while. Continue?")) {
                        return;
                    }

                    isRunning = true;
                    window.switchboardRegenerationRunning = true; // Set global flag for settings panel
                    currentIndex = 0;
                    $(this).hide();
                    $("#stop-regenerate").removeClass("hidden").show();
                    $("#regenerate-status").removeClass("hidden").show();
                    $("#regenerate-log").removeClass("hidden").show();
                    $("#log-content").html("");
                    addLog("Starting regeneration process...");
                    processNext();
                });

                $("#stop-regenerate").on("click", function() {
                    isRunning = false;
                    window.switchboardRegenerationRunning = false; // Clear global flag
                    $(this).hide();
                    $("#start-regenerate").show();
                    addLog("<strong style=\"color: #d63638;\">Stopped by user at " + currentIndex + " of ' . $total . ' images.</strong>");
                });
                
                function processNext() {
                    if (!isRunning || currentIndex >= attachments.length) {
                        if (currentIndex >= attachments.length) {
                            isRunning = false; // Mark as completed
                            window.switchboardRegenerationRunning = false; // Clear global flag
                            addLog("<strong style=\"color: #00a32a;\">All thumbnails regenerated successfully!</strong>");
                            $("#stop-regenerate").hide();
                            $("#start-regenerate").show();
                        }
                        return;
                    }
                    
                    var attachmentId = attachments[currentIndex];
                    
                    $.ajax({
                        url: ajaxUrl,
                        type: "POST",
                        data: {
                            action: "switchboard_regenerate_thumbnail",
                            attachment_id: attachmentId,
                            nonce: switchboardSettings.settings_nonce
                        },
                        success: function(response) {
                            currentIndex++;
                            updateProgress();
                            
                            if (response.success) {
                                addLog("<span style=\"color: #00a32a;\">Done:</span> " + response.data.title);
                            } else {
                                addLog("<span style=\"color: #d63638;\">Failed:</span> " + response.data);
                            }
                            
                            processNext();
                        },
                        error: function() {
                            currentIndex++;
                            addLog("<span style=\"color: #d63638;\">Error:</span> Error processing attachment #" + attachmentId);
                            processNext();
                        }
                    });
                }
                
                function updateProgress() {
                    var percent = (currentIndex / attachments.length) * 100;
                    $("#progress-bar").css("width", percent + "%");
                    $("#progress-count").text(currentIndex);
                    $("#current-image").text("Processing image " + currentIndex + " of " + attachments.length + " (" + Math.round(percent) + "%)");
                }
                
                function addLog(message) {
                    var timestamp = new Date().toLocaleTimeString();
                    $("#log-content").append("<div style=\"margin-bottom: 4px;\">[" + timestamp + "] " + message + "</div>");
                    var logContent = $("#log-content")[0];
                    if (logContent) {
                        logContent.scrollTop = logContent.scrollHeight;
                    }
                }
            });
            </script>
        ';
        
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- HTML is built safely with proper escaping throughout
        echo $html;
    }

    public function ajax_get_image_sizes() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => __('Unauthorized', 'wpswitchboard')]);
        }

        global $_wp_additional_image_sizes;

        if (!is_array($_wp_additional_image_sizes)) {
            $_wp_additional_image_sizes = [];
        }

        $sizes = [];

        // Get default WordPress sizes
        $default_sizes = ['thumbnail', 'medium', 'medium_large', 'large'];
        foreach ($default_sizes as $size) {
            $width = get_option($size . '_size_w');
            $height = get_option($size . '_size_h');
            $crop = get_option($size . '_crop');

            $sizes[] = [
                'name' => $size,
                'label' => ucwords(str_replace('_', ' ', $size)),
                'width' => $width ? $width : 0,
                'height' => $height ? $height : 0,
                'crop' => $crop ? 'Yes' : 'No',
                'type' => 'WordPress Default'
            ];
        }

        // Get custom sizes from Custom Image Sizes module
        $custom_sizes = get_option('switchboard_custom_image_sizes', []);
        $custom_size_names = [];
        if (!empty($custom_sizes) && is_array($custom_sizes)) {
            foreach ($custom_sizes as $size) {
                if (isset($size['name'])) {
                    $custom_size_names[] = $size['name'];
                }
            }
        }

        // Get theme and plugin registered sizes
        if (!empty($_wp_additional_image_sizes)) {
            foreach ($_wp_additional_image_sizes as $name => $size_data) {
                // Determine if this is a custom size or theme/plugin size
                $is_custom = in_array($name, $custom_size_names, true);
                $type = $is_custom ? 'Custom (Switchboard)' : 'Theme/Plugin';

                $sizes[] = [
                    'name' => $name,
                    'label' => ucwords(str_replace(['_', '-'], ' ', $name)),
                    'width' => $size_data['width'],
                    'height' => $size_data['height'],
                    'crop' => $size_data['crop'] ? 'Yes' : 'No',
                    'type' => $type
                ];
            }
        }

        wp_send_json_success(['sizes' => $sizes]);
    }

    public function ajax_regenerate() {
        check_ajax_referer('switchboard_settings', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error(__('Unauthorized', 'wpswitchboard'));
        }

        $attachment_id = isset($_POST['attachment_id']) ? intval($_POST['attachment_id']) : 0;
        $file = get_attached_file($attachment_id);

        if (!$file || !file_exists($file)) {
            wp_send_json_error(__('File not found', 'wpswitchboard'));
        }
        
        // Get upload directory for security validation
        $upload_dir = wp_upload_dir();
        $upload_path = $upload_dir['basedir'];

        // Delete old thumbnails
        $metadata = wp_get_attachment_metadata($attachment_id);
        if (isset($metadata['sizes']) && is_array($metadata['sizes'])) {
            foreach ($metadata['sizes'] as $size => $sizeinfo) {
                if (!is_array($sizeinfo) || !isset($sizeinfo['file'])) {
                    continue;
                }
                $intermediate_file = str_replace(basename($file), $sizeinfo['file'], $file);

                // Security: Ensure file is within uploads directory
                if (strpos(realpath($intermediate_file), realpath($upload_path)) === 0 && file_exists($intermediate_file)) {
                    wp_delete_file($intermediate_file);
                }
            }
        }

        // Regenerate thumbnails
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $metadata = wp_generate_attachment_metadata($attachment_id, $file);
        wp_update_attachment_metadata($attachment_id, $metadata);

        $title = get_the_title($attachment_id);
        if (empty($title)) {
            $title = basename($file);
        }

        wp_send_json_success([
            'title' => sanitize_text_field($title)
        ]);
    }
}

// Initialize and register with data system
$switchboard_instance = new SwitchboardRegenerateThumbnails();
Switchboard_Data_Registry::get_instance()->auto_register($switchboard_instance, __FILE__);
