<?php
declare(strict_types=1);

/**
 * Portable Brotli Compressor
 * 
 * Works on any hosting environment without dependencies
 * 
 * @package ProRank\SEO\Modules\Performance
 * @since   2.0.0
 */
namespace ProRank\SEO\Modules\Performance;

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


/**
 * Smart compression with automatic fallback
 */


class BrotliCompressor {
    
    /**
     * Available compression methods
     */
    private static $capabilities = null;
    
    /**
     * Detect available compression methods
     * 
     * @return array
     */
    public static function detect_capabilities(): array {
        if (self::$capabilities !== null) {
            return self::$capabilities;
        }
        
        self::$capabilities = [
            'brotli_php' => false,
            'gzip' => true, // Always available in PHP
        ];
        
        // Check PHP Brotli extension
        if (function_exists('brotli_compress')) {
            self::$capabilities['brotli_php'] = true;
        }
        
        return self::$capabilities;
    }
    
    /**
     * Compress content using best available method
     * 
     * @param string $content Content to compress
     * @param string $method  Preferred method (auto, brotli, gzip)
     * @return array ['data' => compressed data, 'encoding' => 'br'|'gzip'|'none']
     */
    public static function compress(string $content, string $method = 'auto'): array {
        $caps = self::detect_capabilities();
        
        // If specific method requested
        if ($method === 'brotli') {
            $result = self::try_brotli($content, $caps);
            if ($result['success']) {
                return ['data' => $result['data'], 'encoding' => 'br'];
            }
            // Fall back to gzip if brotli fails
        }
        
        if ($method === 'gzip' || $method === 'auto') {
            $compressed = gzencode($content, 9);
            if ($compressed !== false) {
                return ['data' => $compressed, 'encoding' => 'gzip'];
            }
        }
        
        // No compression available
        return ['data' => $content, 'encoding' => 'none'];
    }
    
    /**
     * Try Brotli compression
     *
     * @param string $content Content to compress
     * @param array  $caps    Capabilities
     * @return array ['success' => bool, 'data' => string]
     */
    private static function try_brotli(string $content, array $caps): array {
        try {
            // Try PHP extension first (fastest)
            if ($caps['brotli_php']) {
                $compressed = @brotli_compress($content, 11);
                if ($compressed !== false) {
                    return ['success' => true, 'data' => $compressed];
                }
            }

        } catch (\Throwable $e) {
            prorank_log('ProRank SEO: Brotli compression failed - ' . $e->getMessage());
            return ['success' => false, 'data' => ''];
        }

        return ['success' => false, 'data' => ''];
    }
    
    /**
     * Get best compression for browser
     * 
     * @param string $accept_encoding Browser Accept-Encoding header
     * @return string 'br', 'gzip', or 'none'
     */
    public static function get_best_encoding(string $accept_encoding = ''): string {
        if (empty($accept_encoding)) {
            $accept_encoding = prorank_get_server_var('HTTP_ACCEPT_ENCODING');
        }
        
        $caps = self::detect_capabilities();
        
        // Check if browser supports Brotli and we can provide it
        if (strpos($accept_encoding, 'br') !== false && 
            $caps['brotli_php']) {
            return 'br';
        }
        
        // Check gzip support
        if (strpos($accept_encoding, 'gzip') !== false) {
            return 'gzip';
        }
        
        return 'none';
    }
    
    /**
     * Get compression stats for admin display
     * 
     * @return array
     */
    public static function get_compression_info(): array {
        $caps = self::detect_capabilities();
        
        $info = [
            'best_available' => 'Gzip',
            'methods' => [],
            'recommendation' => '',
        ];
        
        if ($caps['brotli_php']) {
            $info['best_available'] = 'Brotli (PHP Extension)';
            $info['methods'][] = 'Brotli via PHP extension (Best)';
        } elseif ($caps['brotli_exec']) {
            $info['best_available'] = 'Brotli (System)';
            $info['methods'][] = 'Brotli via system command (Good)';
        }
        
        $info['methods'][] = 'Gzip compression (Always available)';
        
        // Add recommendations
        if (!$caps['brotli_php'] && !$caps['brotli_exec']) {
            $info['recommendation'] = 'For 20-30% better compression, ask your host to install the PHP Brotli extension.';
        } else {
            $info['recommendation'] = 'Optimal compression available! Brotli provides 20-30% better compression than Gzip.';
        }
        
        return $info;
    }
    
