<?php

/**
 * AI-Powered CSS Analyzer for Critical CSS Generation
 *
 * Uses machine learning heuristics to identify critical CSS
 *
 * @package ProRank\SEO\Modules\Performance
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\Performance;

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


/**
 * CssAiAnalyzer class
 */


class CssAiAnalyzer {
    
    /**
     * Critical CSS properties that affect layout (2025 Enhanced)
     *
     * @var array
     */
    private const CRITICAL_PROPERTIES = [
        // Core Layout
        'display' => 100,
        'position' => 90,
        'width' => 85,
        'height' => 85,
        'margin' => 80,
        'padding' => 80,
        'top' => 75,
        'left' => 75,
        'right' => 75,
        'bottom' => 75,
        'float' => 70,
        'clear' => 70,
        
        // Modern Layout (2025)
        'flex' => 85,
        'flex-direction' => 85,
        'flex-wrap' => 80,
        'justify-content' => 80,
        'align-items' => 80,
        'grid' => 85,
        'grid-template' => 85,
        'grid-template-columns' => 85,
        'grid-template-rows' => 85,
        'gap' => 80,
        
        // Container Queries (2025)
        'container' => 95,
        'container-type' => 95,
        'container-name' => 90,
        
        // Logical Properties (2025)
        'block-size' => 85,
        'inline-size' => 85,
        'margin-block' => 80,
        'margin-inline' => 80,
        'padding-block' => 80,
        'padding-inline' => 80,
        
        // View Transitions API (2025)
        'view-transition-name' => 70,
        
        // Scroll-driven Animations (2025)
        'animation-timeline' => 60,
        'animation-range' => 60,
        
        // Visual
        'visibility' => 90,
        'opacity' => 60,
        'z-index' => 70,
        'overflow' => 65,
        'aspect-ratio' => 75,
        'object-fit' => 70,
        'object-position' => 65,
        
        // Typography
        'font-family' => 80,
        'font-size' => 75,
        'line-height' => 70,
        'color' => 50,
        'text-wrap' => 65, // 2025 feature
        
        // Backgrounds & Borders
        'background' => 50,
        'background-color' => 45,
        'background-image' => 40,
        'border' => 55,
        'border-radius' => 50,
        'box-shadow' => 45,
        
        // Box Model
        'box-sizing' => 90,
        'contain' => 80, // CSS Containment
        'content-visibility' => 85, // 2025 optimization
        
        // Transforms & Animations
        'transform' => 60,
        'transition' => 30,
        'animation' => 35,
        'will-change' => 40,
    ];
    
    /**
     * Selector patterns that indicate critical elements (2025 Enhanced)
     *
     * @var array
     */
    private const CRITICAL_PATTERNS = [
        // Core Elements
        '/^(html|body)/i' => 100,
        '/^\*$/i' => 95, // Universal selector
        '/^:root/i' => 100, // CSS custom properties
        
        // Header & Navigation
        '/header/i' => 90,
        '/nav/i' => 90,
        '/menu/i' => 80,
        '/navbar/i' => 85,
        '/topbar/i' => 85,
        '/toolbar/i' => 80,
        
        // Hero & Above Fold
        '/hero/i' => 85,
        '/banner/i' => 85,
        '/above-fold/i' => 100,
        '/critical/i' => 100,
        '/masthead/i' => 85,
        '/jumbotron/i' => 80,
        '/splash/i' => 80,
        '/announcement/i' => 75,
        '/alert/i' => 80,
        
        // Branding
        '/logo/i' => 80,
        '/brand/i' => 75,
        '/site-title/i' => 80,
        
        // Layout
        '/main/i' => 75,
        '/content/i' => 70,
        '/container/i' => 70,
        '/wrapper/i' => 65,
        '/layout/i' => 75,
        '/grid/i' => 70,
        '/flex/i' => 70,
        '/row/i' => 65,
        '/col(umn)?/i' => 65,
        
        // Modern Components (2025)
        '/card/i' => 60,
        '/modal/i' => 55,
        '/dialog/i' => 55,
        '/popover/i' => 50,
        '/toast/i' => 60,
        '/skeleton/i' => 75, // Loading states
        '/placeholder/i' => 70,
        
        // Responsive & Adaptive
        '/mobile/i' => 70,
        '/desktop/i' => 65,
        '/responsive/i' => 70,
        '/adaptive/i' => 70,
        
        // Performance Hints
        '/lazy/i' => 40,
        '/defer/i' => 40,
        '/async/i' => 40,
        '/preload/i' => 80,
        '/prefetch/i' => 60,
    ];
    
    /**
     * Media query breakpoints for 2025
     *
     * @var array
     */
    private const MODERN_BREAKPOINTS = [
        'mobile' => 640,
        'tablet' => 768,
        'laptop' => 1024,
        'desktop' => 1280,
        'wide' => 1536,
        'ultrawide' => 1920,
    ];
    
