<?php

namespace Mamba\Modules\Media\Services;

final class HtaccessManager {
    
    private const HTACCESS_MARKER = '# BEGIN Mamba Next-Gen Support';
    private const HTACCESS_END_MARKER = '# END Mamba Next-Gen Support';
    
    public function __construct() {}
    
    /**
     * Add Next-Gen (AVIF/WebP) serving rules to .htaccess
     */
    public function addNextGenRules(): bool {
        if (!$this->isSupported()) {
            return false;
        }
        
        $htaccessPath = $this->getHtaccessPath();
        if (!$htaccessPath) {
            return false;
        }
        
        $rules = $this->getNextGenRules();
        $currentContent = $this->readHtaccess($htaccessPath);
        
        // Remove old markers if they exist to prevent duplicates
        $pattern = '/\s*# BEGIN Mamba (?:Support|Rules|WebP Support|WebP Rules|Next-Gen Support).*?# END Mamba (?:Support|Rules|WebP Support|WebP Rules|Next-Gen Support)\s*/s';
        $currentContent = preg_replace($pattern, '', $currentContent);
        
        // Add rules to .htaccess
        $newContent = trim($currentContent) . "\n\n" . $rules . "\n";
        $result = $this->writeHtaccess($htaccessPath, $newContent);
        
        return $result;
    }

    /**
     * Compatibility alias
     */
    public function addWebPRules(): bool {
        return $this->addNextGenRules();
    }
    
    /**
     * Remove Next-Gen serving rules from .htaccess
     */
    public function removeNextGenRules(): bool {
        if (!$this->isSupported()) {
            return false;
        }
        
        $htaccessPath = $this->getHtaccessPath();
        if (!$htaccessPath) {
            return false;
        }
        
        $currentContent = $this->readHtaccess($htaccessPath);
        
        // Remove Next-Gen rules section
        $pattern = '/\s*# BEGIN Mamba (?:Support|Rules|WebP Support|WebP Rules|Next-Gen Support).*?# END Mamba (?:Support|Rules|WebP Support|WebP Rules|Next-Gen Support)\s*/s';
        $newContent = preg_replace($pattern, '', $currentContent);
        
        if ($newContent !== $currentContent) {
            $result = $this->writeHtaccess($htaccessPath, $newContent);
            return $result;
        }
        
        return true;
    }

    /**
     * Compatibility alias
     */
    public function removeWebPRules(): bool {
        return $this->removeNextGenRules();
    }
    
    /**
     * Check if Next-Gen rules are present in .htaccess
     */
    public function hasNextGenRules(): bool {
        $htaccessPath = $this->getHtaccessPath();
        if (!$htaccessPath || !file_exists($htaccessPath)) {
            return false;
        }
        
        $content = file_get_contents($htaccessPath);
        return (strpos($content, self::HTACCESS_MARKER) !== false);
    }

    /**
     * Compatibility alias
     */
    public function hasWebPRules(): bool {
        return $this->hasNextGenRules();
    }
    
    /**
     * Get .htaccess file path
     */
    private function getHtaccessPath(): ?string {
        $htaccessPath = ABSPATH . '.htaccess';
        
        if (!file_exists($htaccessPath)) {
            // Try to create a blank .htaccess rather than silently failing
            if (@touch($htaccessPath) === false) {
                return null;
            }
        }
        
        if (!is_writable($htaccessPath)) {
            return null;
        }
        
        return $htaccessPath;
    }
    
