<?php
/**
 * Inline Editor AJAX Handler
 *
 * @package PackshotPhotoAI
 */

namespace PackshotPhotoAI\Admin;

use PackshotPhotoAI\API\ApiRouter;

defined('ABSPATH') || exit;

/**
 * Handles AJAX requests for inline editing and AI generation
 */
class InlineEditor {

    /**
     * Save field via AJAX (supports single or batch saving)
     */
    public function save_field(): void {
        // Get post ID early for nonce verification
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        // Verify nonce for this specific attachment
        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        // Check capability
        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        // Support batch field updates
        if (isset($_POST['fields'])) {
            // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
            $fields_data = wp_unslash($_POST['fields']);
            if (is_string($fields_data)) {
                $fields_data = json_decode(sanitize_text_field($fields_data), true);
            }
            if (!is_array($fields_data)) {
                wp_send_json_error(['success' => false, 'message' => __('Invalid fields data', 'packshotphoto-ai')], 400);
            }

            $result = $this->update_multiple_fields($post_id, $fields_data);
            if ($result['success']) {
                wp_send_json_success($result);
            } else {
                wp_send_json_error($result);
            }
            return;
        }

        $field = isset($_POST['field']) ? sanitize_key(wp_unslash($_POST['field'])) : '';
        $value = isset($_POST['value']) ? wp_kses_post(wp_unslash($_POST['value'])) : '';
        $slug_only = isset($_POST['slug_only']) && sanitize_text_field(wp_unslash($_POST['slug_only'])) === '1';

        if (!in_array($field, ['alt', 'caption', 'description', 'filename'], true)) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid field', 'packshotphoto-ai')], 400);
        }

        $result = $this->update_field($post_id, $field, $value, $slug_only);

