<?php
namespace Mamba\Modules\Media\Services;

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

/**
 * WooCommerce-Focused LCP (Largest Contentful Paint) Optimizer
 * 
 * Optimizes critical images for faster loading on WooCommerce pages:
 * - Product images (main + gallery)
 * - Shop page images
 * - Category images
 * - Featured images
 */
final class LCPOptimizer {
    private int $imageCounter = 0;
    private array $lcpCandidates = [];
    
    public function register(): void {
        // Feature Gating: LCP Optimization is a Premium feature
        if (!get_option('mamba_enable_lcp_optimization', 0) || !function_exists('mamba_fs') || !mamba_fs()->can_use_premium_code__premium_only()) {
            return;
        }

        add_filter('wp_get_attachment_image_attributes', [$this, 'optimizeImageAttributes'], 10, 3);
        add_action('wp_head', [$this, 'injectPreloadTags'], 1);
        
        // Enable more aggressive PLP LCP optimization
        add_filter('mamba_lcp_push_from_attr', [$this, 'enablePlpAggressiveMode'], 10, 1);
    }
    
    /**
     * Optimize image loading attributes for LCP performance
     */
    public function optimizeImageAttributes(array $attr, $attachment, $size): array {
        // Handle numeric attachment IDs (rare edge case)
        if (is_numeric($attachment)) {
            $attachment = get_post((int)$attachment);
        }
        
        // Skip if not a valid attachment
        if (!$attachment || !is_object($attachment)) {
            return $attr;
        }
        
        // Skip in admin, feeds, and AJAX to prevent affecting media library/editor/feeds
        if (is_admin() || is_feed() || (defined('DOING_AJAX') && DOING_AJAX)) {
            return $attr;
        }
        
        $attachmentId = $attachment->ID;
        $sizeArg = (is_string($size) || is_array($size)) ? $size : 'large';
        
        $isCritical = $this->isCriticalImage($attachmentId);
        
        // New: size-aware fallback for the very first image on key Woo pages
        if (
            !$isCritical &&
            $this->imageCounter === 0 &&
            (
                (function_exists('is_product') && is_product()) ||
                (function_exists('is_shop') && is_shop()) ||
                (function_exists('is_product_category') && is_product_category())
            )
        ) {
            // Only treat as critical if it's reasonably large (default ≥320px wide)
            $dim = wp_get_attachment_image_src($attachmentId, $sizeArg);
            $minW = (int) apply_filters('mamba_lcp_min_first_image_width', 320);
            if (is_array($dim) && !empty($dim[1]) && (int) $dim[1] >= $minW) {
                $isCritical = true;
            }
        }
        
        if ($isCritical) {
            if (!isset($attr['loading'])) {
                $attr['loading'] = 'eager';
            }
            $attr['fetchpriority'] = $attr['fetchpriority'] ?? 'high';
            
            // This push happens after wp_head; it won't affect <link rel="preload">.
            // Keep it behind a filter (off by default) to avoid wasted work.
            if (apply_filters('mamba_lcp_push_from_attr', false, $attachmentId, $sizeArg)) {
                $this->pushImagePreloadWithSrcset($attachmentId, $sizeArg);
            }
        } else {
            if (!isset($attr['loading'])) {
                $attr['loading'] = 'lazy';
            }
            unset($attr['fetchpriority']); // let the browser decide
            if (!isset($attr['decoding'])) {
                $attr['decoding'] = 'async';
            }
        }
        
        $this->imageCounter++;
        return $attr;
    }
    
    /**
     * Check if image is critical for LCP (should load eagerly)
     */
    private function isCriticalImage(int $attachmentId): bool {
        // Featured image is critical
        $postId = get_queried_object_id();
        if ($postId && get_post_thumbnail_id($postId) === $attachmentId) {
            return true;
        }
        
        // WooCommerce product main image is critical
        if ($this->isWooCommerceProductImage($attachmentId)) {
            return true;
        }
        
        // WooCommerce shop page image is critical
        if ($this->isWooCommerceShopImage($attachmentId)) {
            return true;
        }
        
        // WooCommerce category image is critical
        if ($this->isWooCommerceCategoryImage($attachmentId)) {
            return true;
        }
        
        // Allow themes to mark additional images as critical
        return apply_filters('mamba_lcp_is_critical_image', false, $attachmentId);
    }
    
    /**
     * Check if image is WooCommerce product main image
     */
    private function isWooCommerceProductImage(int $attachmentId): bool {
        if (!function_exists('is_product') || !is_product()) {
            return false;
        }
        
        global $product;
        if (!$product || !is_object($product)) {
            return false;
        }
        
        return $product->get_image_id() === $attachmentId;
    }
    