    /**
     * Compress and save cache file
     *
     * @param string $file_path Base file path
     * @param string $content   Content to cache
     * @param array  $options   Compression options
     * @return array Files created
     */
    public static function save_compressed_cache(string $file_path, string $content, array $options = []): array {
        $files_created = [];

        try {
            // Always save uncompressed version
            if (file_put_contents($file_path, $content) !== false) {
                $files_created[] = $file_path;
            }

            $compression = $options['compression'] ?? 'both';

            // Save Gzip version
            if ($compression === 'gzip' || $compression === 'both') {
                $gzipped = self::compress($content, 'gzip');
                if ($gzipped['encoding'] === 'gzip') {
                    if (file_put_contents($file_path . '.gz', $gzipped['data']) !== false) {
                        $files_created[] = $file_path . '.gz';
                    }
                }
            }

            // Save Brotli version (if available)
            if ($compression === 'brotli' || $compression === 'both') {
                $brotlied = self::compress($content, 'brotli');
                if ($brotlied['encoding'] === 'br') {
                    if (file_put_contents($file_path . '.br', $brotlied['data']) !== false) {
                        $files_created[] = $file_path . '.br';
                    }
                }
            }
        } catch (\Throwable $e) {
            prorank_log('ProRank SEO: Failed to save compressed cache - ' . $e->getMessage());
        }

        return $files_created;
    }
    
    /**
     * Benchmark compression methods
     * 
     * @param string $content Sample content
     * @return array Benchmark results
     */
    public static function benchmark(string $content = ''): array {
        if (empty($content)) {
            // Use sample HTML if none provided
            $content = str_repeat('<div class="test">Sample HTML content for compression testing</div>', 100);
        }
        
        $original_size = strlen($content);
        $results = [
            'original_size' => $original_size,
            'methods' => [],
        ];
        
        // Test Gzip
        $start = microtime(true);
        $gzipped = self::compress($content, 'gzip');
        $gzip_time = (microtime(true) - $start) * 1000;
        $gzip_size = strlen($gzipped['data']);
        
        $results['methods']['gzip'] = [
            'size' => $gzip_size,
            'ratio' => round((1 - $gzip_size / $original_size) * 100, 2) . '%',
            'time' => round($gzip_time, 2) . 'ms',
            'available' => true,
        ];
        
        // Test Brotli
        $caps = self::detect_capabilities();
        if ($caps['brotli_php'] || $caps['brotli_exec']) {
            $start = microtime(true);
            $brotlied = self::compress($content, 'brotli');
            $brotli_time = (microtime(true) - $start) * 1000;
            
            if ($brotlied['encoding'] === 'br') {
                $brotli_size = strlen($brotlied['data']);
                $results['methods']['brotli'] = [
                    'size' => $brotli_size,
                    'ratio' => round((1 - $brotli_size / $original_size) * 100, 2) . '%',
                    'time' => round($brotli_time, 2) . 'ms',
                    'available' => true,
                    'method' => $caps['brotli_php'] ? 'PHP Extension' : 'System Binary',
                ];
                
                // Compare to gzip
                $results['brotli_vs_gzip'] = round((1 - $brotli_size / $gzip_size) * 100, 2) . '% smaller than Gzip';
            }
        } else {
            $results['methods']['brotli'] = [
                'available' => false,
                'message' => 'Brotli not available on this server',
            ];
        }
        
        return $results;
    }
}
