<?php
/**
 * CDN Cache Management
 * Handles CSS caching and cache clearing with custom header support
 */

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

class USCDN_Cache {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        if (USCDN_Settings::get('cache_enabled', 1)) {
            add_filter('style_loader_src', [$this, 'css_rewrite_proxy'], 8, 1);
        }
        
        // Add cache flush header support
        add_action('init', [$this, 'maybe_send_cache_flush_header']);
    }
    
    /**
     * CSS Rewrite and Cache Proxy
     */
    public function css_rewrite_proxy($src) {
        $origin = $this->get_origin();
        $p = @parse_url($src);
        $path = $p['path'] ?? '';
        
        if (!$path || !preg_match('/\.css($|\?)/i', $src)) {
            return $src;
        }
        
        // Resolve to absolute
        if (empty($p['host'])) {
            if (str_starts_with($src, '//')) {
                $src = $origin['scheme'] . ltrim($src, '/');
            }
            if (str_starts_with($src, '/')) {
                $src = $origin['full'] . $src;
            }
            $p = @parse_url($src);
            $path = $p['path'] ?? $path;
        }
        
        // Only process source hosts
        $url_host = $p['host'] ?? '';
        if (!$this->is_from_source_host($url_host)) {
            return $src;
        }
        
        // Avoid loops on cached files
        if (str_contains($path, '/wp-content/cache/uscdn-css/')) {
            return $src;
        }
        
        // Map to filesystem
        $abs_path = ABSPATH . ltrim($path, '/');
        if (!file_exists($abs_path) || !is_readable($abs_path)) {
            return $src;
        }
        
        $css = @file_get_contents($abs_path);
        if ($css === false || $css === '') {
            return $src;
        }
        
        // Rewrite URLs in CSS (pass the original path to resolve relative URLs)
        $css = $this->rewrite_css_urls($css, $path);
        
        // Cache the rewritten CSS
        $cached_url = $this->cache_css($css, $src, $abs_path);
        
        return $cached_url ? $cached_url : $src;
    }
    
    /**
     * Rewrite URLs inside CSS content
     */
    private function rewrite_css_urls($css, $css_path = '') {
        $bases = USCDN_Settings::get_cdn_bases();
        $hosts = USCDN_Settings::get_source_hosts();
        
        if (empty($hosts)) {
            return $css;
        }
        
        // Convert relative URLs to absolute URLs FIRST
        if ($css_path) {
            $css = $this->resolve_relative_urls($css, $css_path);
        }
        
        $host_alt = implode('|', array_map(fn($h) => preg_quote($h, '/'), $hosts));
        
        // 1) Replace absolute URLs
        $css = preg_replace_callback(
            '/https?:\/\/(' . $host_alt . ')\/[^\s"\')]+/i',
            function($m) {
                $replacer = USCDN_Replacer::get_instance();
                return $replacer->replace_url($m[0]);
            },
            $css
        );
        
        // 2) Replace protocol-relative URLs
        $css = preg_replace_callback(
            '/\/\/(' . $host_alt . ')\/[^\s"\')]+/i',
            function($m) {
                $abs = (is_ssl() ? 'https:' : 'http:') . '//' . $m[1] . substr($m[0], strlen('//' . $m[1]));
                $replacer = USCDN_Replacer::get_instance();
                return $replacer->replace_url($abs);
            },
            $css
        );
        
        // 3) Replace url(/wp-content/uploads/...) → Image CDN
        if (USCDN_Settings::get('enable_image_cdn') && !empty($bases['img'])) {
            $css = preg_replace(
                '/url\((["\']?)(\/wp-content\/uploads\/[^"\')]+)\1\)/i',
                'url($1' . $bases['img'] . '$2$1)',
                $css
            );
        }
        
        // 4) Replace url(/wp-{content|includes}/...) → Static CDN
        if (USCDN_Settings::get('enable_static_cdn') && !empty($bases['static'])) {
            $css = preg_replace(
                '/url\((["\']?)(\/wp-(content|includes)\/[^"\')]+)\1\)/i',
                'url($1' . $bases['static'] . '$2$1)',
                $css
            );
        }
        
        return $css;
    }
    /**
     * Resolve relative URLs in CSS to absolute URLs
     * This prevents relative paths from breaking when CSS is cached
     */
    private function resolve_relative_urls($css, $css_path) {
        // Get the directory of the CSS file
        $css_dir = dirname($css_path);
        
        // Match all url() declarations with relative paths
        $css = preg_replace_callback(
            '/url\((["\']?)([^"\')]+)\1\)/i',
            function($matches) use ($css_dir) {
                $quote = $matches[1];
                $url = $matches[2];
                
                // Skip if already absolute (starts with http://, https://, //, or /)
                if (preg_match('/^(https?:)?\/\//i', $url) || str_starts_with($url, '/')) {
                    return $matches[0];
                }
                
                // Skip data URLs
                if (str_starts_with($url, 'data:')) {
                    return $matches[0];
                }
                
                // Resolve relative path
                $absolute_path = $this->resolve_path($css_dir . '/' . $url);
                
                // Convert to absolute URL
                return 'url(' . $quote . $absolute_path . $quote . ')';
            },
            $css
        );
        
        return $css;
    }
    
    /**
     * Resolve a file path (handle ../ and ./)
     */
    private function resolve_path($path) {
        // Normalize slashes
        $path = str_replace('\\', '/', $path);
        
        // Split path into parts
        $parts = explode('/', $path);
        $resolved = [];
        
        foreach ($parts as $part) {
            if ($part === '' || $part === '.') {
                continue;
            }
            if ($part === '..') {
                array_pop($resolved);
            } else {
                $resolved[] = $part;
            }
        }
        
        return '/' . implode('/', $resolved);
    }

    
    /**
     * Cache rewritten CSS
     */
    private function cache_css($css, $original_url, $abs_path) {
        $cache_dir = WP_CONTENT_DIR . '/cache/uscdn-css';
        if (!is_dir($cache_dir)) {
            wp_mkdir_p($cache_dir);
        }
        
        $bases = USCDN_Settings::get_cdn_bases();
        $p = parse_url($original_url);
        
        $ver = '';
        if (!empty($p['query'])) {
            parse_str($p['query'], $q);
            $ver = isset($q['ver']) ? (string)$q['ver'] : '';
        }
        
        $hash = md5($original_url . '|' . @filemtime($abs_path) . '|' . serialize($bases) . '|' . $ver);
        $filename = basename($p['path'] ?? 'style.css');
        $cached_name = preg_replace('/\.css$/i', '', $filename) . ".{$hash}.css";
        $cached_path = $cache_dir . '/' . $cached_name;
        
        if (!file_exists($cached_path)) {
            @file_put_contents($cached_path, $css);
        }
        
        return content_url('cache/uscdn-css/' . $cached_name);
    }
    
    /**
     * Clear all cached CSS files
     */
    public static function clear_all_cache() {
        $cache_dir = WP_CONTENT_DIR . '/cache/uscdn-css';
        if (!is_dir($cache_dir)) {
            return true;
        }
        
        $files = glob($cache_dir . '/*.css');
        if ($files) {
            foreach ($files as $file) {
                if (is_file($file)) {
                    @unlink($file);
                }
            }
        }
        
        return true;
    }
    
    /**
     * Send cache flush header when clearing cache
     */
    public function maybe_send_cache_flush_header() {
        // Check if this is a cache clear request
        if (isset($_GET['uscdn_clear_cache']) && current_user_can('manage_options')) {
            check_admin_referer('uscdn_clear_cache');
            
            // Clear cache
            self::clear_all_cache();
            
            // Send custom header
            if (!headers_sent()) {
                header('X-Cache-Flush: TRUE');
            }
            
            // Redirect back
            wp_safe_redirect(admin_url('admin.php?page=uscdn-settings&cache_cleared=1'));
            exit;
        }
    }
    
    /**
     * Helper methods
     */
    private function get_origin() {
        $host = $_SERVER['HTTP_HOST'] ?? '';
        $scheme = is_ssl() ? 'https://' : 'http://';
        return [
            'full' => $scheme . $host,
            'host' => $host,
            'scheme' => $scheme
        ];
    }
    
    private function is_from_source_host($url_host) {
        if (empty($url_host)) {
            return true;
        }
        
        $sources = USCDN_Settings::get_source_hosts();
        foreach ($sources as $h) {
            if (strcasecmp($h, $url_host) === 0) {
                return true;
            }
        }
        return false;
    }
}