    /**
     * Check if image is WooCommerce shop page image
     */
    private function isWooCommerceShopImage(int $attachmentId): bool {
        if (!function_exists('is_shop') || !is_shop()) {
            return false;
        }
        
        // Check if this is the shop page featured image
        $shopPageId = wc_get_page_id('shop');
        if ($shopPageId && get_post_thumbnail_id($shopPageId) === $attachmentId) {
            return true;
        }
        
        return false;
    }
    
    /**
     * Check if image is WooCommerce category image
     */
    private function isWooCommerceCategoryImage(int $attachmentId): bool {
        if (!function_exists('is_product_category') || !is_product_category()) {
            return false;
        }
        
        $category = get_queried_object();
        if (!$category || !is_object($category)) {
            return false;
        }
        
        // Check if this is the category thumbnail
        $thumbnailId = get_term_meta($category->term_id, 'thumbnail_id', true);
        return (int)$thumbnailId === $attachmentId;
    }
    
    /**
     * Extract background images from content
     */
    private function extractBackgroundImagesFromContent(string $content): void {
        preg_match_all('/background(?:-image)?\s*:\s*url\(([^\)]+)\)/i', $content, $matches);
        if (!empty($matches[1])) {
            foreach ($matches[1] as $url) {
                $url = trim($url, "\"'");
                
                // Skip data URLs and invalid URLs
                if (stripos($url, 'data:') === 0) continue;
                if (!wp_http_validate_url($url) && strpos($url, '/') !== 0) continue;
                
                $this->lcpCandidates['images'][] = esc_url_raw($url);
            }
        }
    }
    
    /**
     * Inject preload tags for critical resources
     */
    public function injectPreloadTags(): void {
        // Skip on admin, feeds, robots, previews, AMP, REST
        if (is_admin() || is_feed() || is_robots() || is_preview()) {
            return;
        }
        
        // Skip on AMP endpoints
        if (function_exists('is_amp_endpoint') && is_amp_endpoint()) {
            return;
        }
        
        // Skip on REST requests
        if (defined('REST_REQUEST') && REST_REQUEST) {
            return;
        }
        
        global $post;
        
        // Process singular pages
        if (is_singular() && $post instanceof \WP_Post) {
            $this->processSingularPage($post);
        }
        
        // Process WooCommerce pages
        $this->processWooCommercePages();
        

        
        // Output preload tags
        $this->outputPreloadTags();
    }
    
    /**
     * Process singular page content
     */
    private function processSingularPage(\WP_Post $post): void {
        // Featured image
        if (has_post_thumbnail($post)) {
            $thumbId = get_post_thumbnail_id($post);
            if ($thumbId) {
                $this->pushImagePreloadWithSrcset(
                    $thumbId,
                    apply_filters('mamba_lcp_featured_image_size', 'large')
                );
            }
        }
        
        // Extract inline background images
        $this->extractBackgroundImagesFromContent($post->post_content);
        
        // Detect video poster images
        if (preg_match_all('/poster=["\'](.*?)["\']/', $post->post_content, $matches)) {
            foreach ($matches[1] as $posterUrl) {
                $u = trim($posterUrl);
                if (stripos($u, 'data:') === 0) continue;
                if (!wp_http_validate_url($u) && strpos($u, '/') !== 0) continue;
                $this->lcpCandidates['images'][] = esc_url_raw($u);
            }
        }
    }
    
    /**
     * Process WooCommerce-specific pages
     */
    private function processWooCommercePages(): void {
        // Product page images
        if (function_exists('is_product') && is_product()) {
            $this->processProductMainImage();
            $this->processProductGallery();
        }
        
        // Shop page images
        if (function_exists('is_shop') && is_shop()) {
            $this->processShopPage();
        }
        
        // Category page images
        if (function_exists('is_product_category') && is_product_category()) {
            $this->processCategoryPage();
        }
    }
    
    /**
     * Process main product image (most critical for LCP)
     */
    private function processProductMainImage(): void {
        $pid = get_queried_object_id();
        if (!$pid) return;
        if (!function_exists('wc_get_product')) return;
        
        $product = wc_get_product($pid);
        if (!$product) return;
        
        $imgId = $product->get_image_id();
        if ($imgId) {
            $size = apply_filters('mamba_lcp_product_main_size', 'woocommerce_single');
            $this->pushImagePreloadWithSrcset($imgId, $size);
        }
    }
    
    /**
     * Process product gallery images
     */
    private function processProductGallery(): void {
        $pid = get_queried_object_id();
        if (!function_exists('wc_get_product') || !$pid) return;
        
        $product = wc_get_product($pid);
        if (!$product) return;
        
        // Get gallery image IDs
        $galleryIds = $product->get_gallery_image_ids();
        
        // First gallery image gets high priority (after main image)
        if (!empty($galleryIds)) {
            $size = apply_filters('mamba_lcp_product_gallery_size', 'large');
            $this->pushImagePreloadWithSrcset($galleryIds[0], $size);
        }
    }
    
