<?php
/**
 * Media Optimization Module
 *
 * Provides image optimization features including WebP/AVIF conversion,
 * image compression, LCP optimization, and bulk optimization tools.
 *
 * @package Mamba\Modules\Media
 * @since   1.0.0
 */

namespace Mamba\Modules\Media;

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

use Mamba\Support\Paths;
use Mamba\Modules\Media\Services\LCPOptimizer;
use Mamba\Modules\Media\Services\ImageCompressor;
use Mamba\Modules\Media\Services\WebPConverter;
use Mamba\Modules\Media\Services\AvifConverter;
use Mamba\Modules\Media\Services\HtaccessManager;
use Mamba\Modules\Media\Services\BulkOptimizer;
use Mamba\Modules\Media\Services\MediaInvalidation;
use Mamba\Modules\Media\Admin\WebPNginxSupport;

/**
 * Class Module
 *
 * Main media module that registers image optimization services,
 * handles .htaccess rules for next-gen formats, and renders admin tabs.
 *
 * @since 1.0.0
 */
final class Module {
    public function __construct(private ?Paths $paths = null) {}
    
    public function register(): void {
        add_action('mamba/admin/tab/media', [$this, 'renderMedia'], 10, 1);
        
        // Register AJAX handler for live settings save
        add_action('wp_ajax_mamba_save_media_setting', [$this, 'handleSaveMediaSetting']);
        
        // Premium Feature Gate: Only register premium features for premium users
        $can_use_premium = function_exists('mamba_fs') && mamba_fs()->can_use_premium_code__premium_only();
        
        // Register LCP Optimizer if enabled (Premium)
        if ($can_use_premium && get_option('mamba_enable_lcp_optimization', 0)) {
            (new LCPOptimizer())->register();
        }
        
        // Register Image Compressor if enabled (Premium)
        if ($can_use_premium && get_option('mamba_enable_image_compression', 0)) {
            (new ImageCompressor())->register();
        }
        
        // Register WebP Converter if enabled (Free feature)
        if (get_option('mamba_enable_webp_conversion', 0)) {
            (new WebPConverter())->register();
        }

        // Register AVIF Converter if enabled (Premium)
        if ($can_use_premium && get_option('mamba_enable_avif_conversion', 0)) {
            (new AvifConverter())->register();
        }

        // Ensure .htaccess rules exist for Next-Gen serving (WebP free, AVIF premium)
        $webp_enabled = get_option('mamba_enable_webp_conversion', 0);
        $avif_enabled = $can_use_premium && get_option('mamba_enable_avif_conversion', 0);
        if ($webp_enabled || $avif_enabled) {
            $htaccessManager = new HtaccessManager();
            $serverInfo = $htaccessManager->getServerInfo();
            if ($htaccessManager->isSupported() && $serverInfo['is_apache_compatible'] && !$htaccessManager->hasNextGenRules()) {
                $htaccessManager->addNextGenRules();
            }
        }
        
        // Register Bulk Optimizer (always available for admin)
        (new BulkOptimizer())->register();
        
        // Register Media Invalidation (always active for media optimization)
        (new MediaInvalidation())->register();
        
        // Register WebP Nginx Support (detect-only flow)
        (new WebPNginxSupport())->register();
        
        // Add missing image dimensions (reduces CLS)
        if (get_option('mamba_add_image_dimensions', 0)) {
            add_filter('the_content', [$this, 'addMissingImageDimensions'], 99);
            add_filter('post_thumbnail_html', [$this, 'addMissingImageDimensions'], 99);
            add_filter('woocommerce_single_product_image_thumbnail_html', [$this, 'addMissingImageDimensions'], 99);
        }
    }
    
    public function renderMedia(Paths $paths): void {
        $view = __DIR__ . '/views/TabMedia.php';
        if (file_exists($view)) require $view; else echo '<div class="mamba-card">Media optimizations…</div>';
    }
    
    /**
     * Handle AJAX request to save a single media setting
     */
    public function handleSaveMediaSetting(): void {
        check_ajax_referer('mamba_media_settings', 'nonce');
        
        if (!current_user_can('manage_options')) {
            wp_send_json_error(['message' => 'Insufficient permissions']);
        }
        
        $setting = sanitize_text_field(wp_unslash($_POST['setting'] ?? ''));
        $value = wp_unslash($_POST['value'] ?? '');
        
        // Whitelist of allowed settings
        $allowed_settings = [
            'mamba_enable_lcp_optimization',
            'mamba_enable_image_compression',
            'mamba_compression_quality',
            'mamba_compression_type',
            'mamba_compress_full_size',
            'mamba_enable_webp_conversion',
            'mamba_webp_quality',
            'mamba_convert_full_size',
            'mamba_enable_avif_conversion',
            'mamba_avif_quality',
            'mamba_convert_full_size_avif',
            'mamba_add_image_dimensions',
        ];
        
        if (!in_array($setting, $allowed_settings, true)) {
            wp_send_json_error(['message' => 'Invalid setting']);
        }
        
        // Handle mutual exclusivity for WebP/AVIF
        if ($setting === 'mamba_enable_webp_conversion' && $value) {
            update_option('mamba_enable_avif_conversion', 0);
        } elseif ($setting === 'mamba_enable_avif_conversion' && $value) {
            update_option('mamba_enable_webp_conversion', 0);
        }
        
        // Sanitize value based on setting type
        if (in_array($setting, ['mamba_compression_quality', 'mamba_webp_quality', 'mamba_avif_quality'])) {
            $value = absint($value);
        } elseif ($setting === 'mamba_compression_type') {
            $value = sanitize_text_field($value);
        } else {
            $value = $value ? 1 : 0;
        }
        
        update_option($setting, $value);
        
        // Handle .htaccess rules for next-gen formats
        $webp_enabled = (bool) get_option('mamba_enable_webp_conversion', 0);
        $avif_enabled = (bool) get_option('mamba_enable_avif_conversion', 0);
        
        $htaccessManager = new HtaccessManager();
        $serverInfo = $htaccessManager->getServerInfo();
        
        if ($htaccessManager->isSupported() && $serverInfo['is_apache_compatible']) {
            if ($webp_enabled || $avif_enabled) {
                $htaccessManager->addNextGenRules();
            } else {
                $htaccessManager->removeNextGenRules();
            }
        }
        
        // Get updated Nginx config if needed
        $nginxConfig = '';
        if (!$serverInfo['is_apache_compatible'] && ($webp_enabled || $avif_enabled)) {
            $nginxConfig = $htaccessManager->getNginxNextGenConfig();
        }
        
        // Get updated stats
        $bulkOptimizer = new BulkOptimizer();
        $stats = $bulkOptimizer->getTotalCounts();
        
        wp_send_json_success([
            'message' => 'Setting saved',
            'webp_enabled' => $webp_enabled,
            'avif_enabled' => $avif_enabled,
            'nginx_config' => $nginxConfig,
            'stats' => $stats
        ]);
    }
    
