<?php
declare(strict_types=1);

namespace ROITheme\Public\TopNotificationBar\Infrastructure\Ui;

use ROITheme\Shared\Domain\Contracts\RendererInterface;
use ROITheme\Shared\Domain\Contracts\CSSGeneratorInterface;
use ROITheme\Shared\Domain\Entities\Component;
use ROITheme\Shared\Infrastructure\Services\PageVisibilityHelper;
use ROITheme\Shared\Infrastructure\Services\UserVisibilityHelper;

/**
 * Class TopNotificationBarRenderer
 *
 * Renderizador del componente Top Notification Bar para el frontend.
 *
 * Responsabilidades:
 * - Renderizar HTML del componente top-notification-bar
 * - Delegar generación de CSS a CSSGeneratorInterface
 * - Validar visibilidad (is_enabled, show_on_pages, hide_on_mobile)
 * - Manejar visibilidad responsive con clases Bootstrap
 * - Generar script para funcionalidad dismissible
 * - Sanitizar todos los outputs
 *
 * NO responsable de:
 * - Generar string CSS (delega a CSSGeneratorService)
 * - Persistir datos (ya están en Component)
 * - Lógica de negocio (está en Domain)
 *
 * Cumple con:
 * - DIP: Recibe CSSGeneratorInterface por constructor
 * - SRP: Una responsabilidad (renderizar este componente)
 * - Clean Architecture: Infrastructure puede usar WordPress
 *
 * @package ROITheme\Public\TopNotificationBar\Infrastructure\Ui
 */
final class TopNotificationBarRenderer implements RendererInterface
{
    private const COMPONENT_NAME = 'top-notification-bar';

    /**
     * @param CSSGeneratorInterface $cssGenerator Servicio de generación de CSS
     */
    public function __construct(
        private CSSGeneratorInterface $cssGenerator
    ) {}

    /**
     * {@inheritDoc}
     */
    public function render(Component $component): string
    {
        $data = $component->getData();

        // Validar visibilidad general
        if (!$this->isEnabled($data)) {
            return '';
        }

        // Validar visibilidad por página
        if (!PageVisibilityHelper::shouldShow(self::COMPONENT_NAME)) {
            return '';
        }

        // Validar visibilidad por usuario logueado
        if (!UserVisibilityHelper::shouldShowForUser($data['visibility'] ?? [])) {
            return '';
        }

        // Generar HTML
        $html = $this->buildHTML($data);

        // Si is_critical=true, CSS ya fue inyectado en <head> por CriticalCSSService
        $isCritical = $data['visibility']['is_critical'] ?? false;

        if ($isCritical) {
            return $html; // Solo HTML, sin CSS inline
        }

        // CSS inline para componentes no críticos
        $css = $this->generateCSS($data);
        return sprintf("<style>%s</style>\n%s", $css, $html);
    }

    /**
     * {@inheritDoc}
     */
    public function supports(string $componentType): bool
    {
        return $componentType === self::COMPONENT_NAME;
    }

    /**
     * Verificar si el componente está habilitado
     *
     * @param array $data Datos del componente
     * @return bool
     */
    private function isEnabled(array $data): bool
    {
        return ($data['visibility']['is_enabled'] ?? false) === true;
    }

    /**
     * Verificar si el componente fue dismissed por el usuario
     *
     * @param array $data Datos del componente
     * @return bool
     */
    private function isDismissed(array $data): bool
    {
        if (!$this->isDismissible($data)) {
            return false;
        }

        $cookieName = 'roi_notification_bar_dismissed';
        return isset($_COOKIE[$cookieName]) && $_COOKIE[$cookieName] === '1';
    }

    /**
     * Verificar si el componente es dismissible
     *
     * @param array $data Datos del componente
     * @return bool
     */
    private function isDismissible(array $data): bool
    {
        return ($data['behavior']['is_dismissible'] ?? false) === true;
    }

