<?php
/**
 * Image Boost — Backup System
 * Handles backing up and restoring original images.
 */

if (!defined('ABSPATH')) {
    exit;
}

class ImgBoost_Backup {

    /**
     * Create a backup of the original image before optimization.
     *
     * @param string $file_path Absolute path to the original image.
     * @param int    $attachment_id
     * @return string|WP_Error Backup path on success.
     */
    public static function create($file_path, $attachment_id) {
        if (!get_option('imgboost_backup_enabled', 1)) {
            return new WP_Error('backup_disabled', __('Backups are disabled.', 'image-boost'));
        }

        if (!file_exists($file_path)) {
            return new WP_Error('file_missing', __('Original file not found.', 'image-boost'));
        }

        $upload_dir = wp_get_upload_dir();
        
        // Normalize both paths so str_replace actually works on Windows
        $norm_basedir = wp_normalize_path($upload_dir['basedir']);
        $norm_filepath = wp_normalize_path($file_path);
        
        // Case-insensitive replace for Windows compatibility
        $relative_path = preg_replace('/^' . preg_quote($norm_basedir, '/') . '/i', '', $norm_filepath);
        // Clean out query strings if passed by mistake
        $relative_path = preg_replace('/\?.*/', '', $relative_path);
        
        $backup_path = wp_normalize_path(IMGBOOST_BACKUP_DIR . ltrim($relative_path, '/\\'));
        $backup_dir = dirname($backup_path);

        if (!file_exists($backup_dir)) {
            if (!wp_mkdir_p($backup_dir)) {
                return new WP_Error('mkdir_failed', __('Failed to create backup directory. Check permissions.', 'image-boost'));
            }
        }

        if (file_exists($backup_path)) {
            return $backup_path; // Already backed up
        }

        require_once ABSPATH . 'wp-admin/includes/file.php';
        WP_Filesystem();
        global $wp_filesystem;
        
        $copied = false;
        if ($wp_filesystem) {
            $copied = $wp_filesystem->copy($file_path, $backup_path, true, FS_CHMOD_FILE);
        } else {
            $copied = copy($file_path, $backup_path);
        }

        if (!$copied) {
            return new WP_Error('backup_failed', __('Failed to create backup copy.', 'image-boost'));
        }

        update_post_meta($attachment_id, '_imgboost_backup_path', $backup_path);
        update_post_meta($attachment_id, '_imgboost_has_backup', 1);

        return $backup_path;
    }

    /**
     * Restore original image from backup.
     *
     * @param int $attachment_id
     * @return bool|WP_Error
     */
    public static function restore($attachment_id) {
        $backup_path = get_post_meta($attachment_id, '_imgboost_backup_path', true);
        $file_path = imgboost_get_attachment_path($attachment_id);

        $backup_path = wp_normalize_path($backup_path);
        
        $real_backup_path = wp_normalize_path(realpath($backup_path));
        $real_safe_dir    = wp_normalize_path(realpath(IMGBOOST_BACKUP_DIR));

        // Strict Path Traversal Prevention
        if (!$real_backup_path || !$real_safe_dir || stripos($real_backup_path, $real_safe_dir) !== 0) {
            $backup_path = false; // Prevent Arbitrary File Read/Write
        }
        
        if (!$backup_path || !file_exists($backup_path)) {
            // Auto-heal corrupted paths from older versions (stripped backslashes bug)
            $upload_dir = wp_get_upload_dir();
            $norm_basedir = wp_normalize_path($upload_dir['basedir']);
            $norm_filepath = wp_normalize_path($file_path);
            $relative_path = preg_replace('/^' . preg_quote($norm_basedir, '/') . '/i', '', $norm_filepath);
            $healed_backup_path = wp_normalize_path(IMGBOOST_BACKUP_DIR . ltrim($relative_path, '/\\'));
            
            if (file_exists($healed_backup_path)) {
                $backup_path = $healed_backup_path;
                update_post_meta($attachment_id, '_imgboost_backup_path', $backup_path);
            } else {
                return new WP_Error('no_backup', 'No backup found. Path: ' . esc_html($backup_path));
            }
        }

        if (!$file_path) {
            return new WP_Error('no_file', __('Original attachment file not found.', 'image-boost'));
        }

        require_once ABSPATH . 'wp-admin/includes/file.php';
        WP_Filesystem();
        global $wp_filesystem;

        $restored = false;
        if ($wp_filesystem) {
            $restored = $wp_filesystem->copy($backup_path, $file_path, true, FS_CHMOD_FILE);
        } else {
            $restored = copy($backup_path, $file_path);
        }

        if (!$restored) {
            return new WP_Error('restore_failed', 'Copy failed from: ' . esc_html($backup_path) . ' TO: ' . esc_html($file_path));
        }

        // Remove WebP and AVIF versions
        self::cleanup_converted_files($file_path);

        // Also restore thumbnails
        $metadata = wp_get_attachment_metadata($attachment_id);
        $dir = dirname($file_path);

        if (!empty($metadata['sizes'])) {
            foreach ($metadata['sizes'] as $size_data) {
                $size_path = $dir . '/' . $size_data['file'];
                $upload_dir = wp_get_upload_dir();
                
                $norm_basedir = wp_normalize_path($upload_dir['basedir']);
                $norm_sizepath = wp_normalize_path($size_path);
                
                $relative = preg_replace('/^' . preg_quote($norm_basedir, '/') . '/i', '', $norm_sizepath);
                $size_backup = wp_normalize_path(IMGBOOST_BACKUP_DIR . ltrim($relative, '/\\'));
                $size_path = $norm_sizepath;

                if (file_exists($size_backup)) {
                    if ($wp_filesystem) {
                        $wp_filesystem->copy($size_backup, $size_path, true, FS_CHMOD_FILE);
                    } else {
                        copy($size_backup, $size_path);
                    }
                }
                self::cleanup_converted_files($size_path);
            }
        }

        // Clear optimization meta
        delete_post_meta($attachment_id, '_imgboost_status');
        delete_post_meta($attachment_id, '_imgboost_level');
        delete_post_meta($attachment_id, '_imgboost_original_size');
        delete_post_meta($attachment_id, '_imgboost_optimized_size');
        delete_post_meta($attachment_id, '_imgboost_savings');
        delete_post_meta($attachment_id, '_imgboost_webp_path');
        delete_post_meta($attachment_id, '_imgboost_avif_path');

        ImgBoost_DB::delete_attachment_records($attachment_id);

        return true;
    }