    /**
     * Analyze critical selectors using AI heuristics (2025 Enhanced)
     *
     * @param array  $css_analysis  CSS analysis data
     * @param array  $fold_elements Above-fold elements
     * @param string $html         HTML content
     * @return array AI recommendations
     */
    public function analyze_critical_selectors(array $css_analysis, array $fold_elements, string $html): array {
        $recommendations = [
            'critical_selectors' => [],
            'importance_scores' => [],
            'optimization_suggestions' => [],
            'confidence_score' => 0,
        ];
        
        // Analyze each selector
        foreach ($css_analysis['selectors'] as $selector_data) {
            $selector = $selector_data['selector'];
            
            $analysis = $this->analyze_selector(
                $selector_data,
                $fold_elements,
                $css_analysis
            );
            
            $recommendations['critical_selectors'][$selector] = $analysis;
            $recommendations['importance_scores'][$selector] = $analysis['importance_score'];
        }
        
        // Sort by importance
        arsort($recommendations['importance_scores']);
        
        // Generate optimization suggestions
        $recommendations['optimization_suggestions'] = $this->generate_optimization_suggestions(
            $css_analysis,
            $recommendations['critical_selectors']
        );
        
        // Calculate overall confidence score
        $recommendations['confidence_score'] = $this->calculate_confidence_score(
            $recommendations['critical_selectors'],
            $fold_elements
        );
        
        return $recommendations;
    }
    
    /**
     * Analyze individual selector
     *
     * @param array $selector_data Selector data
     * @param array $fold_elements Above-fold elements
     * @param array $css_analysis  Full CSS analysis
     * @return array
     */
    private function analyze_selector(array $selector_data, array $fold_elements, array $css_analysis): array {
        $selector = $selector_data['selector'];
        $score = 0;
        $reasons = [];
        
        // 1. Pattern matching score
        $pattern_score = $this->calculate_pattern_score($selector);
        if ($pattern_score > 0) {
            $score += $pattern_score;
            $reasons[] = 'Matches critical selector pattern';
        }
        
        // 2. Property importance score
        $property_score = $this->calculate_property_score($selector_data['declarations']);
        if ($property_score > 50) {
            $score += $property_score;
            $reasons[] = 'Contains critical CSS properties';
        }
        
        // 3. Above-fold element matching
        $fold_match_score = $this->calculate_fold_match_score($selector, $fold_elements);
        if ($fold_match_score > 0) {
            $score += $fold_match_score;
            $reasons[] = 'Matches above-fold elements';
        }
        
        // 4. Specificity and usage analysis
        $usage_score = $this->calculate_usage_score($selector_data);
        if ($usage_score > 30) {
            $score += $usage_score;
            $reasons[] = 'High usage count and specificity';
        }
        
        // 5. Dependency analysis
        $dependency_score = $this->analyze_dependencies($selector, $css_analysis);
        if ($dependency_score > 0) {
            $score += $dependency_score;
            $reasons[] = 'Required by other critical selectors';
        }
        
        // 6. Media query context
        if ($this->is_critical_media_query($selector, $css_analysis)) {
            $score += 50;
            $reasons[] = 'Part of critical media query';
        }
        
        // Normalize score
        $normalized_score = min(100, $score / 4);
        
        return [
            'is_critical' => $normalized_score > 50,
            'importance_score' => $normalized_score,
            'reasons' => $reasons,
            'properties_analyzed' => count($selector_data['declarations']),
            'recommendation' => $this->get_selector_recommendation($normalized_score),
        ];
    }
    
    /**
     * Calculate pattern matching score
     *
     * @param string $selector CSS selector
     * @return float
     */
    private function calculate_pattern_score(string $selector): float {
        $score = 0;
        
        foreach (self::CRITICAL_PATTERNS as $pattern => $weight) {
            if (preg_match($pattern, $selector)) {
                $score = max($score, $weight);
            }
        }
        
        return $score;
    }
    
    /**
     * Calculate property importance score
     *
     * @param array $declarations CSS declarations
     * @return float
     */
    private function calculate_property_score(array $declarations): float {
        $score = 0;
        $property_count = 0;
        
        foreach ($declarations as $declaration) {
            $property = $declaration['property'];
            
            // Check base property (without vendor prefix)
            $base_property = preg_replace('/^-(?:webkit|moz|ms|o)-/', '', $property);
            
            if (isset(self::CRITICAL_PROPERTIES[$base_property])) {
                $score += self::CRITICAL_PROPERTIES[$base_property];
                $property_count++;
            }
            
            // Bonus for !important declarations
            if ($declaration['important']) {
                $score += 10;
            }
        }
        
        // Average score based on property count
        return $property_count > 0 ? $score / $property_count : 0;
    }
    