        if ($result['success']) {
            wp_send_json_success($result);
        } else {
            wp_send_json_error($result);
        }
    }

    /**
     * Update multiple attachment fields in a single transaction/operation
     *
     * @param int   $post_id Attachment ID
     * @param array $fields  Associative array of field => value
     * @return array
     */
    private function update_multiple_fields(int $post_id, array $fields): array {
        $post_data = ['ID' => $post_id];
        $update_post_needed = false;
        $messages = [];
        $errors = [];
        $data = [];

        // 1. Process alt text
        if (array_key_exists('alt', $fields)) {
            $alt_value = wp_kses_post($fields['alt']);
            update_post_meta($post_id, '_wp_attachment_image_alt', $alt_value);
            $messages[] = __('Saved (Alt)', 'packshotphoto-ai');
        }

        // 2. Process caption
        if (array_key_exists('caption', $fields)) {
            $post_data['post_excerpt'] = wp_kses_post($fields['caption']);
            $update_post_needed = true;
        }

        // 3. Process description
        if (array_key_exists('description', $fields)) {
            $post_data['post_content'] = wp_kses_post($fields['description']);
            $update_post_needed = true;
        }

        // 4. Update post if caption or description are present
        if ($update_post_needed) {
            $result = wp_update_post($post_data);
            if (is_wp_error($result)) {
                $errors[] = $result->get_error_message();
            } else {
                if (array_key_exists('caption', $fields)) {
                    $messages[] = __('Saved (Caption)', 'packshotphoto-ai');
                }
                if (array_key_exists('description', $fields)) {
                    $messages[] = __('Saved (Description)', 'packshotphoto-ai');
                }
            }
        }

        // 5. Process filename (rename file)
        if (array_key_exists('filename', $fields)) {
            $filename_value = sanitize_text_field($fields['filename']);
            $slug_only = !empty($fields['slug_only']);
            
            if ($slug_only) {
                $slug = sanitize_title($filename_value);
                $result = wp_update_post([
                    'ID' => $post_id,
                    'post_name' => $slug,
                    'post_title' => $filename_value
                ]);
                if (is_wp_error($result)) {
                    $errors[] = $result->get_error_message();
                } else {
                    $messages[] = __('Title and Slug updated', 'packshotphoto-ai');
                }
            } else {
                $renamer = new \PackshotPhotoAI\Core\FileRenamer();
                $result = $renamer->rename_file($post_id, $filename_value);
                if ($result['success']) {
                    $messages[] = $result['message'];
                    if (isset($result['data'])) {
                        $data['filename'] = $result['data'];
                    }
                } else {
                    $errors[] = $result['message'];
                }
            }
        }

        if (!empty($errors)) {
            return [
                'success' => false,
                'message' => implode('; ', $errors),
                'data' => $data
            ];
        }

        return [
            'success' => true,
            'message' => implode(', ', $messages),
            'data' => $data
        ];
    }

    /**
     * Generate AI descriptions via AJAX
     */
    public function generate_ai(): void {
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        // Verify nonce
        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        // Check capability
        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        // Get attachment info
        $file_path = get_attached_file($post_id);
        $mime_type = get_post_mime_type($post_id);

        if (!$file_path || !file_exists($file_path)) {
            wp_send_json_error(['success' => false, 'message' => __('File does not exist', 'packshotphoto-ai')]);
        }

        // Check credits
        if (!\PackshotPhotoAI\Core\CreditManager::has_credits()) {
            wp_send_json_error([
                'success' => false,
                'message' => __('Insufficient AI credits. Please purchase a package in settings.', 'packshotphoto-ai'),
                'action'  => 'buy_credits',
                'credit_error' => true,
            ]);
        }

        // Get target language from request
        $language = isset($_POST['language']) ? sanitize_text_field(wp_unslash($_POST['language'])) : '';

        // Get optional image context from user
        $image_context = isset($_POST['image_context']) ? sanitize_textarea_field(wp_unslash($_POST['image_context'])) : '';

        // Fallback to active upload session context if empty
        if (empty($image_context)) {
            $user_id      = get_current_user_id();
            $session_opts = get_transient('packshotphoto_upload_session_opts_' . $user_id);
            if (is_array($session_opts) && !empty($session_opts['context'])) {
                $image_context = $session_opts['context'];
            }
        }

        // Generate via router (auto-selects Gemini or custom OpenAI endpoint)
        $client = new ApiRouter();
        $result = $client->generate_seo_description($file_path, $mime_type, $post_id, $language, $image_context);

        if (!$result['success']) {
            wp_send_json_error($result);
        }

        // Save original metadata before overwriting (for potential revert)
        $this->backup_ai_metadata($post_id, $result['data'] ?? []);

        // Deduct 1 credit on successful generation
        \PackshotPhotoAI\Core\CreditManager::deduct_credit(1);

        // Save opener to recent memory (prevents repetitive description openings)
        $ai_data = $result['data'] ?? [];
        if (!empty($ai_data['desc'])) {
            $openers   = (array) get_option('packshotphoto_recent_openers', []);
            $openers[] = implode(' ', array_slice(explode(' ', $ai_data['desc']), 0, 8));
            update_option('packshotphoto_recent_openers', array_slice($openers, -30), false);
        }

        // FIX: Avoid double nesting — pass only the data portion, not the whole result
        wp_send_json_success($ai_data);
    }

    /**
     * Save original metadata before AI generation
     * Always backup current values before AI overwrites them
     */
    private function backup_ai_metadata(int $post_id, array $ai_data): void {
        $existing_post = get_post($post_id);
        $backup = [
            'alt' => get_post_meta($post_id, '_wp_attachment_image_alt', true) ?: '',
            'caption' => $existing_post ? ($existing_post->post_excerpt ?: '') : '',
            'description' => $existing_post ? ($existing_post->post_content ?: '') : '',
        ];

        // Add original filename to backup if exists
        $original_filename = get_post_meta($post_id, '_pmm_original_filename', true);
        if ($original_filename) {
            $backup['original_filename'] = $original_filename;
        }

        // Store backup with timestamp for reference (can be used for future multi-level revert)
        update_post_meta($post_id, '_pmm_ai_backup', $backup);
    }

    /**
     * Revert AI-generated metadata to original values
     * Supports selective field revert via POST params
     */
    public function revert_ai_metadata(): void {
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $fields = isset($_POST['fields']) ? wp_unslash($_POST['fields']) : [];
        if (is_string($fields)) {
            $fields = json_decode(sanitize_text_field($fields), true) ?: [];
        }
        if (!is_array($fields)) {
            $fields = [];
        }

        // Support version index for multi-version restore
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $version_index = isset($_POST['version_index']) ? (int)wp_unslash($_POST['version_index']) : -1; // -1 = latest
        
        $restore_file = !empty($_POST['restore_file']) && sanitize_text_field(wp_unslash($_POST['restore_file'])) === '1';
        $restored = [];
        $messages = [];

        if (!empty($fields['alt']) || !empty($fields['caption']) || !empty($fields['description'])) {
            $backup_history = get_post_meta($post_id, '_pmm_ai_backup', true);
            $backup = null;
            
            // Get specific version or latest
            if (is_array($backup_history)) {
                if (isset($backup_history[0]) && is_array($backup_history[0])) {
                    // New history format
                    if ($version_index >= 0 && isset($backup_history[$version_index])) {
                        $backup = $backup_history[$version_index];
                    } else {
                        $backup = end($backup_history); // Latest
                    }
                } else {
                    // Old single backup format
                    $backup = $backup_history;
                }
            }
            
            if ($backup && isset($backup['alt']) && !empty($fields['alt'])) {
                update_post_meta($post_id, '_wp_attachment_image_alt', $backup['alt']);
                $restored['alt'] = $backup['alt'];
                $messages[] = 'Alt';
            }

            if ($backup && isset($backup['caption']) && !empty($fields['caption'])) {
                $post = get_post($post_id);
                if ($post) {
                    $post->post_excerpt = $backup['caption'];
                    wp_update_post($post);
                    $restored['caption'] = $backup['caption'];
                    $messages[] = 'Caption';
                }
            }
        }

        if (!empty($fields['description'])) {
            if ($backup && isset($backup['description'])) {
                $post = get_post($post_id);
                if ($post) {
                    $post->post_content = $backup['description'];
                    wp_update_post($post);
                    $restored['description'] = $backup['description'];
                    $messages[] = 'Description';
                }
            }
        }

        if (!empty($fields['filename'])) {
            $original_filename = get_post_meta($post_id, '_pmm_original_filename', true);
            if ($original_filename) {
                $renamer = new \PackshotPhotoAI\Core\FileRenamer();
                $result = $renamer->revert_rename($post_id);
                if ($result['success']) {
                    $restored['filename'] = $result['data']['new_filename'] ?? $original_filename;
                    $messages[] = 'Filename';
                }
            }
        }

        if ($restore_file) {
            $file_result = $this->do_restore_original_file($post_id);
            if ($file_result['success']) {
                $restored['file_restored'] = true;
                $restored['new_url'] = $file_result['url'] ?? '';
                $messages[] = 'Original file';
            }
        }

        // Restore original size only (keep current format, resize to backup dimensions)
        $restore_size_only = !empty($_POST['restore_size_only']) && sanitize_text_field(wp_unslash($_POST['restore_size_only'])) === '1';
        if ($restore_size_only && !$restore_file) {
            $size_result = $this->do_restore_original_size($post_id);
            if ($size_result['success']) {
                $restored['size_restored'] = true;
                $restored['new_dimensions'] = $size_result['dimensions'] ?? '';
                $messages[] = __('Original size', 'packshotphoto-ai');
            } else {
                $messages[] = $size_result['message'] ?? __('Size restore failed', 'packshotphoto-ai');
            }
        }

        if (empty($messages) && empty($fields) && !$restore_file && !$restore_size_only) {
            wp_send_json_error(['success' => false, 'message' => __('No backup found to revert to.', 'packshotphoto-ai')]);
        }

        /* translators: %s: list of restored fields */
        $msg = !empty($messages) ? sprintf(__('Restored: %s', 'packshotphoto-ai'), implode(', ', $messages)) : __('No changes made', 'packshotphoto-ai');

        wp_send_json_success([
            'message'  => $msg,
            'restored' => $restored,
        ]);
    }

    /**
     * Restore original file from backup
     * Extracted for reuse from revert_ai_metadata
     */
    private function do_restore_original_file(int $post_id): array {
        $file_path = get_attached_file($post_id);
        if (!$file_path || !file_exists($file_path)) {
            return ['success' => false, 'message' => __('File missing', 'packshotphoto-ai')];
        }

        $upload_dir = wp_upload_dir();
        $backup_info = $this->get_backup_path_info($post_id, $file_path, $upload_dir);
        $backup_path = $backup_info['path'];
        $backup_extension = $backup_info['extension'];

        if (empty($backup_path) || !file_exists($backup_path) || empty($backup_extension)) {
            return ['success' => false, 'message' => __('Backup file not found', 'packshotphoto-ai')];
        }

        $current_path_info = pathinfo($file_path);
        $new_file_path = $current_path_info['dirname'] . '/' . $current_path_info['filename'] . '.' . $backup_extension;

        if ($backup_path === $new_file_path) {
            $url = wp_get_attachment_url($post_id);
            return ['success' => true, 'message' => __('File already restored!', 'packshotphoto-ai'), 'url' => $url];
        }

        // Use WP_Filesystem to comply with WordPress.org guidelines instead of direct rename/unlink
        global $wp_filesystem;
        if (empty($wp_filesystem)) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }

        // CRITICAL: Rename first, then delete old file - prevents data loss if rename fails
        // Save backup to new location FIRST (don't delete source until successful)
        $temp_restore_path = $current_path_info['dirname'] . '/' . $current_path_info['filename'] . '.restoring.' . $backup_extension;
        
        if (!$wp_filesystem->move($backup_path, $temp_restore_path, true)) {
            return ['success' => false, 'message' => __('Cannot prepare backup for restore', 'packshotphoto-ai')];
        }
        
        // Now safe to delete old current file using wp_delete_file
        if (file_exists($file_path) && !wp_delete_file($file_path)) {
            // Rollback: restore temp file back to backup location
            $wp_filesystem->move($temp_restore_path, $backup_path, true);
            return ['success' => false, 'message' => __('Cannot delete current file', 'packshotphoto-ai')];
        }
        
        // Move restored file to final destination
        if (!$wp_filesystem->move($temp_restore_path, $new_file_path, true)) {
            // Rollback: try to restore original from temp
            $wp_filesystem->move($temp_restore_path, $new_file_path, true);
            // If rollback fails too, we're in a bad state
            return ['success' => false, 'message' => __('Cannot complete restore', 'packshotphoto-ai')];
        }

        $original_mime_type = 'image/' . $backup_extension;
        if ($backup_extension === 'jpg') {
            $original_mime_type = 'image/jpeg';
        }

        wp_update_post(['ID' => $post_id, 'post_mime_type' => $original_mime_type]);
        update_attached_file($post_id, $new_file_path);

        $relative_path = _wp_relative_upload_path($new_file_path);
        $new_guid = $upload_dir['baseurl'] . '/' . $relative_path;
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $wpdb->update($wpdb->posts, ['guid' => $new_guid], ['ID' => $post_id]);
        clean_post_cache($post_id);

        $thumb_dir = dirname($new_file_path) . '/';
        $file_base = basename($new_file_path, '.' . $backup_extension);
        if (is_dir($thumb_dir)) {
            $thumbs = glob($thumb_dir . $file_base . '-*x*.*');
                foreach ($thumbs as $thumb) {
                    wp_delete_file($thumb);
                }
        }

        $metadata = wp_generate_attachment_metadata($post_id, $new_file_path);
        wp_update_attachment_metadata($post_id, $metadata);
        wp_cache_flush();
        delete_post_meta($post_id, '_pmm_original_backup');
        delete_post_meta($post_id, '_pmm_has_file_backup'); // Clear cache flag

        // If restoring from WebP to original format, clean up original filename meta too
        $original_filename = get_post_meta($post_id, '_pmm_original_filename', true);
        if ($original_filename && strtolower($backup_extension) !== 'webp') {
            delete_post_meta($post_id, '_pmm_original_filename');
        }

        $url = $upload_dir['baseurl'] . '/' . $relative_path . '?t=' . time();
        return ['success' => true, 'message' => __('Original file restored!', 'packshotphoto-ai'), 'url' => $url, 'new_filename' => basename($new_file_path)];
    }

    /**
     * Restore original dimensions without changing the current format.
     * Reads the backup file's pixel dimensions and resizes the current file to match.
     */
    private function do_restore_original_size(int $post_id): array {
        $file_path = get_attached_file($post_id);
        if (!$file_path || !file_exists($file_path)) {
            return ['success' => false, 'message' => __('File missing', 'packshotphoto-ai')];
        }

        $upload_dir = wp_upload_dir();
        $backup_info = $this->get_backup_path_info($post_id, $file_path, $upload_dir);
        $backup_path = $backup_info['path'];

        if (empty($backup_path) || !file_exists($backup_path)) {
            return ['success' => false, 'message' => __('Backup file not found', 'packshotphoto-ai')];
        }

        $backup_dims = @getimagesize($backup_path);
        if (!$backup_dims) {
            return ['success' => false, 'message' => __('Cannot read backup dimensions', 'packshotphoto-ai')];
        }

        $target_w = $backup_dims[0];
        $target_h = $backup_dims[1];

        $current_dims = @getimagesize($file_path);
        if ($current_dims && $current_dims[0] === $target_w && $current_dims[1] === $target_h) {
            return ['success' => true, 'message' => __('Dimensions already match', 'packshotphoto-ai'), 'dimensions' => $target_w . 'x' . $target_h];
        }

        // Use WordPress image editor to resize in place (preserves current format)
        $editor = wp_get_image_editor($file_path);
        if (is_wp_error($editor)) {
            return ['success' => false, 'message' => $editor->get_error_message()];
        }

        $result = $editor->resize($target_w, $target_h, false);
        if (is_wp_error($result)) {
            return ['success' => false, 'message' => $result->get_error_message()];
        }

        $save = $editor->save($file_path);
        if (is_wp_error($save)) {
            return ['success' => false, 'message' => $save->get_error_message()];
        }

        // Regenerate thumbnails
        $metadata = wp_generate_attachment_metadata($post_id, $file_path);
        if (!empty($metadata) && !is_wp_error($metadata)) {
            wp_update_attachment_metadata($post_id, $metadata);
        }

        \PackshotPhotoAI\Core\Logger::info('InlineEditor: Restored original size for #' . $post_id, [
            'target' => $target_w . 'x' . $target_h,
        ]);

        return [
            'success' => true,
            /* translators: %1$d: width, %2$d: height */
            'message' => sprintf(__('Restored to %1$dx%2$d', 'packshotphoto-ai'), $target_w, $target_h),
            'dimensions' => $target_w . 'x' . $target_h,
        ];
    }

    /**
     * Get data for image comparison via AJAX
     */
    public function get_comparison_data(): void {
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        // Verify nonce
        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        // Check capability
        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        $file_path = get_attached_file($post_id);
        if (!$file_path || !file_exists($file_path)) {
            wp_send_json_error(['success' => false, 'message' => __('File missing', 'packshotphoto-ai')]);
        }

        $path_info = pathinfo($file_path);
        
        // Check for backup - first try new format (packshotphoto-trash folder with meta)
        $backup_path = '';
        $upload_dir = wp_upload_dir();
        
        $backup_meta = get_post_meta($post_id, '_pmm_original_backup', true);
        if ($backup_meta) {
            $backup_path = $upload_dir['basedir'] . '/' . $backup_meta;
        }
        
        // Fallback checks
        if (!file_exists($backup_path)) {
            $possible_exts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
            foreach ($possible_exts as $ext) {
                // Try -original.ext
                $old_style = $path_info['dirname'] . '/' . $path_info['filename'] . '-original.' . $ext;
                if (file_exists($old_style)) {
                    $backup_path = $old_style;
                    break;
                }
                
                // Try looking in packshotphoto-trash with timestamp patterns if meta was lost
                $trash_dir = $upload_dir['basedir'] . '/packshotphoto-trash';
                if (is_dir($trash_dir)) {
                    $pattern = $trash_dir . '/' . $path_info['filename'] . '-original-*.' . $ext;
                    $matches = glob($pattern);
                    if ($matches) {
                        // Get most recent one
                        usort($matches, function($a, $b) { return filemtime($b) - filemtime($a); });
                        $backup_path = $matches[0];
                        break;
                    }
                }
            }
        }

        if (!file_exists($backup_path)) {
            wp_send_json_error(['success' => false, 'message' => __('Original backup missing', 'packshotphoto-ai')]);
        }

        $base_url = $upload_dir['baseurl'];
        $relative_current = _wp_relative_upload_path($file_path);
        $relative_backup = _wp_relative_upload_path($backup_path);

        $before_size = filesize($backup_path);
        $after_size = filesize($file_path);
        $savings = $before_size > 0 ? round((($before_size - $after_size) / $before_size) * 100, 1) : 0;

        wp_send_json_success([
            'before' => [
                'url'  => $base_url . '/' . $relative_backup,
                'size' => size_format($before_size),
                'bytes' => $before_size
            ],
            'after' => [
                'url'  => $base_url . '/' . $relative_current,
                'size' => size_format($after_size),
                'bytes' => $after_size,
                'savings' => $savings
            ]
        ]);
    }

    /**
     * Restore original file from backup via AJAX
     */
    public function restore_original(): void {
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        $file_path = get_attached_file($post_id);
        if (!$file_path || !file_exists($file_path)) {
            wp_send_json_error(['success' => false, 'message' => __('File missing', 'packshotphoto-ai')]);
        }

        $backup_path = '';
        $upload_dir = wp_upload_dir();
        $backup_extension = '';
        $backup_meta = get_post_meta($post_id, '_pmm_original_backup', true);
        
        if ($backup_meta) {
            $backup_path = $upload_dir['basedir'] . '/' . $backup_meta;
            if (file_exists($backup_path)) {
                $path_info = pathinfo($backup_path);
                $backup_extension = $path_info['extension'];
            }
        }
        
        if (!file_exists($backup_path)) {
            $path_info = pathinfo($file_path);
            $backup_path = $path_info['dirname'] . '/' . $path_info['filename'] . '-original.' . $path_info['extension'];
            if (file_exists($backup_path)) {
                $path_info2 = pathinfo($backup_path);
                $backup_extension = $path_info2['extension'];
            }
        }

        if (!file_exists($backup_path) || empty($backup_extension)) {
            $debug_info = [
                'backup_meta' => $backup_meta,
                'backup_path_checked' => $backup_path,
                'file_exists' => file_exists($backup_path),
                'backup_extension' => $backup_extension,
            ];
            wp_send_json_error([
                'success' => false, 
                'message' => __('Backup file not found', 'packshotphoto-ai'),
                'debug' => $debug_info
            ]);
            return;
        }

        $current_path_info = pathinfo($file_path);
        $new_file_path = $current_path_info['dirname'] . '/' . $current_path_info['filename'] . '.' . $backup_extension;
        
        if ($backup_path === $new_file_path) {
            wp_send_json_success([
                'message' => __('File already restored!', 'packshotphoto-ai'),
                'url' => wp_get_attachment_url($post_id)
            ]);
            return;
        }
        
        // Use WP_Filesystem to comply with WordPress.org guidelines instead of direct rename/unlink
        global $wp_filesystem;
        if (empty($wp_filesystem)) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }

        // CRITICAL: Rename first, then delete old file - prevents data loss if rename fails
        $temp_restore_path = $current_path_info['dirname'] . '/' . $current_path_info['filename'] . '.restoring.' . $backup_extension;
        
        if (!$wp_filesystem->move($backup_path, $temp_restore_path, true)) {
            wp_send_json_error(['success' => false, 'message' => __('Cannot prepare backup for restore', 'packshotphoto-ai')]);
            return;
        }
        
        // Now safe to delete old current file using wp_delete_file
        if (file_exists($file_path) && !wp_delete_file($file_path)) {
            $wp_filesystem->move($temp_restore_path, $backup_path, true);
            wp_send_json_error(['success' => false, 'message' => __('Cannot delete current file', 'packshotphoto-ai')]);
            return;
        }
        
        // Move restored file to final destination
        if (!$wp_filesystem->move($temp_restore_path, $new_file_path, true)) {
            $wp_filesystem->move($temp_restore_path, $new_file_path, true);
            wp_send_json_error(['success' => false, 'message' => __('Cannot complete restore', 'packshotphoto-ai')]);
            return;
        }

        $original_mime_type = 'image/' . $backup_extension;
        if ($backup_extension === 'jpg') {
            $original_mime_type = 'image/jpeg';
        }
        
        wp_update_post([
            'ID' => $post_id,
            'post_mime_type' => $original_mime_type,
        ]);
        
        update_attached_file($post_id, $new_file_path);
        
        $relative_path = _wp_relative_upload_path($new_file_path);
        $new_guid = $upload_dir['baseurl'] . '/' . $relative_path;
        
        global $wpdb;
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $wpdb->update(
            $wpdb->posts,
            ['guid' => $new_guid],
            ['ID' => $post_id]
        );
        
        clean_post_cache($post_id);
        
        // Delete existing thumbnails to force regeneration
        $upload_dir = wp_upload_dir();
        $thumb_path = $upload_dir['basedir'] . '/' . _wp_relative_upload_path($new_file_path);
        $thumb_dir = dirname($thumb_path) . '/';
        $file_base = basename($new_file_path, '.' . $backup_extension);
        
        // Remove old thumbnails using wp_delete_file
        if (is_dir($thumb_dir)) {
            $files = glob($thumb_dir . $file_base . '-*x*.jpg');
            if ($files) {
                foreach ($files as $thumb) {
                    wp_delete_file($thumb);
                }
            }
        }
        
        $metadata = wp_generate_attachment_metadata($post_id, $new_file_path);
        wp_update_attachment_metadata($post_id, $metadata);

        // Force refresh by deleting object cache
        wp_cache_flush();

        delete_post_meta($post_id, '_pmm_original_backup');
        delete_post_meta($post_id, '_pmm_has_file_backup'); // Clear cache flag

        wp_send_json_success([
            'message' => __('Original file restored!', 'packshotphoto-ai'),
            'url' => $new_guid . '?t=' . time()
        ]);
    }

    /**
     * Update attachment field
     *
     * @param int    $post_id Attachment ID
     * @param string $field   Field name
     * @param string $value   New value
     * @return array {
     *     @type bool   $success True if the update was successful, false otherwise.
     *     @type string $message A message describing the result of the operation.
     *     @type array  $data    Optional data returned by some fields.
     * }
     */
    private function update_field(int $post_id, string $field, string $value, bool $slug_only = false): array {
        switch ($field) {
            case 'alt':
                update_post_meta($post_id, '_wp_attachment_image_alt', $value);
                return [
                    'success' => true,
                    'message' => __('Saved (Alt)', 'packshotphoto-ai'),
                ]; 

            case 'caption':
                $result = wp_update_post([
                    'ID'           => $post_id,
                    'post_excerpt' => $value,
                ]);
                if (is_wp_error($result)) {
                    return [
                        'success' => false,
                        'message' => $result->get_error_message(),
                    ];
                }
                return [
                    'success' => true,
                    'message' => __('Saved (Caption)', 'packshotphoto-ai'),
                ];

            case 'description':
                $result = wp_update_post([
                    'ID'           => $post_id,
                    'post_content' => $value,
                ]);
                if (is_wp_error($result)) {
                    return [
                        'success' => false,
                        'message' => $result->get_error_message(),
                    ];
                }
                return [
                    'success' => true,
                    'message' => __('Saved (Description)', 'packshotphoto-ai'),
                ];

            case 'filename':
                if ($slug_only) {
                    $slug = sanitize_title($value);
                    $result = wp_update_post([
                        'ID' => $post_id,
                        'post_name' => $slug,
                        'post_title' => $value
                    ]);
                    if (is_wp_error($result)) {
                        return [
                            'success' => false,
                            'message' => $result->get_error_message(),
                        ];
                    }
                    return [
                        'success' => true,
                        'message' => __('Title and Slug updated', 'packshotphoto-ai'),
                    ];
                }

                $renamer = new \PackshotPhotoAI\Core\FileRenamer();
                $result = $renamer->rename_file($post_id, $value);
                return $result; // Already standardized

            default:
                return [
                    'success' => false,
                    'message' => __('Unknown field', 'packshotphoto-ai'),
                ];
        }
    }

    /**
     * AJAX: Get restore options for an attachment
     * Returns backup data, comparison URLs, and available restore actions
     */
    public function get_restore_options(): void {
        $post_id = isset($_POST['id']) ? absint($_POST['id']) : 0;

        if (!$post_id) {
            wp_send_json_error(['success' => false, 'message' => __('Invalid ID', 'packshotphoto-ai')], 400);
        }

        $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'packshotphoto_edit_' . $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Security error', 'packshotphoto-ai')], 403);
        }

        if (!current_user_can('edit_post', $post_id)) {
            wp_send_json_error(['success' => false, 'message' => __('Permission denied', 'packshotphoto-ai')], 403);
        }

        $result = [
            'has_ai_backup' => false,
            'has_file_backup' => false,
            'has_original_filename' => false,
            'backup_values' => [],
            'current_values' => [],
            'comparison' => null,
        ];

        $ai_backup = get_post_meta($post_id, '_pmm_ai_backup', true);
        if ($ai_backup && is_array($ai_backup)) {
            // Check if it's the new history format (array of arrays) or old single backup
            if (isset($ai_backup[0]) && is_array($ai_backup[0])) {
                // New history format - array of versions
                $result['has_ai_backup'] = true;
                $result['backup_versions'] = [];
                foreach ($ai_backup as $idx => $version) {
                    $ts = $version['timestamp'] ?? 0;
                    $result['backup_versions'][] = [
                        'index' => $idx,
                        'alt' => $version['alt'] ?? '',
                        'caption' => $version['caption'] ?? '',
                        'description' => $version['description'] ?? '',
                        'timestamp' => $ts,
                        'date' => $ts ? gmdate('Y-m-d H:i', $ts) : 'Unknown',
                    ];
                }
                // Latest version as current backup
                $latest = end($ai_backup);
                $result['backup_values']['alt'] = $latest['alt'] ?? '';
                $result['backup_values']['caption'] = $latest['caption'] ?? '';
                $result['backup_values']['description'] = $latest['description'] ?? '';
            } else {
                // Old single backup format - convert to new
                $result['has_ai_backup'] = true;
                $result['backup_values']['alt'] = $ai_backup['alt'] ?? '';
                $result['backup_values']['caption'] = $ai_backup['caption'] ?? '';
                $result['backup_values']['description'] = $ai_backup['description'] ?? '';
            }
        }

        $result['current_values']['alt'] = get_post_meta($post_id, '_wp_attachment_image_alt', true) ?: '';
        $post = get_post($post_id);
        $result['current_values']['caption'] = $post ? ($post->post_excerpt ?: '') : '';
        $result['current_values']['description'] = $post ? ($post->post_content ?: '') : '';

        $file_path = get_attached_file($post_id);
        $upload_dir = wp_upload_dir();

        $original_filename = get_post_meta($post_id, '_pmm_original_filename', true);
        if ($original_filename) {
            $result['has_original_filename'] = true;
            $result['backup_values']['filename'] = $original_filename;
            $result['current_values']['filename'] = basename($file_path);
        } elseif ($file_path && file_exists($file_path) && strtolower(pathinfo($file_path, PATHINFO_EXTENSION)) === 'webp') {
            $backup_meta_fn = get_post_meta($post_id, '_pmm_original_backup', true);
            if ($backup_meta_fn) {
                $result['has_original_filename'] = true;
                // Extract filename but remove the '-original-TIMESTAMP' part if it exists
                $raw_btn_filename = basename($backup_meta_fn);
                $clean_filename = preg_replace('/-original-\d+\./', '.', $raw_btn_filename);
                $result['backup_values']['filename'] = $clean_filename;
                $result['current_values']['filename'] = basename($file_path);
            }
        }

        if ($file_path && file_exists($file_path)) {
            $backup_info = $this->get_backup_path_info($post_id, $file_path, $upload_dir);
            $backup_path = $backup_info['path'];
            $backup_extension = $backup_info['extension'];

            if (file_exists($backup_path) && !empty($backup_extension)) {
                $result['has_file_backup'] = true;

                $relative_current = _wp_relative_upload_path($file_path);
                $relative_backup = _wp_relative_upload_path($backup_path);
                $before_size = filesize($backup_path);
                $after_size = filesize($file_path);
                $savings = $before_size > 0 ? round((($before_size - $after_size) / $before_size) * 100, 1) : 0;

                $backup_dims = @getimagesize($backup_path);
                $current_dims = @getimagesize($file_path);
                $backup_w = $backup_dims ? $backup_dims[0] : 0;
                $backup_h = $backup_dims ? $backup_dims[1] : 0;
                $current_w = $current_dims ? $current_dims[0] : 0;
                $current_h = $current_dims ? $current_dims[1] : 0;

                $current_ext = strtoupper(pathinfo($file_path, PATHINFO_EXTENSION));
                $backup_ext = strtoupper($backup_extension);
                $format_changed = $current_ext !== $backup_ext;
                $size_changed = ($backup_w > 0 && $current_w > 0) && ($backup_w !== $current_w || $backup_h !== $current_h);

                // Show "restore size only" when dimensions differ
                $result['has_size_restore'] = $size_changed;

                $result['comparison'] = [
                    'before_url' => $upload_dir['baseurl'] . '/' . $relative_backup,
                    'after_url' => $upload_dir['baseurl'] . '/' . $relative_current,
                    'before_size' => size_format($before_size),
                    'after_size' => size_format($after_size),
                    'before_bytes' => $before_size,
                    'after_bytes' => $after_size,
                    'before_format' => $backup_ext,
                    'after_format' => $current_ext,
                    'savings' => $savings,
                    'backup_width' => $backup_w,
                    'backup_height' => $backup_h,
                    'current_width' => $current_w,
                    'current_height' => $current_h,
                    'format_changed' => $format_changed,
                ];
            }
        }

        wp_send_json_success($result);
    }

    /**
     * Helper to find backup file path and extension for a given attachment
     */
    private function get_backup_path_info(int $post_id, string $file_path, array $upload_dir): array {
        $backup_path = '';
        $backup_extension = '';
        $backup_meta = get_post_meta($post_id, '_pmm_original_backup', true);

        if ($backup_meta) {
            $backup_path = $upload_dir['basedir'] . '/' . $backup_meta;
            if (file_exists($backup_path)) {
                $path_info = pathinfo($backup_path);
                $backup_extension = $path_info['extension'];
            }
        }

        // Fallback 1: old-style backup in same directory
        if (!file_exists($backup_path)) {
            $path_info = pathinfo($file_path);
            $possible_exts = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
            foreach ($possible_exts as $ext) {
                $old_backup = $path_info['dirname'] . '/' . $path_info['filename'] . '-original.' . $ext;
                if (file_exists($old_backup)) {
                    $backup_path = $old_backup;
                    $backup_extension = $ext;
                    break;
                }
            }
        }

        // Fallback 2: search packshotphoto-trash by original filename from meta
        if (!file_exists($backup_path) && empty($backup_extension)) {
            $original_filename_meta = get_post_meta($post_id, '_pmm_original_filename', true);
            if ($original_filename_meta) {
                $original_name_without_ext = pathinfo($original_filename_meta, PATHINFO_FILENAME);
                $trash_dir = $upload_dir['basedir'] . '/packshotphoto-trash';
                if (is_dir($trash_dir)) {
                    $trash_files = @scandir($trash_dir);
                    if ($trash_files && is_array($trash_files)) {
                        foreach ($trash_files as $candidate) {
                            if ($candidate === '.' || $candidate === '..') continue;
                            $candidate_name = pathinfo($candidate, PATHINFO_FILENAME);
                            $candidate_base = preg_replace('/-original-\d+$/', '', $candidate_name);
                            if ($candidate_base === $original_name_without_ext) {
                                $backup_path = $trash_dir . '/' . $candidate;
                                $backup_extension = pathinfo($candidate, PATHINFO_EXTENSION);
                                break;
                            }
                        }
                    }
                }
            }
        }

        // Fallback 3: search by current filename
        if (!file_exists($backup_path) && empty($backup_extension)) {
            $current_filename = pathinfo($file_path, PATHINFO_FILENAME);
            $trash_dir = $upload_dir['basedir'] . '/packshotphoto-trash';
            if (is_dir($trash_dir)) {
                $trash_files = @scandir($trash_dir);
                if ($trash_files && is_array($trash_files)) {
                    foreach ($trash_files as $candidate) {
                        if ($candidate === '.' || $candidate === '..') continue;
                        $candidate_name = pathinfo($candidate, PATHINFO_FILENAME);
                        if (strpos($candidate_name, $current_filename) === 0) {
                            $backup_path = $trash_dir . '/' . $candidate;
                            $backup_extension = pathinfo($candidate, PATHINFO_EXTENSION);
                            break;
                        }
                    }
                }
            }
        }

        return [
            'path' => $backup_path,
            'extension' => $backup_extension
        ];
    }
}
