<?php

/**
 * CSS Cache Server
 *
 * Handles serving cached CSS files with proper headers
 *
 * @package ProRank\SEO\Core\Optimization\CSS
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\Optimization\CSS;

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


/**
 * CssCacheServer class
 */


class CssCacheServer {
    
    /**
     * Initialize the cache server
     *
     * @return void
     */
    public function init(): void {
        // Hook into init to check for cache requests
        add_action('init', [$this, 'serve_cached_css'], 1);
        
        // Add rewrite rules
        add_action('init', [$this, 'add_rewrite_rules']);
        
        // Filter upload directory structure
        add_filter('upload_dir', [$this, 'filter_upload_dir']);
    }
    
    /**
     * Serve cached CSS files
     *
     * @return void
     */
    public function serve_cached_css(): void {
        // Check if this is a cache request
        $request_uri = prorank_get_server_var('REQUEST_URI');
        if ($request_uri === '') {
            return;
        }

        $cache_pattern = '/prorank-cache/css/';
        
        if (strpos($request_uri, $cache_pattern) === false) {
            return;
        }
        
        // Extract filename
        $parts = explode($cache_pattern, $request_uri);
        if (count($parts) < 2) {
            return;
        }
        
        $filename = basename($parts[1]);
        $cache_dir = wp_upload_dir()['basedir'] . '/prorank-cache/css/';
        $file_path = $cache_dir . $filename;
        
        // Validate filename (security check)
        if (!preg_match('/^[a-f0-9]{32}\.(?:min\.)?css(?:\.gz)?$/', $filename)) {
            return;
        }
        
        // Check if file exists
        if (!file_exists($file_path)) {
            return;
        }
        
        // Serve the file
        $this->serve_css_file($file_path);
        exit;
    }
    
    /**
     * Serve CSS file with proper headers
     *
     * @param string $file_path Path to CSS file
     * @return void
     */
    private function serve_css_file(string $file_path): void {
        $is_gzipped = substr($file_path, -3) === '.gz';
        $content = file_get_contents($file_path);
        
        if ($content === false) {
            http_response_code(404);
            exit;
        }
        
        // Set headers
        header('Content-Type: text/css; charset=utf-8');
        
        // Cache headers (30 days)
        $expires = 30 * DAY_IN_SECONDS;
        header('Cache-Control: public, max-age=' . $expires);
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
        
        // ETag
        $etag = '"' . md5($content) . '"';
        header('ETag: ' . $etag);
        
        // Check if-none-match
        if (prorank_get_server_var('HTTP_IF_NONE_MATCH') === $etag) {
            http_response_code(304);
            exit;
        }
        
        // Gzip encoding
        if ($is_gzipped && $this->accepts_gzip()) {
            header('Content-Encoding: gzip');
            header('Vary: Accept-Encoding');
        } elseif ($is_gzipped) {
            // Decompress for clients that don't support gzip
            $content = gzdecode($content);
            if ($content === false) {
                http_response_code(500);
                exit;
            }
        }
        
        // Content length
        header('Content-Length: ' . strlen($content));
        
        // CORS headers (if needed)
        $this->add_cors_headers();
        
        // Output content
        // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- serving cached CSS content
        echo $content;
    }
    
    /**
     * Check if client accepts gzip
     *
     * @return bool
     */
    private function accepts_gzip(): bool {
        $accept_encoding = prorank_get_server_var('HTTP_ACCEPT_ENCODING');
        if ($accept_encoding === '') {
            return false;
        }

        return strpos($accept_encoding, 'gzip') !== false;
    }
    
    /**
     * Add CORS headers if needed
     *
     * @return void
     */
    private function add_cors_headers(): void {
        // Check if CORS is needed (e.g., for CDN setup)
        $settings = get_option('prorank_css_optimize_settings', []);
        
        if (!empty($settings['css_cors_enabled'])) {
            $allowed_origins = $settings['css_cors_origins'] ?? '*';
            header('Access-Control-Allow-Origin: ' . $allowed_origins);
            header('Access-Control-Allow-Methods: GET, OPTIONS');
            header('Access-Control-Max-Age: 86400');
        }
    }
    
    /**
     * Add rewrite rules for pretty URLs
     *
     * @return void
     */
    public function add_rewrite_rules(): void {
        // Add rewrite rule for cache URLs
        add_rewrite_rule(
            '^prorank-cache/css/([a-f0-9]{32}\.(?:min\.)?css(?:\.gz)?)$',
            'index.php?prorank_css_cache=$1',
            'top'
        );
    }
    
    /**
     * Filter upload directory for cache files
     *
     * @param array $uploads Upload directory info
     * @return array
     */
    public function filter_upload_dir(array $uploads): array {
        // Only filter for our cache directory
        if (strpos($uploads['path'], '/prorank-cache/') !== false) {
            // Ensure directory is not date-based
            $uploads['path'] = str_replace($uploads['subdir'], '/prorank-cache/css', $uploads['path']);
            $uploads['url'] = str_replace($uploads['subdir'], '/prorank-cache/css', $uploads['url']);
            $uploads['subdir'] = '/prorank-cache/css';
        }
        
        return $uploads;
    }
    
    /**
     * Get cache URL for a file
     *
     * @param string $filename Cache filename
     * @return string
     */
    public static function get_cache_url(string $filename): string {
        $upload_dir = wp_upload_dir();

        $filename = basename($filename);
        $baseurl = isset($upload_dir['baseurl']) && is_string($upload_dir['baseurl'])
            ? trailingslashit($upload_dir['baseurl'])
            : trailingslashit(content_url('uploads'));

        // Pretty cache URLs are optional because many nginx setups do not route
        // /prorank-cache/* requests through WordPress, which causes 404s.
        $use_pretty_urls = (bool) apply_filters('prorank_css_cache_use_pretty_urls', false, $filename);
        if ($use_pretty_urls && get_option('permalink_structure')) {
            return home_url('/prorank-cache/css/' . $filename);
        }

        // Default to direct uploads URL for maximum compatibility.
        return $baseurl . 'prorank-cache/css/' . $filename;
    }
}
