<?php
/**
 * Name: Download Media Library
 * Description: Export your entire media library or selected months as a ZIP file for backup, migration, or archival purposes
 * Category: Media
 * Icon: -
 * Added: 2025-12-24
 * Tags: media, download, zip, backup, export, archive
 * WhereToFind: {
 *   "location": "Switchboard Settings",
 *   "url": "admin.php?page=switchboard",
 *   "instructions": "Find this module in the Media category and click to access settings",
 *   "newTab": false
 * }
 * UseCases: [
 *   {
 *     "title": "Full Site Backup",
 *     "description": "Download your entire media library as a ZIP file before migrating to a new host or performing major updates."
 *   },
 *   {
 *     "title": "Monthly Archives",
 *     "description": "Create monthly backups of uploaded media for archival and compliance purposes."
 *   },
 *   {
 *     "title": "Client Handoff",
 *     "description": "Package all media files to deliver to clients when a project is complete or for their records."
 *   }
 * ]
 */

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

class SwitchboardDownloadMediaLibrary {

    public function __construct() {
        add_action('wp_ajax_switchboard_download_media_library', [$this, 'ajax_download_media_library']);
        add_action('wp_ajax_switchboard_get_media_library_stats', [$this, 'ajax_get_media_library_stats']);
        add_action('wp_ajax_switchboard_delete_media_library_zip', [$this, 'ajax_delete_media_library_zip']);
        add_action('wp_ajax_switchboard_get_existing_media_zips', [$this, 'ajax_get_existing_media_zips']);

        // Schedule cron for ZIP cleanup
        add_action('switchboard_cleanup_download_zips', [$this, 'cron_cleanup_old_zips']);
        if (!wp_next_scheduled('switchboard_cleanup_download_zips')) {
            wp_schedule_event(time(), 'hourly', 'switchboard_cleanup_download_zips');
        }

        // Register with data system
        Switchboard_Data_Registry::get_instance()->auto_register($this, __FILE__);
    }

    /**
     * Cron handler for cleaning up old ZIP files
     */
    public function cron_cleanup_old_zips() {
        $upload_dir = wp_upload_dir();
        $zip_dir = trailingslashit($upload_dir['basedir']) . 'switchboard-downloads';

        if (!file_exists($zip_dir)) {
            return;
        }

        $files = @glob($zip_dir . '/*.zip');
        if (!$files) {
            return;
        }

        $expiry_time = Switchboard_Zip_Handler::EXPIRY_TIME;

        foreach ($files as $file) {
            if (!file_exists($file)) {
                continue;
            }

            $file_age = time() - filemtime($file);

            // Check if file has associated metadata with auto_delete setting
            $zip_id = basename($file, '.zip');
            $meta_file = $zip_dir . '/' . $zip_id . '.json';

            if (file_exists($meta_file)) {
                $meta = json_decode(file_get_contents($meta_file), true);
                // If auto_delete is explicitly false, skip this file
                if (isset($meta['auto_delete']) && $meta['auto_delete'] === false) {
                    continue;
                }
            }

            // Delete if older than expiry time
            if ($file_age > $expiry_time) {
                @unlink($file);
                // Also delete associated meta file if exists
                if (file_exists($meta_file)) {
                    @unlink($meta_file);
                }
            }
        }
    }

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