    /**
     * Generar CSS usando CSSGeneratorService
     *
     * Este método es público para que CriticalCSSService pueda
     * generar CSS crítico antes de wp_head sin duplicar lógica.
     *
     * @param array $data Datos del componente
     * @return string CSS generado
     */
    public function generateCSS(array $data): string
    {
        $css = '';

        // Estilos base de la barra
        $baseStyles = [
            'background_color' => $data['styles']['background_color'] ?? '#0E2337',
            'color' => $data['styles']['text_color'] ?? '#FFFFFF',
            'font_size' => $data['styles']['font_size'] ?? '0.9rem',
            'padding' => $data['styles']['padding'] ?? '0.5rem 0',
            'width' => '100%',
            'z_index' => '1050',
        ];
        $css .= $this->cssGenerator->generate('.top-notification-bar', $baseStyles);

        // Estilos del ícono
        $iconStyles = [
            'color' => $data['styles']['icon_color'] ?? '#FF8600',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.top-notification-bar .notification-icon', $iconStyles);

        // Estilos de la etiqueta (label)
        $labelStyles = [
            'color' => $data['styles']['label_color'] ?? '#FF8600',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.top-notification-bar .notification-label', $labelStyles);

        // Estilos del enlace
        $linkStyles = [
            'color' => $data['styles']['link_color'] ?? '#FFFFFF',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.top-notification-bar .notification-link', $linkStyles);

        // Estilos del enlace hover
        $linkHoverStyles = [
            'color' => $data['styles']['link_hover_color'] ?? '#FF8600',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.top-notification-bar .notification-link:hover', $linkHoverStyles);

        // Estilos del ícono personalizado
        $customIconStyles = [
            'width' => '24px',
            'height' => '24px',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.top-notification-bar .custom-icon', $customIconStyles);

        return $css;
    }

    /**
     * Generar HTML del componente
     *
     * @param array $data Datos del componente
     * @return string HTML generado
     */
    private function buildHTML(array $data): string
    {
        $classes = $this->buildClasses($data);
        $content = $this->buildContent($data);

        return sprintf(
            '<div class="%s">%s</div>',
            esc_attr($classes),
            $content
        );
    }

    /**
     * Construir clases CSS del componente
     *
     * @param array $data Datos del componente
     * @return string Clases CSS
     */
    private function buildClasses(array $data): string
    {
        $classes = ['top-notification-bar'];

        // Agregar clases de visibilidad responsive
        $showOnDesktop = ($data['visibility']['show_on_desktop'] ?? true) === true;
        $showOnMobile = ($data['visibility']['show_on_mobile'] ?? true) === true;

        $visibilityClasses = $this->getVisibilityClasses($showOnDesktop, $showOnMobile);

        if ($visibilityClasses !== null) {
            $classes[] = $visibilityClasses;
        }

        return implode(' ', $classes);
    }

    /**
     * Construir atributos data para dismissible
     *
     * @param array $data Datos del componente
     * @return string Atributos HTML
     */
    private function buildDismissAttributes(array $data): string
    {
        if (!$this->isDismissible($data)) {
            return '';
        }

        $days = (int) ($data['behavior']['dismissible_cookie_days'] ?? 7);
        return sprintf(' data-dismissible-days="%d"', $days);
    }

    /**
     * Construir contenido del componente
     *
     * @param array $data Datos del componente
     * @return string HTML del contenido
     */
    private function buildContent(array $data): string
    {
        $html = '<div class="container">';
        $html .= '<div class="d-flex align-items-center justify-content-center">';

        // Ícono
        $html .= $this->buildIcon($data);

        // Texto del anuncio
        $html .= $this->buildAnnouncementText($data);

        // Enlace
        $html .= $this->buildLink($data);

        $html .= '</div>';
        $html .= '</div>';

        return $html;
    }

    /**
     * Construir ícono del componente
     *
     * @param array $data Datos del componente
     * @return string HTML del ícono
     */
    private function buildIcon(array $data): string
    {
        // Siempre usar Bootstrap icon desde content.icon_class
        $iconClass = $data['content']['icon_class'] ?? 'bi-megaphone-fill';

        // Asegurar prefijo 'bi-'
        if (strpos($iconClass, 'bi-') !== 0) {
            $iconClass = 'bi-' . $iconClass;
        }

        return sprintf(
            '<i class="bi %s notification-icon me-2"></i>',
            esc_attr($iconClass)
        );
    }

    /**
     * Construir texto del anuncio
     *
     * @param array $data Datos del componente
     * @return string HTML del texto
     */
    private function buildAnnouncementText(array $data): string
    {
        $label = $data['content']['label_text'] ?? '';
        $text = $data['content']['message_text'] ?? '';

        if (empty($text)) {
            return '';
        }

        $html = '<span>';

        if (!empty($label)) {
            $html .= sprintf('<strong class="notification-label">%s</strong> ', esc_html($label));
        }

        $html .= esc_html($text);
        $html .= '</span>';

        return $html;
    }

    /**
     * Construir enlace de acción
     *
     * @param array $data Datos del componente
     * @return string HTML del enlace
     */
    private function buildLink(array $data): string
    {
        $linkText = $data['content']['link_text'] ?? '';
        $linkUrl = $data['content']['link_url'] ?? '#';

        if (empty($linkText)) {
            return '';
        }

        return sprintf(
            '<a href="%s" class="notification-link ms-2 text-decoration-underline">%s</a>',
            esc_url($linkUrl),
            esc_html($linkText)
        );
    }

    /**
     * Construir botón de cerrar
     *
     * @return string HTML del botón
     */
    private function buildDismissButton(): string
    {
        return '<button type="button" class="btn-close btn-close-white ms-3 roi-dismiss-notification" aria-label="Cerrar"></button>';
    }

    /**
     * Construir estilos CSS de animaciones
     *
     * @param array $data Datos del componente
     * @return string CSS de animaciones
     */
    private function buildAnimationStyles(array $data): string
    {
        $animationType = $data['visual_effects']['animation_type'] ?? 'slide-down';

        $animations = [
            'slide-down' => [
                'keyframes' => '@keyframes roiSlideDown { from { transform: translateY(-100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } }',
                'animation' => 'roiSlideDown 0.5s ease-out',
            ],
            'fade-in' => [
                'keyframes' => '@keyframes roiFadeIn { from { opacity: 0; } to { opacity: 1; } }',
                'animation' => 'roiFadeIn 0.5s ease-out',
            ],
        ];

        $anim = $animations[$animationType] ?? $animations['slide-down'];

        return sprintf(
            "%s\n.top-notification-bar.roi-animated.roi-%s { animation: %s; }",
            $anim['keyframes'],
            $animationType,
            $anim['animation']
        );
    }

    /**
     * Construir script para funcionalidad dismissible
     *
     * @param array $data Datos del componente
     * @return string JavaScript
     */
    private function buildDismissScript(array $data): string
    {
        $days = (int) ($data['behavior']['dismissible_cookie_days'] ?? 7);

        return sprintf(
            '<script>
document.addEventListener("DOMContentLoaded", function() {
    const dismissBtn = document.querySelector(".roi-dismiss-notification");
    if (dismissBtn) {
        dismissBtn.addEventListener("click", function() {
            const bar = document.querySelector(".top-notification-bar");
            if (bar) {
                bar.style.display = "none";
            }

            const days = %d;
            const date = new Date();
            date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
            const expires = "expires=" + date.toUTCString();
            document.cookie = "roi_notification_bar_dismissed=1;" + expires + ";path=/";
        });
    }
});
</script>',
            $days
        );
    }

    /**
     * Obtiene las clases CSS de Bootstrap para visibilidad responsive
     *
     * Implementa tabla de decisión según especificación (10.03):
     * - Desktop Y Mobile = null (visible en ambos)
     * - Solo Desktop = 'd-none d-lg-block'
     * - Solo Mobile = 'd-lg-none'
     * - Ninguno = 'd-none' (oculto)
     *
     * @param bool $desktop Mostrar en desktop
     * @param bool $mobile Mostrar en mobile
     * @return string|null Clases CSS o null si visible en ambos
     */
    private function getVisibilityClasses(bool $desktop, bool $mobile): ?string
    {
        // Desktop Y Mobile = visible en ambos dispositivos
        if ($desktop && $mobile) {
            return null; // Sin clases = visible siempre
        }

        // Solo Desktop
        if ($desktop && !$mobile) {
            return 'd-none d-lg-block';
        }

        // Solo Mobile
        if (!$desktop && $mobile) {
            return 'd-lg-none';
        }

        // Ninguno = oculto completamente
        return 'd-none';
    }
}