    /**
     * Delete backup files for an attachment.
     *
     * @param int $attachment_id
     */
    public static function delete($attachment_id) {
        $backup_path = get_post_meta($attachment_id, '_imgboost_backup_path', true);
        require_once ABSPATH . 'wp-admin/includes/file.php';

        if ($backup_path && file_exists(wp_normalize_path($backup_path))) {
            wp_delete_file(wp_normalize_path($backup_path));
        }

        $file_path = imgboost_get_attachment_path($attachment_id);
        if ($file_path) {
            $metadata = wp_get_attachment_metadata($attachment_id);
            $dir = dirname($file_path);

            if (!empty($metadata['sizes'])) {
                foreach ($metadata['sizes'] as $size_data) {
                    $size_path = $dir . '/' . $size_data['file'];
                    $upload_dir = wp_get_upload_dir();
                    $relative = str_replace($upload_dir['basedir'], '', $size_path);
                    $size_backup = IMGBOOST_BACKUP_DIR . ltrim($relative, '/\\');

                    if (file_exists(wp_normalize_path($size_backup))) {
                        wp_delete_file(wp_normalize_path($size_backup));
                    }
                }
            }
        }

        delete_post_meta($attachment_id, '_imgboost_backup_path');
        delete_post_meta($attachment_id, '_imgboost_has_backup', 0);
    }

    /**
     * Remove WebP and AVIF converted files.
     */
    private static function cleanup_converted_files($file_path) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        
        // Use case insensitive logic
        $extension = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
        if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif'])) {
            $webp_path = preg_replace('/\.' . preg_quote($extension, '/') . '$/i', '.webp', $file_path);
            $avif_path = preg_replace('/\.' . preg_quote($extension, '/') . '$/i', '.avif', $file_path);
            
            if ($webp_path && file_exists(wp_normalize_path($webp_path))) {
                wp_delete_file(wp_normalize_path($webp_path));
            }
            if ($avif_path && file_exists(wp_normalize_path($avif_path))) {
                wp_delete_file(wp_normalize_path($avif_path));
            }
        }
    }
    
    /**
     * CRON: Auto Delete Old Backups
     */
    public static function auto_delete_old_backups() {
        if (!get_option('imgboost_backup_enabled', 1)) {
            return;
        }
        
        $days = (int) get_option('imgboost_backup_days', 30);
        if ($days <= 0) {
            return;
        }
        
        global $wpdb;
        $threshold = time() - ($days * DAY_IN_SECONDS);
        
        // Find attachments with backups older than threshold
        // By checking when they were optimized
        $table = $wpdb->prefix . 'imgboost_log';
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $results = $wpdb->get_results($wpdb->prepare(
            "SELECT DISTINCT attachment_id FROM {$wpdb->prefix}imgboost_log WHERE optimized_at < %s AND backup_path IS NOT NULL",
            gmdate('Y-m-d H:i:s', $threshold)
        ));
        
        if ($results) {
            foreach ($results as $row) {
                self::delete($row->attachment_id);
            }
        }
    }
}

// ─── Hook: Clean up on attachment deletion ────────────────────
add_action('delete_attachment', function ($attachment_id) {
    ImgBoost_Backup::delete($attachment_id);

    $file_path = imgboost_get_attachment_path($attachment_id);
    if ($file_path) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        
        $clean_files = function($path) {
            $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
            if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif'])) {
                $webp = preg_replace('/\.' . preg_quote($ext, '/') . '$/i', '.webp', $path);
                $avif = preg_replace('/\.' . preg_quote($ext, '/') . '$/i', '.avif', $path);
                if ($webp && file_exists(wp_normalize_path($webp))) wp_delete_file(wp_normalize_path($webp));
                if ($avif && file_exists(wp_normalize_path($avif))) wp_delete_file(wp_normalize_path($avif));
            }
        };
        
        // Clean original
        $clean_files($file_path);
        
        // Clean thumbnails WebP and AVIF
        $metadata = wp_get_attachment_metadata($attachment_id);
        if (!empty($metadata['sizes'])) {
            $dir = dirname($file_path);
            foreach ($metadata['sizes'] as $size_data) {
                $clean_files($dir . '/' . $size_data['file']);
            }
        }
    }

    ImgBoost_DB::delete_attachment_records($attachment_id);
});