    /**
     * Get Next-Gen (AVIF/WebP) .htaccess rules
     */
    private function getNextGenRules(): string {
        $enableWebP = get_option('mamba_enable_webp_conversion', 0);
        $enableAvif = get_option('mamba_enable_avif_conversion', 0);

        if (!$enableWebP && !$enableAvif) {
            return "";
        }

        $rules = self::HTACCESS_MARKER . "\n" .
                "<IfModule mod_rewrite.c>\n" .
                "RewriteEngine On\n";

        if ($enableAvif) {
            $rules .= "# AVIF Image Serving - Check if browser supports AVIF\n" .
                      "RewriteCond %{HTTP_ACCEPT} image/avif\n" .
                      "RewriteCond %{REQUEST_FILENAME} \\.(jpe?g|png)$\n" .
                      "RewriteCond %{REQUEST_FILENAME}\\.avif -f\n" .
                      "RewriteRule ^(.+)\\.(jpe?g|png)$ $1.$2.avif [T=image/avif,E=avif:1,L]\n\n";
        }

        if ($enableWebP) {
            $rules .= "# WebP Image Serving - Check if browser supports WebP\n" .
                      "RewriteCond %{HTTP_ACCEPT} image/webp\n" .
                      "RewriteCond %{REQUEST_FILENAME} \\.(jpe?g|png)$\n" .
                      "RewriteCond %{REQUEST_FILENAME}\\.webp -f\n" .
                      "RewriteRule ^(.+)\\.(jpe?g|png)$ $1.$2.webp [T=image/webp,E=webp:1,L]\n";
        }

        $rules .= "</IfModule>\n\n" .
                  "<IfModule mod_headers.c>\n" .
                  "# Add Vary header for proper caching\n" .
                  "Header append Vary Accept\n" .
                  "# Set proper cache headers for Next-Gen formats\n" .
                  "<FilesMatch \"\\.(webp|avif)$\">\n" .
                  "Header set Cache-Control \"public, max-age=31536000, immutable\"\n" .
                  "</FilesMatch>\n" .
                  "</IfModule>\n\n" .
                  "<IfModule mod_mime.c>\n" .
                  "AddType image/webp .webp\n" .
                  "AddType image/avif .avif\n" .
                  "</IfModule>\n" .
                  self::HTACCESS_END_MARKER;

        return $rules;
    }
    
    /**
     * Get Nginx Next-Gen configuration
     * 
     * Note: Nginx doesn't support nested if statements, so we use a map-based approach
     * for proper AVIF > WebP > Original fallback chain.
     */
    public function getNginxNextGenConfig(): string {
        $enableWebP = get_option('mamba_enable_webp_conversion', 0);
        $enableAvif = get_option('mamba_enable_avif_conversion', 0);

        // Build the map entries based on enabled formats
        $mapEntries = "    default \"\";";
        
        // AVIF takes priority (checked first in Accept header matching)
        if ($enableAvif && $enableWebP) {
            // Both enabled: AVIF priority, WebP fallback
            return "# Next-Gen Image Support for Mamba Media Optimization
# Add this to your http {} block in nginx.conf:

map \$http_accept \$nextgen_suffix {
    default \"\";
    \"~*avif\" \".avif\";
    \"~*webp\" \".webp\";
}

# Add this to your server {} block:
location ~* \\.(jpe?g|png)\$ {
    add_header Vary Accept;
    
    # Try AVIF first, then WebP, then original
    try_files \$uri.avif \$uri.webp \$uri =404;
}

# Ensure Next-Gen MIME types are served correctly
location ~* \\.(webp|avif)\$ {
    add_header Vary Accept;
    expires 1y;
    add_header Cache-Control \"public, immutable\";
}";
        } elseif ($enableAvif) {
            // Only AVIF enabled
            return "# AVIF Image Support for Mamba Media Optimization
# Add this to your server {} block:

location ~* \\.(jpe?g|png)\$ {
    add_header Vary Accept;
    set \$avif_suffix \"\";
    
    if (\$http_accept ~* \"avif\") {
        set \$avif_suffix \".avif\";
    }
    
    try_files \$uri\$avif_suffix \$uri =404;
}

# Ensure AVIF MIME type is served correctly
location ~* \\.avif\$ {
    add_header Vary Accept;
    expires 1y;
    add_header Cache-Control \"public, immutable\";
}";
        } elseif ($enableWebP) {
            // Only WebP enabled
            return "# WebP Image Support for Mamba Media Optimization
# Add this to your server {} block:

location ~* \\.(jpe?g|png)\$ {
    add_header Vary Accept;
    set \$webp_suffix \"\";
    
    if (\$http_accept ~* \"webp\") {
        set \$webp_suffix \".webp\";
    }
    
    try_files \$uri\$webp_suffix \$uri =404;
}

# Ensure WebP MIME type is served correctly
location ~* \\.webp\$ {
    add_header Vary Accept;
    expires 1y;
    add_header Cache-Control \"public, immutable\";
}";
        }
        
        // Neither enabled
        return "# No Next-Gen image formats enabled. Enable WebP or AVIF conversion first.";
    }