    /**
     * Render settings panel
     */
    public function render_settings($settings = []) {
        // Clean up expired ZIPs when panel loads
        $this->cron_cleanup_old_zips();

        global $wpdb;

        // Get media library statistics
        $total_count = (int) $wpdb->get_var("
            SELECT COUNT(*) FROM {$wpdb->posts}
            WHERE post_type = 'attachment' AND post_status = 'inherit'
        ");

        // Get months with media
        $months = $wpdb->get_results("
            SELECT
                YEAR(post_date) as year,
                MONTH(post_date) as month,
                COUNT(*) as count
            FROM {$wpdb->posts}
            WHERE post_type = 'attachment' AND post_status = 'inherit'
            GROUP BY YEAR(post_date), MONTH(post_date)
            ORDER BY year DESC, month DESC
        ");

        // Calculate total size estimate
        $total_size = 0;
        $attachments = get_posts([
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'posts_per_page' => -1,
            'fields' => 'ids',
        ]);
        foreach ($attachments as $attachment_id) {
            $file_path = get_attached_file($attachment_id);
            if ($file_path && file_exists($file_path)) {
                $total_size += filesize($file_path);
            }
        }

        $nonce = wp_create_nonce('switchboard_nonce');
        ?>
        <style>
            .sb-media-download .sb-stats-grid {
                display: grid;
                grid-template-columns: repeat(2, 1fr);
                gap: 16px;
            }
            .sb-media-download .sb-stat-item {
                text-align: center;
            }
            .sb-media-download .sb-stat-value {
                font-size: 24px;
                font-weight: 600;
                color: #111827;
            }
            .sb-media-download .sb-stat-label {
                font-size: 12px;
                color: #6b7280;
                text-transform: uppercase;
                letter-spacing: 0.5px;
            }
            .sb-media-download .sb-month-selector {
                max-height: 300px;
                overflow-y: auto;
                margin-bottom: 16px;
            }
            .sb-media-download .sb-module-button .spinner {
                animation: sb-spin 1s linear infinite;
            }
            @keyframes sb-spin {
                from { transform: rotate(0deg); }
                to { transform: rotate(360deg); }
            }
            .sb-media-download .sb-download-progress {
                display: none;
                margin-top: 16px;
                padding: 12px;
                background: #eff6ff;
                border: 1px solid #bfdbfe;
                border-radius: 6px;
                font-size: 13px;
                color: #1e40af;
            }
            .sb-media-download .sb-download-result {
                display: none;
                margin-top: 16px;
            }
            .sb-media-download .sb-download-result h5 {
                margin: 0 0 8px 0;
                font-size: 14px;
                font-weight: 600;
                color: #166534;
            }
            .sb-media-download .sb-download-result p {
                margin: 0 0 12px 0;
                font-size: 12px;
                color: #6b7280;
            }
            .sb-media-download .sb-download-result .sb-btn-group {
                display: flex;
                gap: 8px;
                flex-wrap: wrap;
            }
            .sb-media-download .sb-select-actions {
                display: flex;
                gap: 8px;
                margin-bottom: 8px;
            }
            .sb-media-download .sb-select-actions button {
                padding: 4px 8px;
                font-size: 11px;
                background: #f3f4f6;
                border: 1px solid #d1d5db;
                border-radius: 4px;
                cursor: pointer;
            }
            .sb-media-download .sb-select-actions button:hover {
                background: #e5e7eb;
            }
            .sb-media-download .sb-existing-zips-table {
                width: 100%;
                border-collapse: collapse;
                font-size: 13px;
            }
            .sb-media-download .sb-existing-zips-table th {
                text-align: left;
                padding: 8px 12px;
                background: #f9fafb;
                border-bottom: 1px solid #e5e7eb;
                font-weight: 500;
                color: #6b7280;
                font-size: 11px;
                text-transform: uppercase;
            }
            .sb-media-download .sb-existing-zips-table td {
                padding: 10px 12px;
                border-bottom: 1px solid #f3f4f6;
                vertical-align: middle;
            }
            .sb-media-download .sb-existing-zips-table tr:last-child td {
                border-bottom: none;
            }
            .sb-media-download .sb-existing-zips-table .sb-zip-actions {
                display: flex;
                gap: 6px;
            }
            .sb-media-download .sb-existing-zips-table .sb-zip-actions a,
            .sb-media-download .sb-existing-zips-table .sb-zip-actions button {
                font-size: 11px;
                padding: 4px 8px;
            }
            .sb-media-download .sb-existing-zips-table .sb-zip-actions a.sb-module-button-primary {
                background: #4f7df3;
                border-color: #4f7df3;
                color: white;
            }
            .sb-media-download .sb-inline-error {
                display: none;
                margin-top: 12px;
                padding: 10px 14px;
                background: #fef2f2;
                border: 1px solid #fecaca;
                border-radius: 6px;
                color: #dc2626;
                font-size: 13px;
            }
            .sb-media-download .sb-inline-error .sb-error-dismiss {
                float: right;
                cursor: pointer;
                font-weight: bold;
                color: #9ca3af;
                margin-left: 8px;
            }
            .sb-media-download .sb-inline-error .sb-error-dismiss:hover {
                color: #dc2626;
            }
            .sb-media-download .sb-download-progress .sb-progress-bar {
                height: 6px;
                background: #dbeafe;
                border-radius: 3px;
                margin-top: 8px;
                overflow: hidden;
            }
            .sb-media-download .sb-download-progress .sb-progress-bar-fill {
                height: 100%;
                background: #3b82f6;
                width: 0%;
                border-radius: 3px;
                animation: sb-progress-pulse 2s ease-in-out infinite;
            }
            @keyframes sb-progress-pulse {
                0%, 100% { width: 30%; margin-left: 0%; }
                50% { width: 50%; margin-left: 25%; }
            }
        </style>

        <div class="sb-media-download">
            <input type="hidden" id="media-download-nonce" value="<?php echo esc_attr($nonce); ?>">

            <div class="sb-sp-info-box sb-sp-info-box-info" style="margin-bottom: 24px;">
                <h4 class="sb-sp-heading-sm">Download Media Library</h4>
                <p class="sb-sp-description" style="margin-bottom: 12px;">Export your entire media library or selected months as a ZIP file for backup, migration, or archival purposes.</p>
                <div class="sb-stats-grid">
                    <div class="sb-stat-item">
                        <div class="sb-stat-value"><?php echo number_format($total_count); ?></div>
                        <div class="sb-stat-label">Total Files</div>
                    </div>
                    <div class="sb-stat-item">
                        <div class="sb-stat-value"><?php echo size_format($total_size); ?></div>
                        <div class="sb-stat-label">Total Size</div>
                    </div>
                </div>
            </div>

            <?php if ($total_size > 500 * 1024 * 1024): ?>
            <div class="sb-sp-info-box sb-sp-info-box-tip" style="margin-bottom: 24px;">
                <p class="sb-sp-description" style="margin: 0;"><strong>Large Library Warning:</strong> Your media library exceeds 500MB. Consider downloading by month to avoid timeout issues on some servers.</p>
            </div>
            <?php endif; ?>

            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <div class="sb-module-option-item sb-module-toggle-item">
                    <div class="sb-module-option-content">
                        <div class="sb-module-toggle-header">
                            <strong class="sb-module-option-title">Auto-delete ZIP files</strong>
                            <label class="sb-module-toggle">
                                <input type="checkbox" id="auto-delete-toggle" checked>
                                <span class="sb-module-toggle-slider"></span>
                            </label>
                        </div>
                        <p class="sb-module-option-text">When enabled, ZIP files are automatically deleted after 1 hour. Disable to keep them until manually deleted.</p>
                    </div>
                </div>
            </div>

            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">Download Full Library</h3>
                <p class="sb-sp-description" style="margin-bottom: 16px;">Download all <?php echo number_format($total_count); ?> media files as a single ZIP archive.</p>
                <button type="button" class="sb-module-button sb-module-button-primary" id="download-full-library" <?php echo $total_count === 0 ? 'disabled' : ''; ?>>
                    Download All Media
                </button>
                <div class="sb-download-progress" id="full-library-progress">
                    <span>Creating ZIP file... This may take a while for large libraries.</span>
                    <div class="sb-progress-bar"><div class="sb-progress-bar-fill"></div></div>
                </div>
                <div class="sb-inline-error" id="full-library-error">
                    <span class="sb-error-dismiss">&times;</span>
                    <span class="sb-error-message"></span>
                </div>
                <div class="sb-download-result sb-sp-info-box sb-sp-info-box-success" id="full-library-result"></div>
            </div>

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

            <div class="sb-sp-group" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">Download by Month</h3>
                <p class="sb-sp-description" style="margin-bottom: 16px;">Select specific months to download. Useful for large libraries or monthly backups.</p>

                <?php if (!empty($months)): ?>
                <div class="sb-select-actions">
                    <button type="button" id="select-all-months">Select All</button>
                    <button type="button" id="deselect-all-months">Deselect All</button>
                </div>
                <div class="sb-month-selector" id="month-selector">
                    <?php foreach ($months as $month_data):
                        $month_key = $month_data->year . '-' . str_pad($month_data->month, 2, '0', STR_PAD_LEFT);
                        $month_name = date_i18n('F Y', strtotime($month_key . '-01'));
                    ?>
                    <div class="sb-module-option-item sb-module-toggle-item">
                        <div class="sb-module-option-content">
                            <div class="sb-module-toggle-header">
                                <div>
                                    <strong class="sb-module-option-title"><?php echo esc_html($month_name); ?></strong>
                                    <span style="font-size: 11px; color: #9ca3af; margin-left: 8px;"><?php echo number_format($month_data->count); ?> files</span>
                                </div>
                                <label class="sb-module-toggle">
                                    <input type="checkbox" class="month-checkbox" value="<?php echo esc_attr($month_key); ?>">
                                    <span class="sb-module-toggle-slider"></span>
                                </label>
                            </div>
                        </div>
                    </div>
                    <?php endforeach; ?>
                </div>
                <button type="button" class="sb-module-button sb-module-button-primary" id="download-selected-months" disabled>
                    Download Selected Months
                </button>
                <?php else: ?>
                <p class="sb-sp-description" style="font-style: italic;">No media files found in your library.</p>
                <?php endif; ?>
                <div class="sb-download-progress" id="monthly-progress">
                    <span>Creating ZIP file... This may take a while.</span>
                    <div class="sb-progress-bar"><div class="sb-progress-bar-fill"></div></div>
                </div>
                <div class="sb-inline-error" id="monthly-error">
                    <span class="sb-error-dismiss">&times;</span>
                    <span class="sb-error-message"></span>
                </div>
                <div class="sb-download-result sb-sp-info-box sb-sp-info-box-success" id="monthly-result"></div>
            </div>

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

            <div class="sb-sp-group" id="existing-zips-section" style="margin-bottom: 24px;">
                <h3 class="sb-sp-heading">Existing ZIP Files</h3>
                <p class="sb-sp-description" style="margin-bottom: 16px;">Previously created ZIP files that are still available on the server.</p>
                <div class="sb-inline-error" id="existing-zips-error">
                    <span class="sb-error-dismiss">&times;</span>
                    <span class="sb-error-message"></span>
                </div>
                <div id="existing-zips-list">
                    <p class="sb-sp-description" style="font-style: italic;">Loading...</p>
                </div>
            </div>

            <div class="sb-sp-info-box sb-sp-info-box-tip">
                <h4 class="sb-sp-heading-sm">How It Works</h4>
                <ul class="sb-sp-list">
                    <li class="sb-sp-list-item"><strong>ZIP Creation:</strong> Files are organized by year/month folders in the ZIP archive</li>
                    <li class="sb-sp-list-item"><strong>Auto-delete:</strong> When enabled, ZIPs are automatically deleted after 1 hour. Disable to keep them indefinitely.</li>
                    <li class="sb-sp-list-item"><strong>Size Limit:</strong> Maximum 500MB per download to avoid timeouts</li>
                </ul>
            </div>
        </div>

        <script>
        jQuery(document).ready(function($) {
            const nonce = $('#media-download-nonce').val();

            // Enable/disable download button based on selection
            $('#month-selector .month-checkbox').on('change', function() {
                const checked = $('#month-selector .month-checkbox:checked').length;
                $('#download-selected-months').prop('disabled', checked === 0);
            });

            // Select all months
            $('#select-all-months').on('click', function() {
                $('#month-selector .month-checkbox').prop('checked', true).trigger('change');
            });

            // Deselect all months
            $('#deselect-all-months').on('click', function() {
                $('#month-selector .month-checkbox').prop('checked', false).trigger('change');
            });

            // Download full library
            $('#download-full-library').on('click', function() {
                const $btn = $(this);
                downloadMedia($btn, 'all', null, '#full-library-progress', '#full-library-result', '#full-library-error');
            });

            // Download selected months
            $('#download-selected-months').on('click', function() {
                const $btn = $(this);
                const selectedMonths = [];
                $('#month-selector .month-checkbox:checked').each(function() {
                    selectedMonths.push($(this).val());
                });

                if (selectedMonths.length === 0) {
                    showError('#monthly-error', 'Please select at least one month.');
                    return;
                }

                downloadMedia($btn, 'months', selectedMonths, '#monthly-progress', '#monthly-result', '#monthly-error');
            });

            // Error dismiss handlers
            $('.sb-error-dismiss').on('click', function() {
                $(this).closest('.sb-inline-error').slideUp();
            });

            function showError(selector, message) {
                $(selector).find('.sb-error-message').text(message);
                $(selector).slideDown();
            }

            function downloadMedia($btn, type, months, progressSelector, resultSelector, errorSelector) {
                const originalHtml = $btn.html();

                $btn.prop('disabled', true).html('Creating ZIP...');
                $(progressSelector).slideDown();
                $(resultSelector).slideUp();
                $(errorSelector).slideUp();

                const autoDelete = $('#auto-delete-toggle').is(':checked');

                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'switchboard_download_media_library',
                        type: type,
                        months: months,
                        auto_delete: autoDelete ? 1 : 0,
                        nonce: nonce
                    },
                    timeout: 600000, // 10 minute timeout
                    success: function(response) {
                        $btn.prop('disabled', false).html(originalHtml);
                        $(progressSelector).slideUp();

                        if (response.success) {
                            showResult(resultSelector, response.data);
                        } else {
                            showError(errorSelector, response.data || 'Failed to create ZIP');
                        }
                    },
                    error: function(xhr, status, error) {
                        $btn.prop('disabled', false).html(originalHtml);
                        $(progressSelector).slideUp();

                        if (status === 'timeout') {
                            showError(errorSelector, 'Request timed out. Try downloading smaller batches (by month).');
                        } else {
                            showError(errorSelector, 'Error creating ZIP file: ' + error);
                        }
                    }
                });
            }

            function showResult(selector, data) {
                const html = `
                    <h5 style="margin: 0 0 8px 0; font-size: 14px; font-weight: 600; color: #166534;">Download Ready!</h5>
                    <p class="sb-sp-description" style="margin-bottom: 12px;">${data.file_count} files (${data.size}) - File will be deleted from server after 1 hour.</p>
                    <div class="sb-btn-group" style="display: flex; gap: 8px;">
                        <a href="${data.download_url}" download="${data.filename}" class="sb-module-button sb-module-button-primary" style="background: #4f7df3; border-color: #4f7df3; color: white; text-decoration: none;">Download ZIP</a>
                        <button type="button" class="sb-module-button sb-module-button-danger sb-delete-btn" data-zip-id="${data.zip_id}">Delete from Server</button>
                    </div>
                `;

                $(selector).html(html).slideDown();

                // Bind delete button
                $(selector).find('.sb-delete-btn').on('click', function() {
                    const $deleteBtn = $(this);
                    const zipId = $deleteBtn.data('zip-id');
                    const errorSelector = selector.replace('-result', '-error');

                    $deleteBtn.prop('disabled', true).text('Deleting...');

                    $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {
                            action: 'switchboard_delete_media_library_zip',
                            zip_id: zipId,
                            nonce: nonce
                        },
                        success: function(response) {
                            if (response.success) {
                                $(selector).slideUp();
                            } else {
                                $deleteBtn.prop('disabled', false).text('Delete from Server');
                                showError(errorSelector, 'Failed to delete file from server.');
                            }
                        },
                        error: function() {
                            $deleteBtn.prop('disabled', false).text('Delete from Server');
                            showError(errorSelector, 'Error deleting file. Please try again.');
                        }
                    });
                });
            }