    /**
     * Calculate above-fold element matching score
     *
     * @param string $selector      CSS selector
     * @param array  $fold_elements Above-fold elements
     * @return float
     */
    private function calculate_fold_match_score(string $selector, array $fold_elements): float {
        $score = 0;
        $matches = 0;
        
        foreach ($fold_elements as $element) {
            if ($this->selector_matches_element_ai($selector, $element)) {
                $matches++;
                
                // Higher score for more specific matches
                if ($element['id'] && strpos($selector, '#' . $element['id']) !== false) {
                    $score += 30;
                } elseif (!empty($element['classes'])) {
                    foreach ($element['classes'] as $class) {
                        if (strpos($selector, '.' . $class) !== false) {
                            $score += 20;
                            break;
                        }
                    }
                } else {
                    $score += 10;
                }
            }
        }
        
        // Bonus for matching multiple elements
        if ($matches > 1) {
            $score += $matches * 5;
        }
        
        return min(100, $score);
    }
    
    /**
     * Calculate usage score based on selector data
     *
     * @param array $selector_data Selector data
     * @return float
     */
    private function calculate_usage_score(array $selector_data): float {
        $score = 0;
        
        // Usage count contributes to score
        $usage_count = $selector_data['usage_count'] ?? 0;
        if ($usage_count > 0) {
            $score += min(50, $usage_count * 10);
        }
        
        // Specificity indicates importance
        $specificity = $selector_data['specificity'] ?? 0;
        if ($specificity > 100) {
            $score += 20; // ID selector
        } elseif ($specificity > 10) {
            $score += 10; // Class selector
        }
        
        return $score;
    }
    
    /**
     * Analyze selector dependencies
     *
     * @param string $selector     Current selector
     * @param array  $css_analysis CSS analysis data
     * @return float
     */
    private function analyze_dependencies(string $selector, array $css_analysis): float {
        $score = 0;
        
        // Check if this selector is referenced in animations
        foreach ($css_analysis['animations'] as $animation) {
            if ($animation['usage_count'] > 0) {
                foreach ($css_analysis['rules'] as $rule) {
                    if ($rule['selector'] === $selector) {
                        foreach ($rule['declarations'] as $declaration) {
                            if (strpos($declaration['value'], $animation['name']) !== false) {
                                $score += 30;
                                break 2;
                            }
                        }
                    }
                }
            }
        }
        
        // Check if selector defines custom properties used elsewhere
        $defines_vars = false;
        foreach ($css_analysis['rules'] as $rule) {
            if ($rule['selector'] === $selector) {
                foreach ($rule['declarations'] as $declaration) {
                    if (strpos($declaration['property'], '--') === 0) {
                        $defines_vars = true;
                        break;
                    }
                }
            }
        }
        
        if ($defines_vars) {
            $score += 20;
        }
        
        return $score;
    }
    
    /**
     * Check if selector is part of critical media query
     *
     * @param string $selector     CSS selector
     * @param array  $css_analysis CSS analysis data
     * @return bool
     */
    private function is_critical_media_query(string $selector, array $css_analysis): bool {
        foreach ($css_analysis['media_queries'] as $mq) {
            // Check if media query is for small screens (mobile-first critical)
            if (preg_match('/max-width:\s*(\d+)px/', $mq['media'], $matches)) {
                $max_width = intval($matches[1]);
                
                if ($max_width <= 768) {
                    foreach ($mq['rules'] as $rule) {
                        if ($rule['selector'] === $selector) {
                            return true;
                        }
                    }
                }
            }
        }
        
        return false;
    }
    