    /**
     * Process shop page images
     */
    private function processShopPage(): void {
        $shopPageId = wc_get_page_id('shop');
        if ($shopPageId && has_post_thumbnail($shopPageId)) {
            $thumbnailId = get_post_thumbnail_id($shopPageId);
            if ($thumbnailId) {
                $size = apply_filters('mamba_lcp_shop_image_size', 'large');
                $this->pushImagePreloadWithSrcset($thumbnailId, $size);
            }
        }
    }
    
    /**
     * Process category page images
     */
    private function processCategoryPage(): void {
        $category = get_queried_object();
        if (!$category || !is_object($category)) {
            return;
        }
        
        $thumbnailId = get_term_meta($category->term_id, 'thumbnail_id', true);
        if ($thumbnailId) {
            $size = apply_filters('mamba_lcp_category_image_size', 'large');
            $this->pushImagePreloadWithSrcset($thumbnailId, $size);
        }
    }
    
    /**
     * Convert file path to URL using proper theme directory mapping
     */
    private function pathToUrl(string $path): ?string {
        $map = [
            get_stylesheet_directory() => get_stylesheet_directory_uri(),
            get_template_directory() => get_template_directory_uri(),
        ];
        
        foreach ($map as $root => $uri) {
            if (strpos($path, $root) === 0) {
                return $uri . substr($path, strlen($root));
            }
        }
        
        return null;
    }
    
    /**
     * Normalize URLs for better compatibility
     */
    private function normalizeUrl(string $url): string {
        if (strpos($url, '//') === 0) {
            return (is_ssl() ? 'https:' : 'http:') . $url;
        }
        if (strpos($url, '/') === 0) {
            return home_url($url);
        }
        return $url;
    }
    
    /**
     * Push image preload with responsive variants
     */
    private function pushImagePreloadWithSrcset(int $attachmentId, $size = 'large'): void {
        $url = wp_get_attachment_image_url($attachmentId, $size);
        $srcset = wp_get_attachment_image_srcset($attachmentId, $size);
        $sizes = wp_get_attachment_image_sizes($attachmentId, $size);
        
        if ($url) {
            $url = esc_url_raw($url);
            $this->lcpCandidates['images'][] = [
                'url' => $url,
                'srcset' => $srcset ?: '',
                'sizes' => $sizes ?: '',
            ];
        }
    }
    
    /**
     * Enable aggressive PLP LCP optimization
     */
    public function enablePlpAggressiveMode(bool $push): bool {
        return (function_exists('is_shop') && is_shop())
            || (function_exists('is_product_category') && is_product_category());
    }
    
    /**
     * Canonicalize and deduplicate image entries by URL
     */
    private function uniqueImageEntries(array $entries): array {
        $seen = [];
        $out = [];
        
        foreach ($entries as $e) {
            $url = is_array($e) ? ($e['url'] ?? '') : (string) $e;
            if (!$url) continue;
            
            $url = $this->normalizeUrl($url);
            if (isset($seen[$url])) continue;
            
            $seen[$url] = true;
            
            // Normalize to canonical array shape
            if (!is_array($e)) {
                $e = ['url' => $url, 'srcset' => '', 'sizes' => ''];
            } else {
                $e['url'] = $url; // ensure normalized
            }
            
            $out[] = $e;
        }
        
        return $out;
    }
    
    /**
     * Output preload tags
     */
    private function outputPreloadTags(): void {
        if (!apply_filters('mamba_lcp_should_output', true)) {
            return;
        }
        
        if (empty($this->lcpCandidates)) {
            return;
        }
        
        $maxImages = (int) apply_filters('mamba_lcp_max_image_preloads', 3);
        
        foreach ($this->lcpCandidates as $type => $urls) {
            if ($type === 'images') {
                $urls = $this->uniqueImageEntries($urls);
                $urls = array_slice($urls, 0, $maxImages);
            }
            
            // Allow customization of candidates
            $urls = apply_filters('mamba_lcp_collect_candidates', $urls, $type);
            $urls = is_array($urls) ? $urls : (array) $urls;
            
            // Safety: re-canonicalize after external filter (in case filter returned non-canonical format)
            if ($type === 'images') {
                $urls = $this->uniqueImageEntries($urls);
            }
            
            foreach ($urls as $entry) {
                switch ($type) {
                    case 'images':
                        // entry is canonical array here
                        $href = $entry['url'];
                        echo '<link rel="preload" as="image" href="' . esc_url($href) . '" fetchpriority="high"';
                        if (!empty($entry['srcset'])) {
                            echo ' imagesrcset="' . esc_attr($entry['srcset']) . '"';
                        }
                        if (!empty($entry['sizes'])) {
                            echo ' imagesizes="' . esc_attr($entry['sizes']) . '"';
                        }
                        echo '>' . "\n";
                        break;
                }
            }
        }
    }
}
