<?php
declare(strict_types=1);

namespace ROITheme\Shared\Infrastructure\Services;

/**
 * CriticalBootstrapService
 *
 * Inyecta CSS crítico de Bootstrap en wp_head para evitar
 * bloqueo de renderizado por el Bootstrap completo.
 *
 * RESPONSABILIDAD:
 * - Leer critical-bootstrap.css (subset de Bootstrap)
 * - Inyectar en <head> via wp_head (priority 0, antes de CriticalCSSService)
 * - Cachear contenido para evitar lecturas repetidas
 *
 * FLUJO:
 * 1. wp_head (priority 0) → render()
 * 2. Lee Assets/css/critical-bootstrap.css
 * 3. Output: <style id="roi-critical-bootstrap">...</style>
 *
 * IMPORTANTE:
 * - Este servicio se ejecuta ANTES de CriticalCSSService (priority 0 vs 1)
 * - Bootstrap completo se carga diferido (media="print" + onload)
 *
 * @package ROITheme\Shared\Infrastructure\Services
 */
final class CriticalBootstrapService
{
    /**
     * Instancia singleton
     */
    private static ?self $instance = null;

    /**
     * Cache del contenido CSS
     */
    private ?string $cssCache = null;

    /**
     * Ruta al archivo CSS crítico
     */
    private string $cssFilePath;

    /**
     * Constructor privado (singleton)
     */
    private function __construct()
    {
        $this->cssFilePath = get_template_directory() . '/Assets/Css/critical-bootstrap.css';
    }

    /**
     * Obtiene la instancia singleton
     *
     * @return self
     */
    public static function getInstance(): self
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Renderiza Critical Bootstrap CSS en wp_head
     *
     * Este método se llama desde wp_head con priority 0 (muy temprano).
     * Inyecta el subset de Bootstrap antes del CSS de componentes.
     *
     * @return void
     */
    public function render(): void
    {
        $css = $this->getCriticalCSS();

        if (empty($css)) {
            return;
        }

        // Minificar CSS removiendo comentarios y espacios innecesarios
        $minifiedCSS = $this->minifyCSS($css);

        printf(
            '<style id="roi-critical-bootstrap">%s</style>' . "\n",
            $minifiedCSS
        );
    }

    /**
     * Obtiene el contenido del CSS crítico
     *
     * @return string CSS crítico o string vacío si no existe
     */
    private function getCriticalCSS(): string
    {
        // Usar cache si existe
        if ($this->cssCache !== null) {
            return $this->cssCache;
        }

        // Verificar que el archivo existe
        if (!file_exists($this->cssFilePath)) {
            error_log('ROI Theme: Critical Bootstrap CSS file not found: ' . $this->cssFilePath);
            $this->cssCache = '';
            return '';
        }

        // Leer contenido
        $content = file_get_contents($this->cssFilePath);

        if ($content === false) {
            error_log('ROI Theme: Failed to read Critical Bootstrap CSS');
            $this->cssCache = '';
            return '';
        }

        $this->cssCache = $content;
        return $content;
    }

    /**
     * Minifica CSS removiendo comentarios y espacios innecesarios
     *
     * @param string $css CSS a minificar
     * @return string CSS minificado
     */
    private function minifyCSS(string $css): string
    {
        // Remover comentarios
        $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);

        // Remover espacios, tabs y newlines
        $css = str_replace(["\r\n", "\r", "\n", "\t"], '', $css);

        // Remover espacios múltiples
        $css = preg_replace('/\s+/', ' ', $css);

        // Remover espacios alrededor de caracteres especiales
        $css = preg_replace('/\s*([{}:;,>+~])\s*/', '$1', $css);

        // Remover último punto y coma antes de }
        $css = str_replace(';}', '}', $css);

        return trim($css);
    }
}