    /**
     * Enhanced selector matching with AI logic
     *
     * @param string $selector CSS selector
     * @param array  $element  Element data
     * @return bool
     */
    private function selector_matches_element_ai(string $selector, array $element): bool {
        // Direct ID match
        if ($element['id'] && strpos($selector, '#' . $element['id']) !== false) {
            return true;
        }
        
        // Class matching with fuzzy logic
        if (!empty($element['classes'])) {
            foreach ($element['classes'] as $class) {
                // Direct class match
                if (strpos($selector, '.' . $class) !== false) {
                    return true;
                }
                
                // Fuzzy matching for similar classes
                if ($this->fuzzy_class_match($selector, $class)) {
                    return true;
                }
            }
        }
        
        // Tag matching with context
        if (strpos($selector, $element['tag']) !== false) {
            // Check if it's a meaningful match (not just 'div' or 'span')
            if (!in_array($element['tag'], ['div', 'span'], true) || 
                $this->selector_has_context($selector, $element['tag'])) {
                return true;
            }
        }
        
        // Attribute matching
        foreach ($element['attributes'] as $attr => $value) {
            if (strpos($selector, "[{$attr}") !== false) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Fuzzy class matching for similar patterns
     *
     * @param string $selector CSS selector
     * @param string $class    Class name
     * @return bool
     */
    private function fuzzy_class_match(string $selector, string $class): bool {
        // Extract class names from selector
        preg_match_all('/\.([a-zA-Z0-9_-]+)/', $selector, $matches);
        
        if (empty($matches[1])) {
            return false;
        }
        
        foreach ($matches[1] as $selector_class) {
            // Check for common prefixes/suffixes
            if (strpos($selector_class, $class) !== false || 
                strpos($class, $selector_class) !== false) {
                return true;
            }
            
            // Check for similar patterns (e.g., 'btn-primary' matches 'button-primary')
            similar_text($selector_class, $class, $percent);
            if ($percent > 70) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Check if selector has meaningful context
     *
     * @param string $selector CSS selector
     * @param string $tag      Tag name
     * @return bool
     */
    private function selector_has_context(string $selector, string $tag): bool {
        // Check if tag is qualified with class or ID
        return preg_match("/{$tag}[.#]/", $selector) || 
               preg_match("/[.#][^\\s]+\\s+{$tag}/", $selector);
    }
    
    /**
     * Get recommendation for selector
     *
     * @param float $score Importance score
     * @return string
     */
    private function get_selector_recommendation(float $score): string {
        if ($score >= 80) {
            return 'Highly critical - must include';
        } elseif ($score >= 60) {
            return 'Critical - should include';
        } elseif ($score >= 40) {
            return 'Moderately important - consider including';
        } elseif ($score >= 20) {
            return 'Low importance - include if space permits';
        } else {
            return 'Non-critical - safe to defer';
        }
    }
    
    /**
     * Generate optimization suggestions
     *
     * @param array $css_analysis       CSS analysis data
     * @param array $critical_selectors Critical selectors analysis
     * @return array
     */
    private function generate_optimization_suggestions(array $css_analysis, array $critical_selectors): array {
        $suggestions = [];
        
        // Analyze overall critical CSS size
        $critical_count = 0;
        foreach ($critical_selectors as $data) {
            if ($data['is_critical']) {
                $critical_count++;
            }
        }
        
        $critical_percentage = ($critical_count / count($critical_selectors)) * 100;
        
        if ($critical_percentage > 30) {
            $suggestions[] = [
                'type' => 'warning',
                'message' => 'High percentage of CSS marked as critical. Consider refactoring styles.',
                'impact' => 'medium',
            ];
        }
        
        // Check for unused animations
        $unused_animations = 0;
        foreach ($css_analysis['animations'] as $animation) {
            if ($animation['usage_count'] === 0) {
                $unused_animations++;
            }
        }
        
        if ($unused_animations > 0) {
            $suggestions[] = [
                'type' => 'optimization',
                'message' => "Found {$unused_animations} unused animations that can be removed.",
                'impact' => 'high',
            ];
        }
        
        // Check for duplicate rules
        $duplicate_count = $this->count_duplicate_rules($css_analysis['rules']);
        if ($duplicate_count > 10) {
            $suggestions[] = [
                'type' => 'optimization',
                'message' => "Found {$duplicate_count} duplicate CSS rules that can be consolidated.",
                'impact' => 'medium',
            ];
        }
        
        // Font optimization
        if (count($css_analysis['fonts']) > 5) {
            $suggestions[] = [
                'type' => 'performance',
                'message' => 'Consider reducing the number of web fonts for better performance.',
                'impact' => 'high',
            ];
        }
        
        return $suggestions;
    }
    
    /**
     * Count duplicate CSS rules
     *
     * @param array $rules CSS rules
     * @return int
     */
    private function count_duplicate_rules(array $rules): int {
        $seen = [];
        $duplicates = 0;
        
        foreach ($rules as $rule) {
            $key = $rule['selector'] . serialize($rule['declarations']);
            
            if (isset($seen[$key])) {
                $duplicates++;
            } else {
                $seen[$key] = true;
            }
        }
        
        return $duplicates;
    }
    
    /**
     * Calculate confidence score
     *
     * @param array $critical_selectors Critical selectors analysis
     * @param array $fold_elements      Above-fold elements
     * @return float
     */
    private function calculate_confidence_score(array $critical_selectors, array $fold_elements): float {
        $total_score = 0;
        $critical_count = 0;
        
        foreach ($critical_selectors as $data) {
            if ($data['is_critical']) {
                $total_score += $data['importance_score'];
                $critical_count++;
            }
        }
        
        // Base confidence on coverage and accuracy
        $coverage_score = min(100, (count($fold_elements) / 10) * 100);
        $accuracy_score = $critical_count > 0 ? $total_score / $critical_count : 0;
        
        return ($coverage_score + $accuracy_score) / 2;
    }
}