    /**
     * Compatibility wrapper for Nginx config
     */
    public function getNginxWebPConfig(): string {
        return $this->getNginxNextGenConfig();
    }
    
    /**
     * Remove existing WebP rules from content
     */
    private function removeExistingRules(string $content): string {
        $startPos = strpos($content, self::HTACCESS_MARKER);
        if ($startPos === false) {
            return $content;
        }
        
        $endPos = strpos($content, self::HTACCESS_END_MARKER);
        if ($endPos === false) {
            return $content;
        }
        
        $endPos += strlen(self::HTACCESS_END_MARKER);
        
        $before = substr($content, 0, $startPos);
        $after = substr($content, $endPos);
        
        return trim($before) . "\n" . trim($after);
    }
    
    /**
     * Check if server supports .htaccess
     */
    public function isSupported(): bool {
        return $this->getHtaccessPath() !== null;
    }
    
    /**
     * Get server information
     */
    public function getServerInfo(): array {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized via sanitize_text_field
        $serverSoftware = isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : '';
        
        // Enhanced server detection with proper distinction
        $isLiteSpeed = stripos($serverSoftware, 'litespeed') !== false;
        $isApache = stripos($serverSoftware, 'apache') !== false && !$isLiteSpeed;
        $isNginx = stripos($serverSoftware, 'nginx') !== false;
        $isIIS = stripos($serverSoftware, 'microsoft-iis') !== false || stripos($serverSoftware, 'iis') !== false;
        $isCaddy = stripos($serverSoftware, 'caddy') !== false;
        
        // Apache-compatible servers (Apache and LiteSpeed both support .htaccess)
        $isApacheCompatible = $isApache || $isLiteSpeed;
        
        // Determine server type for display
        $serverType = 'Unknown';
        if ($isLiteSpeed) {
            $serverType = 'LiteSpeed';
        } elseif ($isApache) {
            $serverType = 'Apache';
        } elseif ($isNginx) {
            $serverType = 'Nginx';
        } elseif ($isIIS) {
            $serverType = 'IIS';
        } elseif ($isCaddy) {
            $serverType = 'Caddy';
        }
        
        return [
            'software' => $serverSoftware,
            'server_type' => $serverType,
            'is_apache' => $isApache, // Only true Apache
            'is_nginx' => $isNginx,
            'is_litespeed' => $isLiteSpeed,
            'is_iis' => $isIIS,
            'is_caddy' => $isCaddy,
            'is_apache_compatible' => $isApacheCompatible, // For .htaccess support
            'htaccess_writable' => $this->getHtaccessPath() !== null,
            'has_webp_rules' => $this->hasWebPRules()
        ];
    }
    
    /**
     * Test if .htaccess is actually supported (beyond just file writability)
     */
    private function testHtaccessSupport(): bool {
        // If we can write to .htaccess and mod_rewrite functions exist, likely Apache
        return $this->getHtaccessPath() !== null && (
            function_exists('apache_get_modules') ||
            // WordPress uses .htaccess, so if WordPress works, .htaccess likely works
            is_file(ABSPATH . '.htaccess')
        );
    }

    /**
     * Read .htaccess file content
     */
    private function readHtaccess(string $htaccessPath): string {
        if (!file_exists($htaccessPath)) {
            return '';
        }
        return file_get_contents($htaccessPath);
    }

    /**
     * Write content to .htaccess file
     */
    private function writeHtaccess(string $htaccessPath, string $content): bool {
        return file_put_contents($htaccessPath, $content, LOCK_EX) !== false;
    }
}