    /**
     * Add missing width and height attributes to images
     * Reduces Cumulative Layout Shift (CLS) for better Core Web Vitals
     * 
     * @param string $content HTML content containing images
     * @return string Modified content with image dimensions added
     */
    public function addMissingImageDimensions(string $content): string {
        if (empty($content)) {
            return $content;
        }
        
        // Match all img tags
        return preg_replace_callback('/<img\s+[^>]*>/i', function($match) {
            $img = $match[0];
            
            // Skip if already has both width and height
            if (preg_match('/\swidth\s*=/i', $img) && preg_match('/\sheight\s*=/i', $img)) {
                return $img;
            }
            
            // Extract src attribute
            if (!preg_match('/\ssrc\s*=\s*["\']([^"\']+)["\']/i', $img, $srcMatch)) {
                return $img;
            }
            
            $src = $srcMatch[1];
            
            // Skip data URIs and external images (for performance)
            if (strpos($src, 'data:') === 0) {
                return $img;
            }
            
            // Try to get dimensions
            $dimensions = $this->getImageDimensions($src);
            
            if (!$dimensions) {
                return $img;
            }
            
            $width  = (int) $dimensions[0];
            $height = (int) $dimensions[1];
            
            if ( $width <= 0 || $height <= 0 ) {
                return $img;
            }
            
            // Add missing attributes
            $hasWidth = preg_match('/\swidth\s*=/i', $img);
            $hasHeight = preg_match('/\sheight\s*=/i', $img);
            
            if (!$hasWidth && !$hasHeight) {
                // Add both
                $img = preg_replace('/<img\s/i', '<img width="' . esc_attr( $width ) . '" height="' . esc_attr( $height ) . '" ', $img);
            } elseif (!$hasWidth) {
                // Add width only
                $img = preg_replace('/<img\s/i', '<img width="' . esc_attr( $width ) . '" ', $img);
            } elseif (!$hasHeight) {
                // Add height only
                $img = preg_replace('/<img\s/i', '<img height="' . esc_attr( $height ) . '" ', $img);
            }
            
            return $img;
        }, $content);
    }
    
    /**
     * Get image dimensions from URL
     * Supports local files and cached remote lookups
     * 
     * @param string $src Image URL
     * @return array|null [width, height] or null if not found
     */
    private function getImageDimensions(string $src): ?array {
        // Convert URL to local path if it's a local image
        $siteUrl = site_url();
        $homeUrl = home_url();
        $uploadDir = wp_upload_dir();
        
        $localPath = null;
        
        // Check if it's a local URL
        if (strpos($src, $siteUrl) === 0) {
            $localPath = str_replace($siteUrl, ABSPATH, $src);
        } elseif (strpos($src, $homeUrl) === 0) {
            $localPath = str_replace($homeUrl, ABSPATH, $src);
        } elseif (strpos($src, $uploadDir['baseurl']) === 0) {
            $localPath = str_replace($uploadDir['baseurl'], $uploadDir['basedir'], $src);
        } elseif (strpos($src, '/wp-content/') === 0) {
            // Relative path starting with /wp-content/
            $localPath = ABSPATH . ltrim($src, '/');
        }
        
        // Try local file first
        if ($localPath && file_exists($localPath)) {
            $size = @getimagesize($localPath);
            if ($size && isset($size[0]) && isset($size[1])) {
                return [$size[0], $size[1]];
            }
        }
        
        // Try to get from attachment metadata (more efficient for WordPress media)
        $attachmentId = attachment_url_to_postid($src);
        if ($attachmentId) {
            $metadata = wp_get_attachment_metadata($attachmentId);
            if ($metadata && isset($metadata['width']) && isset($metadata['height'])) {
                return [$metadata['width'], $metadata['height']];
            }
        }
        
        // For external images, use cached lookup (optional, disabled by default for performance)
        if (apply_filters('mamba_image_dimensions_check_external', false)) {
            $cacheKey = 'mamba_img_dim_' . md5($src);
            $cached = get_transient($cacheKey);
            
            if ($cached !== false) {
                return $cached === 'none' ? null : $cached;
            }
            
            // Fetch image headers only (not full image)
            $size = @getimagesize($src);
            if ($size && isset($size[0]) && isset($size[1])) {
                $dimensions = [$size[0], $size[1]];
                set_transient($cacheKey, $dimensions, DAY_IN_SECONDS);
                return $dimensions;
            }
            
            // Cache negative result
            set_transient($cacheKey, 'none', HOUR_IN_SECONDS);
        }
        
        return null;
    }
}


