<?php

/**
 * Image Optimization Settings REST API Controller
 *
 * @package ProRank\SEO\Core\RestApi
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\RestApi;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

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


/**
 * ImageOptimizationSettingsController class
 */


class ImageOptimizationSettingsController extends \WP_REST_Controller {

    /**
     * Constructor
     */
    public function __construct() {
        $this->namespace = 'prorank-seo/v1';
        $this->rest_base = 'settings/image_optimization';
    }

    /**
     * Register routes
     *
     * @return void
     */
    public function register_routes(): void {
        // Get settings
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base,
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_settings'],
                    'permission_callback' => [$this, 'get_items_permissions_check'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_settings'],
                    'permission_callback' => [$this, 'create_item_permissions_check'],
                ],
            ]
        );

        register_rest_route(
            $this->namespace,
            '/performance/image-optimization/settings',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_settings'],
                    'permission_callback' => [$this, 'get_items_permissions_check'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_settings'],
                    'permission_callback' => [$this, 'create_item_permissions_check'],
                ],
            ]
        );

        // Get statistics
        register_rest_route(
            'prorank-seo/v1',
            '/performance/image-optimization/stats',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_stats'],
                    'permission_callback' => [$this, 'get_items_permissions_check'],
                ],
            ]
        );

        // Start bulk optimization
        register_rest_route(
            'prorank-seo/v1',
            '/performance/image-optimization/bulk',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'start_bulk_optimization'],
                    'permission_callback' => [$this, 'create_item_permissions_check'],
                ],
            ]
        );
    }

    /**
     * Get image optimization settings
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function get_settings(WP_REST_Request $request) {
        $defaults = [
            'optimization_method' => 'local',
            'webp_enabled' => true,
            'webp_quality' => 85,
            'avif_enabled' => false,
            'avif_quality' => 80,
            'jxl_enabled' => false,
            'jxl_quality' => 80,
            'jpegli_enabled' => false,
            'png_quality' => 80,
            'png_pipeline' => false,
            'smart_compression' => true,
            'compression_type' => 'glossy',
            'optimize_on_upload' => false,
            'background_mode' => false,
            'backup_originals' => true,
            'optimize_original_source' => false,
            'lazyload_images' => false,
            'lazyload_iframes' => false,
            'lazyload_videos' => false,
            'lazyload_threshold' => 200,
            'cdn_enabled' => false,
            'cdn_url' => '',
            'exclude_paths' => '',
            'cloud_opt_in' => false,
            'cloud_opt_in_at' => null,
            // Advanced settings
            'png_to_jpeg' => true,
            'cmyk_to_rgb' => true,
            'remove_exif' => true,
            'optimize_pdf' => false,
            'generate_retina' => false,
            'no_ai_training' => false,
            'delivery_method' => 'picture',
            // Client Hints settings
            'client_hints_enabled' => false,
            'client_hints_dpr' => true,
            'client_hints_width' => true,
            'client_hints_viewport' => true,
            'client_hints_save_data' => false,
            // CDN settings
            'cdn_mode' => 'disabled',
            'cdn_custom_endpoint' => '',
            // SmartCrop & Resize settings
            'smart_crop_enabled' => false,
            'resize_large_enabled' => false,
            'resize_max_width' => 2560,
            'resize_max_height' => 2560,
            // Additional settings
            'jpeg_quality' => 85,
            'exclude_sizes' => [],
            'cdn_exclude_paths' => '',
        ];

        $settings = get_option('prorank_image_optimization_settings', $defaults);
        if (!is_array($settings)) {
            $settings = [];
        }
        $settings = wp_parse_args($settings, $defaults);
        $settings['optimization_method'] = 'local';
        $settings['cloud_opt_in'] = false;
        $settings['cloud_opt_in_at'] = null;

        return rest_ensure_response([
            'settings' => $settings,
        ]);
    }

    /**
     * Update image optimization settings
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function update_settings(WP_REST_Request $request) {
        $incoming_settings = $request->get_param('settings');

        if (empty($incoming_settings) || !is_array($incoming_settings)) {
            return new WP_Error(
                'invalid_settings',
                __('Invalid settings provided', 'prorank-seo'),
                ['status' => 400]
            );
        }

        // Merge with existing settings to avoid dropping keys when partial payloads are sent
        $existing_settings = get_option('prorank_image_optimization_settings', []);
        $settings = array_merge(is_array($existing_settings) ? $existing_settings : [], $incoming_settings);

        // Validate settings
        $validated_settings = $this->validate_settings($settings);

        // Save settings
        update_option('prorank_image_optimization_settings', $validated_settings);

        // Clear image-optimization related caches without flushing global object cache.
        delete_transient('prorank_image_quota_exceeded');
        delete_transient('prorank_image_optimization_progress');
        delete_transient('prorank_image_conversion_running');

        global $wpdb;
        if ($wpdb && isset($wpdb->options)) {
            $wpdb->query(
                "DELETE FROM {$wpdb->options}
                 WHERE option_name LIKE '_transient_prorank_image_usage_%'
                 OR option_name LIKE '_transient_timeout_prorank_image_usage_%'"
            );
        }

        return rest_ensure_response([
            'success' => true,
            'settings' => $validated_settings,
        ]);
    }

    /**
     * Get image optimization statistics
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function get_stats(WP_REST_Request $request) {
        // Prefer module stats so we reuse one source of truth
        $module_enabled = false;
        $plugin = \ProRank\SEO\Plugin::get_instance();
        $stats = [
            'total_images' => 0,
            'optimized_images' => 0,
            'saved_bytes' => 0,
            'optimization_percentage' => 0,
            'already_modern_images' => 0,
            'unsupported_images' => 0,
            'source_images' => 0,
            'pending' => 0,
            'unresolved_images' => 0,
            'failed_images' => 0,
            'retryable_failed_images' => 0,
            'exhausted_failed_images' => 0,
            'no_gain_images' => 0,
            'bulk_retry_limit' => 0,
            'backup_size' => 0,
            'backup_size_formatted' => '',
        ];

        if ($plugin && $plugin->is_initialized()) {
            $module = $plugin->modules()->get_module('image_optimization');
            if ($module && method_exists($module, 'get_stats')) {
                $module_enabled = method_exists($module, 'is_enabled')
                    ? (bool) $module->is_enabled()
                    : false;
                $module_stats = $module->get_stats();
                $stats['total_images'] = (int) ($module_stats['total'] ?? 0);
                $stats['optimized_images'] = (int) ($module_stats['optimized'] ?? 0);
                $stats['saved_bytes'] = (int) ($module_stats['total_savings'] ?? $module_stats['bytes_saved'] ?? 0);
                $stats['optimization_percentage'] = $stats['total_images'] > 0
                    ? round(($stats['optimized_images'] / $stats['total_images']) * 100, 2)
                    : 0;
                $stats['already_modern_images'] = (int) ($module_stats['already_modern_images'] ?? 0);
                $stats['unsupported_images'] = (int) ($module_stats['unsupported_images'] ?? 0);
                $stats['source_images'] = (int) ($module_stats['source_images'] ?? 0);
                $stats['pending'] = (int) ($module_stats['pending'] ?? 0);
                $stats['unresolved_images'] = (int) ($module_stats['unresolved_images'] ?? 0);
                $stats['failed_images'] = (int) ($module_stats['failed_images'] ?? 0);
                $stats['retryable_failed_images'] = (int) ($module_stats['retryable_failed_images'] ?? 0);
                $stats['exhausted_failed_images'] = (int) ($module_stats['exhausted_failed_images'] ?? 0);
                $stats['no_gain_images'] = (int) ($module_stats['no_gain_images'] ?? 0);
                $stats['bulk_retry_limit'] = (int) ($module_stats['bulk_retry_limit'] ?? 0);
                if (!empty($module_stats['backup_size'])) {
                    $stats['backup_size'] = (int) ($module_stats['backup_size'] ?? 0);
                    $stats['backup_size_formatted'] = $module_stats['backup_size_formatted'] ?? '';
                }
            }
        }

        return rest_ensure_response([
            'module_enabled' => $module_enabled,
            'stats' => $stats,
        ]);
    }

    /**
     * Start bulk optimization process
     *
     * @param WP_REST_Request $request Request object.
     * @return WP_REST_Response|WP_Error
     */
    public function start_bulk_optimization(WP_REST_Request $request) {
        // Check if a bulk process is already running
        if (get_transient('prorank_bulk_optimization_running')) {
            return rest_ensure_response([
                'success' => true,
                'already_running' => true,
                'message' => __('Bulk optimization is already running. Resuming the existing job.', 'prorank-seo'),
            ]);
        }

        // Set running flag
        set_transient('prorank_bulk_optimization_running', true, HOUR_IN_SECONDS);

        // Schedule background task
        if (!wp_next_scheduled('prorank_bulk_optimize_images')) {
            wp_schedule_single_event(time() + 10, 'prorank_bulk_optimize_images');
        }

        // Kick off WP-Cron immediately when possible to avoid waiting for the next visitor.
        if (function_exists('spawn_cron')) {
            spawn_cron(time());
        }

        return rest_ensure_response([
            'success' => true,
            'message' => __('Bulk optimization started successfully', 'prorank-seo'),
        ]);
    }

    /**
     * Validate settings
     *
     * @param array $settings Settings to validate.
     * @return array Validated settings.
     */
    private function validate_settings(array $settings): array {
        $defaults = [
            'optimization_method' => 'local',
            'webp_enabled' => true,
            'webp_quality' => 85,
            'avif_enabled' => false,
            'avif_quality' => 80,
            'jxl_enabled' => false,
            'jxl_quality' => 80,
            'jpegli_enabled' => false,
            'png_quality' => 80,
            'png_pipeline' => false,
            'smart_compression' => true,
            'compression_type' => 'glossy',
            'optimize_on_upload' => false,
            'background_mode' => false,
            'backup_originals' => true,
            'optimize_original_source' => false,
            'lazyload_images' => false,
            'lazyload_iframes' => false,
            'lazyload_videos' => false,
            'lazyload_threshold' => 200,
            'cdn_enabled' => false,
            'cdn_url' => '',
            'exclude_paths' => '',
            'cloud_opt_in' => false,
            'cloud_opt_in_at' => null,
            // Advanced settings
            'png_to_jpeg' => true,
            'cmyk_to_rgb' => true,
            'remove_exif' => true,
            'optimize_pdf' => false,
            'generate_retina' => false,
            'no_ai_training' => false,
            'delivery_method' => 'picture',
            // Client Hints settings
            'client_hints_enabled' => false,
            'client_hints_dpr' => true,
            'client_hints_width' => true,
            'client_hints_viewport' => true,
            'client_hints_save_data' => false,
            // CDN settings
            'cdn_mode' => 'disabled',
            'cdn_custom_endpoint' => '',
            // SmartCrop & Resize settings
            'smart_crop_enabled' => false,
            'resize_large_enabled' => false,
            'resize_max_width' => 2560,
            'resize_max_height' => 2560,
            // Additional settings
            'jpeg_quality' => 85,
            'exclude_sizes' => [],
            'cdn_exclude_paths' => '',
        ];

        $validated = [];

        foreach ($defaults as $key => $default) {
            if (isset($settings[$key])) {
                switch ($key) {
                    case 'cloud_opt_in':
                        $validated[$key] = filter_var($settings[$key], FILTER_VALIDATE_BOOLEAN);
                        break;

                    case 'cloud_opt_in_at':
                        $validated[$key] = is_numeric($settings[$key]) ? (int) $settings[$key] : null;
                        break;

                    case 'webp_quality':
                    case 'avif_quality':
                    case 'jxl_quality':
                    case 'png_quality':
                    case 'jpeg_quality':
                        $validated[$key] = max(0, min(100, intval($settings[$key])));
                        break;

                    case 'lazyload_threshold':
                        $validated[$key] = max(0, min(1000, intval($settings[$key])));
                        break;

                    case 'resize_max_width':
                    case 'resize_max_height':
                        $validated[$key] = max(100, min(10000, intval($settings[$key])));
                        break;

                    case 'cdn_url':
                    case 'cdn_custom_endpoint':
                        $validated[$key] = esc_url_raw($settings[$key]);
                        break;

                    case 'exclude_paths':
                    case 'cdn_exclude_paths':
                        $validated[$key] = sanitize_textarea_field($settings[$key]);
                        break;

                    case 'exclude_sizes':
                        if (is_array($settings[$key])) {
                            $validated[$key] = array_map('sanitize_text_field', $settings[$key]);
                        } else {
                            $validated[$key] = [];
                        }
                        break;

                    case 'optimization_method':
                        $valid_methods = ['local'];
                        $validated[$key] = in_array($settings[$key], $valid_methods)
                            ? $settings[$key]
                            : $default;
                        break;

                    case 'compression_type':
                        $valid_types = ['lossless', 'glossy', 'lossy', 'aggressive'];
                        $validated[$key] = in_array($settings[$key], $valid_types)
                            ? $settings[$key]
                            : $default;
                        break;

                    case 'delivery_method':
                        $valid_methods = ['picture', 'accept_header', 'htaccess', 'cdn', 'none'];
                        $validated[$key] = in_array($settings[$key], $valid_methods)
                            ? $settings[$key]
                            : $default;
                        break;

                    case 'cdn_mode':
                        $valid_modes = ['disabled', 'custom'];
                        $validated[$key] = in_array($settings[$key], $valid_modes)
                            ? $settings[$key]
                            : $default;
                        break;

                    default:
                        $validated[$key] = (bool) $settings[$key];
                        break;
                }
            } else {
                $validated[$key] = $default;
            }
        }

        $validated['optimization_method'] = 'local';
        $validated['cloud_opt_in'] = false;
        $validated['cloud_opt_in_at'] = null;

        return $validated;
    }

    /**
     * Check if user has permission to read items
     *
     * @param WP_REST_Request $request Request object.
     * @return bool|WP_Error
     */
    public function get_items_permissions_check($request) {
        return current_user_can('manage_options');
    }

    /**
     * Check if user has permission to create items
     *
     * @param WP_REST_Request $request Request object.
     * @return bool|WP_Error
     */
    public function create_item_permissions_check($request) {
        return current_user_can('manage_options');
    }
}
