<?php
/**
 * Safe File Renamer
 *
 * @package PackshotPhotoAI
 */

namespace PackshotPhotoAI\Core;

defined('ABSPATH') || exit;

/**
 * Handles safe file renaming for attachments
 */
class FileRenamer {

    /**
     * Rename an attachment file and its thumbnails
     *
     * @param int    $post_id      Attachment ID
     * @param string $new_filename New filename (with or without extension)
     * @return array ['success' => bool, 'message' => string]
     */
    public function rename_file(int $post_id, string $new_filename): array {
        $file_path = get_attached_file($post_id);

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

        $dir = dirname($file_path);
        $old_filename = basename($file_path);
        $ext = pathinfo($file_path, PATHINFO_EXTENSION);
        
        // Sanitize new filename
        $new_filename = \sanitize_file_name($new_filename);
        
        // Ensure extension matches/exists
        $new_ext = pathinfo($new_filename, PATHINFO_EXTENSION);
        if ($new_ext !== $ext) {
            // If user didn't provide extension or provided wrong one, force original extension
            $new_filename = pathinfo($new_filename, PATHINFO_FILENAME) . '.' . $ext;
        }

        if ($old_filename === $new_filename) {
            return [
                'success' => true,
                'message' => __('Filename unchanged.', 'packshotphoto-ai'),
                'data'    => [
                    'filename' => $new_filename,
                    'file'     => $file_path,
                ],
            ];
        }

        $new_file_path = \trailingslashit($dir) . $new_filename;

        // Check collision
        if (file_exists($new_file_path)) {
            Logger::warning('Rename collision', ['id' => $post_id, 'old' => $old_filename, 'target' => $new_filename]);
            return ['success' => false, 'message' => __('A file with this name already exists.', 'packshotphoto-ai')];
        }

        // Save original filename if not already set (record the first name ever)
        if (!\get_post_meta($post_id, '_pmm_original_filename', true)) {
            \update_post_meta($post_id, '_pmm_original_filename', $old_filename);
        }

        // 1. Rename Main File
        global $wp_filesystem;
        if (empty($wp_filesystem)) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }

        if (!$wp_filesystem->move($file_path, $new_file_path, true)) {
            Logger::error('Failed to rename attachment', ['id' => $post_id, 'source' => $file_path, 'target' => $new_file_path]);
            return ['success' => false, 'message' => __('Failed to rename file (permission error?).', 'packshotphoto-ai')];
        }

        // 2. Update _wp_attached_file (Path relative to uploads dir)
        $uploads       = \wp_upload_dir();
        $relative_path = \_wp_relative_upload_path($new_file_path);
        \update_post_meta($post_id, '_wp_attached_file', $relative_path);

        // 3. Update Attachment Metadata (thumbnails and main file entry)
        $meta = \wp_get_attachment_metadata($post_id);
        if ($meta) {
            // Update the main file path in metadata array
            $meta['file'] = $relative_path;

            if (!empty($meta['sizes'])) {
                $base_old = pathinfo($old_filename, PATHINFO_FILENAME);
                $base_new = pathinfo($new_filename, PATHINFO_FILENAME);

                foreach ($meta['sizes'] as $size => $data) {
                    $thumb_old_name = $data['file'];
                    $thumb_old_path = \trailingslashit($dir) . $thumb_old_name;

                    if (file_exists($thumb_old_path)) {
                        // Use preg_quote to safely replace only the base filename part at the start
                        $pattern        = '/^' . preg_quote($base_old, '/') . '/';
                        $thumb_new_name = preg_replace($pattern, $base_new, $thumb_old_name);
                        $thumb_new_path = \trailingslashit($dir) . $thumb_new_name;

                        // Only rename if new name is actually different and target doesn't exist
                        if ($thumb_new_name !== $thumb_old_name && !file_exists($thumb_new_path)) {
                            $wp_filesystem->move($thumb_old_path, $thumb_new_path, true);
                            $meta['sizes'][$size]['file'] = $thumb_new_name;
                        }
                    }
                }
            }
            \wp_update_attachment_metadata($post_id, $meta);
        }

        // 4. Update GUID (Optional but keeps clean)
        $new_guid = $uploads['baseurl'] . '/' . $relative_path;
        
        // Sync Post Name (Slug) with new Filename
        $path_parts = pathinfo($new_filename);
        $new_slug   = \sanitize_title($path_parts['filename']);

        // Check settings (Default to ON if not set)
        $settings  = get_option('packshotphoto_settings', []);
        $sync_slug = isset($settings['sync_slug']) ? (bool)$settings['sync_slug'] : true;

        global $wpdb;
        $update_data = ['guid' => $new_guid];
        
        if ($sync_slug) {
            $update_data['post_name'] = $new_slug;
            // Also update post title to match the new file name (without extension, spaces instead of hyphens)
            $update_data['post_title'] = ucfirst(str_replace(['-', '_'], ' ', $path_parts['filename']));
        }

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $wpdb->update($wpdb->posts, $update_data, ['ID' => $post_id]);
        
        if ($sync_slug) {
            \clean_post_cache($post_id); // Ensure cache is cleared for UI updates
        }

        // 5. Search and Replace in Content
        $old_url = $uploads['baseurl'] . '/' . \_wp_relative_upload_path($file_path);
        $new_url = $new_guid;
        
        $this->update_database_references($old_url, $new_url);

        return [
            'success' => true, 
            'message' => __('Filename changed successfully.', 'packshotphoto-ai'),
            'data'    => [
                'old_filename' => $old_filename,
                'new_filename' => $new_filename,
                'url'          => $new_url,
                'relative'     => $relative_path,
            ],
        ];
    }

    /**
     * Revert filename to the first recorded original name
     *
     * @param int $post_id Attachment ID
     * @return array Result
     */
    public function revert_rename(int $post_id): array {
        $original = \get_post_meta($post_id, '_pmm_original_filename', true);
        if (!$original) {
            return [
                'success' => false,
                'message' => __('No backup name found to revert to.', 'packshotphoto-ai')
            ];
        }

        // Perform standard rename to the original name
        // We temporarily block meta deletion to avoid loop issues
        $result = $this->rename_file($post_id, $original);

        if ($result['success']) {
            // Remove the backup marker once we've reverted successfully
            \delete_post_meta($post_id, '_pmm_original_filename');
            $result['message'] = __('Restored original filename.', 'packshotphoto-ai');
        }

        return $result;
    }

    /**
     * Search and replace media URL in post content
     */
    private function update_database_references(string $old_url, string $new_url): void {
        global $wpdb;

        // 1. Post Content (HTML) - Generally Safe for SQL REPLACE
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $wpdb->query(
            $wpdb->prepare(
                "UPDATE $wpdb->posts SET post_content = REPLACE(post_content, %s, %s)",
                $old_url,
                $new_url
            )
        );
    }
}