            // Load existing ZIPs on page load
            loadExistingZips();

            function loadExistingZips() {
                $.ajax({
                    url: ajaxurl,
                    type: 'POST',
                    data: {
                        action: 'switchboard_get_existing_media_zips',
                        nonce: nonce
                    },
                    success: function(response) {
                        if (response.success && response.data.zips.length > 0) {
                            renderExistingZips(response.data.zips);
                        } else {
                            $('#existing-zips-list').html('<p class="sb-sp-description" style="font-style: italic;">No existing ZIP files found.</p>');
                        }
                    },
                    error: function() {
                        $('#existing-zips-list').html('<p class="sb-sp-description" style="font-style: italic; color: #dc2626;">Failed to load existing ZIP files.</p>');
                    }
                });
            }

            function renderExistingZips(zips) {
                // Filter out expired files from display
                zips = zips.filter(function(zip) { return !zip.is_expired; });

                if (zips.length === 0) {
                    $('#existing-zips-list').html('<p class="sb-sp-description" style="font-style: italic;">No existing ZIP files found.</p>');
                    return;
                }

                let html = `
                    <table class="sb-existing-zips-table">
                        <thead>
                            <tr>
                                <th>Type</th>
                                <th>Files</th>
                                <th>Size</th>
                                <th>Expires</th>
                                <th>Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                `;
                zips.forEach(function(zip) {
                    const expiryText = zip.auto_delete ? (zip.expires_in ? 'in ' + zip.expires_in : 'Expired') : 'Kept';
                    const expiryStyle = zip.auto_delete ? 'color: #9ca3af;' : 'color: #10b981; font-weight: 500;';
                    html += `
                        <tr data-zip-id="${zip.zip_id}">
                            <td>${zip.type === 'full' ? 'Full Library' : 'Selected Months'}</td>
                            <td>${zip.file_count}</td>
                            <td>${zip.size}</td>
                            <td style="${expiryStyle}">${expiryText}</td>
                            <td>
                                <div class="sb-zip-actions">
                                    <a href="${zip.download_url}" download="${zip.filename}" class="sb-module-button sb-module-button-primary">Download</a>
                                    <button type="button" class="sb-module-button sb-module-button-danger sb-delete-existing-btn" data-zip-id="${zip.zip_id}">Delete</button>
                                </div>
                            </td>
                        </tr>
                    `;
                });
                html += '</tbody></table>';

                $('#existing-zips-list').html(html);

                // Bind delete buttons
                $('.sb-delete-existing-btn').on('click', function() {
                    const $btn = $(this);
                    const zipId = $btn.data('zip-id');
                    const $row = $btn.closest('tr');

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

                    $.ajax({
                        url: ajaxurl,
                        type: 'POST',
                        data: {
                            action: 'switchboard_delete_media_library_zip',
                            zip_id: zipId,
                            nonce: nonce
                        },
                        success: function(response) {
                            if (response.success) {
                                $row.fadeOut(function() {
                                    $(this).remove();
                                    if ($('.sb-existing-zips-table tbody tr').length === 0) {
                                        $('#existing-zips-list').html('<p class="sb-sp-description" style="font-style: italic;">No existing ZIP files found.</p>');
                                    }
                                });
                            } else {
                                $btn.prop('disabled', false).text('Delete');
                                showError('#existing-zips-error', 'Failed to delete file from server.');
                            }
                        },
                        error: function() {
                            $btn.prop('disabled', false).text('Delete');
                            showError('#existing-zips-error', 'Error deleting file. Please try again.');
                        }
                    });
                });
            }
        });
        </script>
        <?php
    }

    /**
     * AJAX handler for downloading media library
     */
    public function ajax_download_media_library() {
        check_ajax_referer('switchboard_nonce', 'nonce');

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

        $type = isset($_POST['type']) ? sanitize_text_field($_POST['type']) : 'all';
        $months = isset($_POST['months']) ? array_map('sanitize_text_field', (array) $_POST['months']) : [];
        $auto_delete = isset($_POST['auto_delete']) ? (bool) intval($_POST['auto_delete']) : true;

        // Build query args
        $args = [
            'post_type' => 'attachment',
            'post_status' => 'inherit',
            'posts_per_page' => -1,
        ];

        // Filter by months if specified
        if ($type === 'months' && !empty($months)) {
            $date_query = ['relation' => 'OR'];
            foreach ($months as $month) {
                $parts = explode('-', $month);
                if (count($parts) === 2) {
                    $date_query[] = [
                        'year' => intval($parts[0]),
                        'month' => intval($parts[1]),
                    ];
                }
            }
            $args['date_query'] = $date_query;
        }

        $attachments = get_posts($args);

        if (empty($attachments)) {
            wp_send_json_error(__('No media files found.', 'wpswitchboard'));
        }

        // Create ZIP file
        $filename_suffix = $type === 'months' ? 'selected-months' : 'full-library';
        $result = $this->create_media_library_zip($attachments, $filename_suffix, $auto_delete);

        if (is_wp_error($result)) {
            wp_send_json_error($result->get_error_message());
        }

        wp_send_json_success([
            'download_url' => $result['url'],
            'filename' => $result['filename'],
            'file_count' => count($attachments),
            'size' => size_format($result['size']),
            'zip_id' => $result['zip_id'],
        ]);
    }

    /**
     * AJAX handler for deleting ZIP file
     */
    public function ajax_delete_media_library_zip() {
        check_ajax_referer('switchboard_nonce', 'nonce');

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

        $zip_id = isset($_POST['zip_id']) ? sanitize_text_field($_POST['zip_id']) : '';

        if (empty($zip_id)) {
            wp_send_json_error(__('Invalid ZIP ID.', 'wpswitchboard'));
        }

        // Security: Validate zip_id format to prevent path traversal
        // Only allow alphanumeric characters, hyphens, and underscores
        if (!preg_match('/^[a-zA-Z0-9_-]+$/', $zip_id)) {
            wp_send_json_error(__('Invalid ZIP ID format.', 'wpswitchboard'));
        }

        $upload_dir = wp_upload_dir();
        $zip_dir = trailingslashit($upload_dir['basedir']) . 'switchboard-downloads';
        $zip_file = $zip_dir . '/' . $zip_id . '.zip';

        // Security: Verify the file is within the expected directory
        $real_zip_dir = realpath($zip_dir);
        $real_zip_file = realpath(dirname($zip_file)) . '/' . basename($zip_file);
        if ($real_zip_dir && strpos($real_zip_file, $real_zip_dir) !== 0) {
            wp_send_json_error(__('Invalid file path.', 'wpswitchboard'));
        }

        if (file_exists($zip_file)) {
            @unlink($zip_file);
        }

        // Also delete associated metadata file if exists
        $meta_file = $zip_dir . '/' . $zip_id . '.json';
        if (file_exists($meta_file)) {
            @unlink($meta_file);
        }

        wp_send_json_success(['deleted' => true]);
    }

    /**
     * AJAX handler for getting media library stats
     */
    public function ajax_get_media_library_stats() {
        check_ajax_referer('switchboard_nonce', 'nonce');

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

        global $wpdb;

        $total_count = (int) $wpdb->get_var("
            SELECT COUNT(*) FROM {$wpdb->posts}
            WHERE post_type = 'attachment' AND post_status = 'inherit'
        ");

        wp_send_json_success([
            'total_count' => $total_count,
        ]);
    }

    /**
     * AJAX handler for getting existing ZIP files
     */
    public function ajax_get_existing_media_zips() {
        check_ajax_referer('switchboard_nonce', 'nonce');

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

        $upload_dir = wp_upload_dir();
        $zip_dir = trailingslashit($upload_dir['basedir']) . 'switchboard-downloads';

        if (!file_exists($zip_dir)) {
            wp_send_json_success(['zips' => []]);
        }

        $zips = [];
        $files = @glob($zip_dir . '/media-library-*.zip');

        if ($files) {
            foreach ($files as $file) {
                $zip_id = basename($file, '.zip');
                $filename = basename($file);
                $meta_file = $zip_dir . '/' . $zip_id . '.json';

                // Read metadata if available
                $auto_delete = true; // Default to true for backward compatibility
                $file_count_from_meta = 0;
                if (file_exists($meta_file)) {
                    $meta = json_decode(file_get_contents($meta_file), true);
                    if (isset($meta['auto_delete'])) {
                        $auto_delete = (bool) $meta['auto_delete'];
                    }
                    if (isset($meta['file_count'])) {
                        $file_count_from_meta = (int) $meta['file_count'];
                    }
                }

                // Parse type from filename (media-library-full-library-* or media-library-selected-months-*)
                $type = 'unknown';
                if (strpos($zip_id, 'full-library') !== false) {
                    $type = 'full';
                } elseif (strpos($zip_id, 'selected-months') !== false) {
                    $type = 'months';
                }

                // Get file count from ZIP if possible, or use metadata
                $file_count = $file_count_from_meta;
                if ($file_count === 0 && extension_loaded('zip') && class_exists('ZipArchive')) {
                    $zip = new ZipArchive();
                    if ($zip->open($file) === true) {
                        $file_count = $zip->numFiles;
                        $zip->close();
                    }
                }

                // Calculate time remaining before auto-delete
                $file_time = filemtime($file);
                $expiry_time = Switchboard_Zip_Handler::EXPIRY_TIME;
                $time_remaining = ($file_time + $expiry_time) - time();
                $is_expired = $auto_delete && $time_remaining <= 0;

                // Skip expired files with auto_delete enabled
                if ($is_expired) {
                    continue;
                }

                // Determine expiry display
                if ($auto_delete) {
                    $expires_human = $time_remaining > 0 ? human_time_diff(time(), $file_time + $expiry_time) : 'Expired';
                } else {
                    $expires_human = null; // No expiry
                }

                $zips[] = [
                    'zip_id' => $zip_id,
                    'download_url' => trailingslashit($upload_dir['baseurl']) . 'switchboard-downloads/' . $filename,
                    'filename' => $filename,
                    'type' => $type,
                    'file_count' => $file_count,
                    'created' => $file_time,
                    'created_human' => human_time_diff($file_time) . ' ago',
                    'expires_in' => $expires_human,
                    'is_expired' => $is_expired,
                    'auto_delete' => $auto_delete,
                    'size' => size_format(filesize($file)),
                ];
            }
        }

        // Sort by creation time (newest first)
        usort($zips, function($a, $b) {
            return $b['created'] - $a['created'];
        });

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

    /**
     * Create ZIP file containing media library files
     */
    private function create_media_library_zip($attachments, $suffix, $auto_delete = true) {
        // Check for ZIP support
        $use_ziparchive = extension_loaded('zip') && class_exists('ZipArchive');
        $use_pclzip = !$use_ziparchive;

        if (!$use_ziparchive && !class_exists('PclZip')) {
            require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
            $use_pclzip = class_exists('PclZip');
        }

        if (!$use_ziparchive && !$use_pclzip) {
            return new WP_Error(
                'zip_not_available',
                __('ZIP extension is not available on this server.', 'wpswitchboard')
            );
        }

        // Increase limits
        @ini_set('memory_limit', '512M');
        @set_time_limit(600);

        // Create downloads directory
        $upload_dir = wp_upload_dir();
        $zip_dir = trailingslashit($upload_dir['basedir']) . 'switchboard-downloads';

        if (!file_exists($zip_dir)) {
            wp_mkdir_p($zip_dir);
            file_put_contents($zip_dir . '/index.php', '<?php // Silence is golden');
            file_put_contents($zip_dir . '/.htaccess', "Options -Indexes\n");
        }

        // Clean up old ZIPs
        $this->cleanup_old_zips($zip_dir);

        // Generate unique ZIP ID and filename
        $site_name = sanitize_file_name(get_bloginfo('name'));
        $date = date('Y-m-d');
        $zip_id = 'media-library-' . $suffix . '-' . $date . '-' . wp_generate_password(8, false);
        $zip_file = $zip_dir . '/' . $zip_id . '.zip';
        $zip_filename = $site_name . '-media-' . $suffix . '-' . $date . '.zip';

        // Calculate total size
        $total_size = 0;
        foreach ($attachments as $attachment) {
            $file_path = get_attached_file($attachment->ID);
            if ($file_path && file_exists($file_path)) {
                $total_size += filesize($file_path);
            }
        }

        // Check size limit (500MB for ZIP creation)
        if ($total_size > 500 * 1024 * 1024) {
            return new WP_Error(
                'file_too_large',
                sprintf(
                    __('Total file size (%s) exceeds maximum allowed (500MB). Try downloading by month.', 'wpswitchboard'),
                    size_format($total_size)
                )
            );
        }

        // Check disk space using centralized handler
        if (!Switchboard_Zip_Handler::get_instance()->has_disk_space($total_size)) {
            return new WP_Error(
                'insufficient_space',
                __('Insufficient disk space to create ZIP file.', 'wpswitchboard')
            );
        }

        // Create ZIP
        if ($use_ziparchive) {
            $result = $this->create_zip_ziparchive($zip_file, $attachments);
        } else {
            $result = $this->create_zip_pclzip($zip_file, $attachments);
        }

        if (is_wp_error($result)) {
            return $result;
        }

        // Verify ZIP was created
        if (!file_exists($zip_file) || filesize($zip_file) === 0) {
            return new WP_Error(
                'zip_creation_failed',
                __('Failed to create ZIP file.', 'wpswitchboard')
            );
        }

        $download_url = trailingslashit($upload_dir['baseurl']) . 'switchboard-downloads/' . $zip_id . '.zip';

        // Save metadata
        $meta_file = $zip_dir . '/' . $zip_id . '.json';
        $metadata = [
            'type' => 'media-library',
            'suffix' => $suffix,
            'file_count' => count($attachments),
            'created' => time(),
            'auto_delete' => $auto_delete,
        ];
        file_put_contents($meta_file, json_encode($metadata));

        return [
            'url' => $download_url,
            'filename' => $zip_filename,
            'zip_id' => $zip_id,
            'size' => filesize($zip_file),
            'auto_delete' => $auto_delete,
        ];
    }

    /**
     * Create ZIP using ZipArchive
     */
    private function create_zip_ziparchive($zip_file, $attachments) {
        $zip = new ZipArchive();

        if ($zip->open($zip_file, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
            return new WP_Error(
                'zip_create_failed',
                __('Failed to create ZIP archive.', 'wpswitchboard')
            );
        }

        $file_count = 0;
        $used_names = [];

        foreach ($attachments as $attachment) {
            $file_path = get_attached_file($attachment->ID);

            if (!$file_path || !file_exists($file_path) || !is_readable($file_path)) {
                continue;
            }

            // Organize by year/month folders
            $year = date('Y', strtotime($attachment->post_date));
            $month = date('m', strtotime($attachment->post_date));
            $folder = $year . '/' . $month . '/';

            $filename = basename($file_path);
            $full_path = $folder . $filename;

            // Handle duplicate filenames
            if (isset($used_names[$full_path])) {
                $used_names[$full_path]++;
                $ext = pathinfo($filename, PATHINFO_EXTENSION);
                $name = pathinfo($filename, PATHINFO_FILENAME);
                $full_path = $folder . $name . '-' . $used_names[$full_path] . '.' . $ext;
            } else {
                $used_names[$full_path] = 1;
            }

            if (@$zip->addFile($file_path, $full_path)) {
                $file_count++;
            }
        }

        if ($file_count === 0) {
            $zip->close();
            @unlink($zip_file);
            return new WP_Error(
                'no_files_added',
                __('No files could be added to the ZIP archive.', 'wpswitchboard')
            );
        }

        $zip->close();
        return true;
    }

    /**
     * Create ZIP using PclZip
     */
    private function create_zip_pclzip($zip_file, $attachments) {
        if (!class_exists('PclZip')) {
            require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
        }

        $zip = new PclZip($zip_file);
        $files_to_add = [];

        foreach ($attachments as $attachment) {
            $file_path = get_attached_file($attachment->ID);

            if (!$file_path || !file_exists($file_path) || !is_readable($file_path)) {
                continue;
            }

            $files_to_add[] = $file_path;
        }

        if (empty($files_to_add)) {
            return new WP_Error(
                'no_files_added',
                __('No files could be added to the ZIP archive.', 'wpswitchboard')
            );
        }

        $result = $zip->create($files_to_add, PCLZIP_OPT_REMOVE_ALL_PATH);

        if ($result == 0) {
            return new WP_Error(
                'zip_create_failed',
                sprintf(__('Failed to create ZIP: %s', 'wpswitchboard'), $zip->errorInfo(true))
            );
        }

        return true;
    }

    /**
     * Clean up old ZIP files
     */
    private function cleanup_old_zips($zip_dir) {
        $files = @glob($zip_dir . '/media-library-*.zip');
        if (!$files) {
            return;
        }

        foreach ($files as $file) {
            if (file_exists($file) && (time() - filemtime($file)) > Switchboard_Zip_Handler::EXPIRY_TIME) {
                @unlink($file);
            }
        }
    }
}

// Initialize
$switchboard_instance = new SwitchboardDownloadMediaLibrary();
