<?php
/**
 * CDN CORS Handler
 * Adds proper CORS headers for fonts and static assets
 * Fixes 404 errors and cross-origin issues
 */

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

class USCDN_CORS_Handler {
    
    private static $instance = null;
    
    public static function get_instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        $this->init_hooks();
    }
    
    /**
     * Initialize hooks
     */
    private function init_hooks() {
        // Add CORS headers - use send_headers hook which runs after init
        add_action('send_headers', [$this, 'add_cors_headers'], 1);
        
        // Also add to template_redirect for frontend requests
        add_action('template_redirect', [$this, 'add_cors_headers'], 1);
        
        // Fix font MIME types
        add_filter('upload_mimes', [$this, 'add_font_mimes']);
        add_filter('wp_check_filetype_and_ext', [$this, 'fix_font_mime_type'], 10, 4);
        
        // Add cache directory .htaccess - runs after WordPress is fully loaded
        add_action('wp_loaded', [$this, 'ensure_cache_htaccess']);
        
        // Add rewrite rules after init
        add_action('init', [$this, 'add_rewrite_rules']);
        add_filter('query_vars', [$this, 'add_query_vars']);
        add_action('template_redirect', [$this, 'handle_font_request']);
    }
    
    /**
     * Add CORS headers for cross-origin requests
     */
    public function add_cors_headers() {
        // Ensure WordPress functions are available
        if (!function_exists('home_url') || !function_exists('get_option')) {
            return;
        }
        
        // Get all configured domains
        $configured_domains = $this->get_all_configured_domains();
        
        // Get current host
        $current_host = $_SERVER['HTTP_HOST'] ?? '';
        $home_url = home_url();
        $main_host = $home_url ? parse_url($home_url, PHP_URL_HOST) : '';
        
        // Check if we're on any configured subdomain/domain
        $is_alt_domain = false;
        foreach ($configured_domains as $domain) {
            $domain_host = parse_url($domain, PHP_URL_HOST);
            if ($domain_host && strcasecmp($current_host, $domain_host) === 0) {
                $is_alt_domain = true;
                break;
            }
        }
        
        // Add CORS headers if on alternative domain OR accessing static assets
        if ($is_alt_domain || ($main_host && strcasecmp($current_host, $main_host) !== 0)) {
            $this->send_cors_headers();
        }
        
        // Always add CORS for font files and static assets
        $request_uri = $_SERVER['REQUEST_URI'] ?? '';
        if ($this->is_static_asset($request_uri) || $this->is_font_file($request_uri)) {
            $this->send_cors_headers();
        }
    }
    
    /**
     * Get all configured domains from plugin settings
     */
    private function get_all_configured_domains() {
        $domains = [];
        
        // Origin URL
        if (get_option('uscdn_enable_origin_url')) {
            $origin_url = get_option('uscdn_origin_url', '');
            if ($origin_url) {
                $domains[] = $origin_url;
            }
        }
        
        // Admin URL
        if (get_option('uscdn_enable_admin_url')) {
            $admin_url = get_option('uscdn_admin_url', '');
            if ($admin_url) {
                $domains[] = $admin_url;
            }
        }
        
        // Image CDN
        if (get_option('uscdn_enable_image_cdn')) {
            $image_cdn = get_option('uscdn_cdn_image_base', '');
            if ($image_cdn) {
                $domains[] = $image_cdn;
            }
        }
        
        // Static CDN
        if (get_option('uscdn_enable_static_cdn')) {
            $static_cdn = get_option('uscdn_cdn_static_base', '');
            if ($static_cdn) {
                $domains[] = $static_cdn;
            }
        }
        
        // Link CDN
        if (get_option('uscdn_enable_link_cdn')) {
            $link_cdn = get_option('uscdn_cdn_link_base', '');
            if ($link_cdn) {
                $domains[] = $link_cdn;
            }
        }
        
        return $domains;
    }
    
    /**
     * Send CORS headers
     */
    private function send_cors_headers() {
        if (headers_sent()) {
            return;
        }
        
        // Ensure WordPress functions are available
        if (!function_exists('home_url')) {
            // Fallback: just use wildcard if WordPress not ready
            header('Access-Control-Allow-Origin: *');
            header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
            header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, X-Cache-Flush');
            header('Access-Control-Allow-Credentials: false');
            header('Access-Control-Max-Age: 86400');
            
            if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
                status_header(200);
                exit;
            }
            return;
        }
        
        // Get origin from request
        $origin = $_SERVER['HTTP_ORIGIN'] ?? '';
        
        // Get all configured domains
        $configured_domains = $this->get_all_configured_domains();
        $home_url = home_url();
        $allowed_origins = $home_url ? array_merge($configured_domains, [$home_url]) : $configured_domains;
        
        // Check if origin is allowed
        $origin_allowed = false;
        foreach ($allowed_origins as $allowed_url) {
            if (!$allowed_url) continue;
            
            $allowed_host = parse_url($allowed_url, PHP_URL_HOST);
            $origin_host = parse_url($origin, PHP_URL_HOST);
            
            if ($allowed_host && $origin_host && strcasecmp($allowed_host, $origin_host) === 0) {
                $origin_allowed = true;
                break;
            }
        }
        
        // If origin is in our list, use it; otherwise use wildcard for CDN compatibility
        if ($origin_allowed && $origin) {
            header('Access-Control-Allow-Origin: ' . $origin);
            header('Vary: Origin');
        } else {
            // Fallback to wildcard for maximum CDN compatibility
            header('Access-Control-Allow-Origin: *');
        }
        
        header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
        header('Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With, X-Cache-Flush');
        header('Access-Control-Allow-Credentials: false');
        header('Access-Control-Max-Age: 86400'); // 24 hours
        
        // Handle preflight OPTIONS request
        if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
            status_header(200);
            exit;
        }
    }
    
    /**
     * Check if request is for a static asset
     */
    private function is_static_asset($uri) {
        $static_extensions = [
            'css', 'js', 'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg',
            'woff', 'woff2', 'ttf', 'otf', 'eot',
            'ico', 'pdf', 'zip', 'mp4', 'mp3'
        ];
        
        $ext = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
        return in_array($ext, $static_extensions);
    }
    
    /**
     * Check if request is for a font file
     */
    private function is_font_file($uri) {
        $font_extensions = ['woff', 'woff2', 'ttf', 'otf', 'eot', 'svg'];
        $ext = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
        return in_array($ext, $font_extensions);
    }
    
    /**
     * Add font MIME types
     */
    public function add_font_mimes($mimes) {
        $mimes['woff'] = 'font/woff';
        $mimes['woff2'] = 'font/woff2';
        $mimes['ttf'] = 'font/ttf';
        $mimes['otf'] = 'font/otf';
        $mimes['eot'] = 'application/vnd.ms-fontobject';
        $mimes['svg'] = 'image/svg+xml';
        
        return $mimes;
    }
    
    /**
     * Fix font MIME type detection
     */
    public function fix_font_mime_type($data, $file, $filename, $mimes) {
        $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        
        $font_mimes = [
            'woff' => 'font/woff',
            'woff2' => 'font/woff2',
            'ttf' => 'font/ttf',
            'otf' => 'font/otf',
            'eot' => 'application/vnd.ms-fontobject',
        ];
        
        if (isset($font_mimes[$ext])) {
            $data['ext'] = $ext;
            $data['type'] = $font_mimes[$ext];
            $data['proper_filename'] = $filename;
        }
        
        return $data;
    }
    
    /**
     * Add rewrite rules for fonts and static assets
     */
    public function add_rewrite_rules() {
        // No special rewrite rules needed - fonts served from their original locations
        // CORS headers are added via send_headers hook
    }
    
    /**
     * Add query vars
     */
    public function add_query_vars($vars) {
        // No custom query vars needed
        return $vars;
    }
    
    /**
     * Handle font file requests
     * Note: This is intentionally a no-op as fonts are served from original locations
     */
    public function handle_font_request() {
        // Fonts are served directly from their original locations (theme/plugin directories)
        // with CORS headers added via send_headers hook
        return;
    }
    
    /**
     * Ensure cache directories have proper .htaccess
     */
    public function ensure_cache_htaccess() {
        // Ensure WordPress constants are defined
        if (!defined('WP_CONTENT_DIR')) {
            return;
        }
        
        // Add .htaccess to wp-content root for CORS on all fonts
        $this->ensure_wp_content_htaccess();
        
        // Add .htaccess for CSS cache directory
        $cache_dirs = [
            WP_CONTENT_DIR . '/cache/uscdn-css'
        ];
        
        foreach ($cache_dirs as $dir) {
            try {
                if (!is_dir($dir)) {
                    wp_mkdir_p($dir);
                }
                
                $htaccess_file = $dir . '/.htaccess';
                
                if (!file_exists($htaccess_file)) {
                    $htaccess_content = $this->get_htaccess_content();
                    @file_put_contents($htaccess_file, $htaccess_content);
                }
            } catch (Exception $e) {
                // Silently fail - not critical
                continue;
            }
        }
    }
    
    /**
     * Ensure wp-content directory has CORS headers for fonts
     */
    private function ensure_wp_content_htaccess() {
        $htaccess_file = WP_CONTENT_DIR . '/.htaccess';
        
        // Check if .htaccess exists
        $existing_content = '';
        if (file_exists($htaccess_file)) {
            $existing_content = @file_get_contents($htaccess_file);
            
            // Check if our CORS rules already exist
            if (strpos($existing_content, '# Utility Server CDN - CORS Headers') !== false) {
                return; // Already added
            }
        }
        
        // Add CORS headers for fonts and static assets
        $cors_rules = "\n\n# Utility Server CDN - CORS Headers\n";
        $cors_rules .= "<IfModule mod_headers.c>\n";
        $cors_rules .= "    # Add CORS headers for font files\n";
        $cors_rules .= "    <FilesMatch \"\.(woff|woff2|ttf|otf|eot|svg)$\">\n";
        $cors_rules .= "        Header set Access-Control-Allow-Origin \"*\"\n";
        $cors_rules .= "        Header set Access-Control-Allow-Methods \"GET, OPTIONS\"\n";
        $cors_rules .= "        Header set Access-Control-Allow-Headers \"Content-Type\"\n";
        $cors_rules .= "    </FilesMatch>\n";
        $cors_rules .= "    \n";
        $cors_rules .= "    # Add CORS headers for CSS and JS files\n";
        $cors_rules .= "    <FilesMatch \"\.(css|js)$\">\n";
        $cors_rules .= "        Header set Access-Control-Allow-Origin \"*\"\n";
        $cors_rules .= "        Header set Access-Control-Allow-Methods \"GET, OPTIONS\"\n";
        $cors_rules .= "        Header set Access-Control-Allow-Headers \"Content-Type\"\n";
        $cors_rules .= "    </FilesMatch>\n";
        $cors_rules .= "</IfModule>\n";
        $cors_rules .= "\n";
        $cors_rules .= "# Font MIME types\n";
        $cors_rules .= "<IfModule mod_mime.c>\n";
        $cors_rules .= "    AddType font/woff .woff\n";
        $cors_rules .= "    AddType font/woff2 .woff2\n";
        $cors_rules .= "    AddType font/ttf .ttf\n";
        $cors_rules .= "    AddType font/otf .otf\n";
        $cors_rules .= "    AddType application/vnd.ms-fontobject .eot\n";
        $cors_rules .= "</IfModule>\n";
        
        // Append to existing content or create new
        $new_content = $existing_content . $cors_rules;
        
        // Write the file
        @file_put_contents($htaccess_file, $new_content);
    }
    
    /**
     * Get .htaccess content for cache directories
     */
    private function get_htaccess_content() {
        return <<<HTACCESS
# Utility Server CDN - Cache Directory
# Enable direct file access and CORS

<IfModule mod_headers.c>
    # CORS headers for all files
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "GET, OPTIONS"
    Header set Access-Control-Allow-Headers "Content-Type"
    
    # Cache headers
    Header set Cache-Control "public, max-age=31536000"
</IfModule>

# Font MIME types
<IfModule mod_mime.c>
    AddType font/woff .woff
    AddType font/woff2 .woff2
    AddType font/ttf .ttf
    AddType font/otf .otf
    AddType application/vnd.ms-fontobject .eot
    AddType image/svg+xml .svg
</IfModule>

# Enable file access
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
</IfModule>

# Allow from all
<IfModule mod_authz_core.c>
    Require all granted
</IfModule>
<IfModule !mod_authz_core.c>
    Order allow,deny
    Allow from all
</IfModule>

# Enable compression
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE font/woff
    AddOutputFilterByType DEFLATE font/woff2
</IfModule>
HTACCESS;
    }
}
