<?php
declare(strict_types=1);

namespace ROITheme\Public\CtaLetsTalk\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 CtaLetsTalkRenderer
 *
 * Renderizador del componente CTA "Let's Talk" para el frontend.
 *
 * Responsabilidades:
 * - Renderizar botón CTA "Let's Talk" en el navbar
 * - Delegar generación de CSS a CSSGeneratorInterface
 * - Validar visibilidad (is_enabled, show_on_pages, show_on_desktop, show_on_mobile)
 * - Manejar visibilidad responsive con clases Bootstrap
 * - Generar atributos para modal o URL personalizada
 * - 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\CtaLetsTalk\Infrastructure\Ui
 */
final class CtaLetsTalkRenderer implements RendererInterface
{
    private const COMPONENT_NAME = 'cta-lets-talk';

    /**
     * @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 CSS usando CSSGeneratorService
        $css = $this->generateCSS($data);

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

        // Combinar todo
        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;
    }

    /**
     * Calcular clases de visibilidad responsive
     *
     * @param bool $desktop Mostrar en desktop
     * @param bool $mobile Mostrar en mobile
     * @return string|null Clases CSS o null si no debe mostrarse
     */
    private function getVisibilityClasses(bool $desktop, bool $mobile): ?string
    {
        if (!$desktop && !$mobile) {
            return null;
        }
        if (!$desktop && $mobile) {
            return 'd-lg-none';
        }
        if ($desktop && !$mobile) {
            return 'd-none d-lg-block';
        }
        return '';
    }

    /**
     * Generar CSS usando CSSGeneratorService
     *
     * @param array $data Datos del componente
     * @return string CSS generado
     */
    public function generateCSS(array $data): string
    {
        $css = '';

        // Estilos base del botón
        $baseStyles = [
            'background_color' => $data['colors']['background_color'] ?? '#FF8600',
            'color' => $data['colors']['text_color'] ?? '#FFFFFF',
            'font_size' => $data['typography']['font_size'] ?? '1rem',
            'font_weight' => $data['typography']['font_weight'] ?? '600',
            'text_transform' => $data['typography']['text_transform'] ?? 'none',
            'padding' => sprintf(
                '%s %s',
                $data['spacing']['padding_top_bottom'] ?? '0.5rem',
                $data['spacing']['padding_left_right'] ?? '1.5rem'
            ),
            'border' => sprintf(
                '%s solid %s',
                $data['visual_effects']['border_width'] ?? '0',
                $data['colors']['border_color'] ?? 'transparent'
            ),
            'border_radius' => $data['visual_effects']['border_radius'] ?? '6px',
            'box_shadow' => $data['visual_effects']['box_shadow'] ?? 'none',
            'transition' => sprintf(
                'all %s ease',
                $data['visual_effects']['transition_duration'] ?? '0.3s'
            ),
            'cursor' => 'pointer',
        ];
        $css .= $this->cssGenerator->generate('.btn-lets-talk', $baseStyles);

        // Estilos hover del botón
        $hoverStyles = [
            'background_color' => $data['colors']['background_hover_color'] ?? '#FF6B35',
            'color' => $data['colors']['text_hover_color'] ?? '#FFFFFF',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.btn-lets-talk:hover', $hoverStyles);

        // Estilos del ícono dentro del botón
        $iconStyles = [
            'color' => $data['colors']['text_color'] ?? '#FFFFFF',
            'margin_right' => $data['spacing']['icon_spacing'] ?? '0.5rem',
        ];
        $css .= "\n" . $this->cssGenerator->generate('.btn-lets-talk i', $iconStyles);

        // Estilos responsive - ocultar en móvil si show_on_mobile = false
        $showOnMobile = ($data['visibility']['show_on_mobile'] ?? false) === true;
        if (!$showOnMobile) {
            $responsiveStyles = [
                'display' => 'none !important',
            ];
            $css .= "\n@media (max-width: 991px) {\n";
            $css .= $this->cssGenerator->generate('.btn-lets-talk', $responsiveStyles);
            $css .= "\n}";
        }

        // Estilos responsive - ocultar en desktop si show_on_desktop = false
        $showOnDesktop = ($data['visibility']['show_on_desktop'] ?? true) === true;
        if (!$showOnDesktop) {
            $responsiveStyles = [
                'display' => 'none !important',
            ];
            $css .= "\n@media (min-width: 992px) {\n";
            $css .= $this->cssGenerator->generate('.btn-lets-talk', $responsiveStyles);
            $css .= "\n}";
        }

        // Margen izquierdo para separar del menú (solo desktop)
        $marginLeft = $data['spacing']['margin_left'] ?? '1rem';
        if (!empty($marginLeft) && $marginLeft !== '0') {
            $css .= "\n@media (min-width: 992px) {\n";
            $css .= $this->cssGenerator->generate('.btn-lets-talk', ['margin_left' => $marginLeft]);
            $css .= "\n}";
        }

        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);
        $attributes = $this->buildAttributes($data);
        $content = $this->buildContent($data);

        $tag = $this->useModal($data) ? 'button' : 'a';

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

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

        // Agregar clase ms-lg-3 para margen en desktop (Bootstrap)
        // Esto solo aplica en pantallas >= lg (992px)
        $classes[] = 'ms-lg-3';

        return implode(' ', $classes);
    }

    /**
     * Determinar si debe usar modal o URL
     *
     * @param array $data Datos del componente
     * @return bool
     */
    private function useModal(array $data): bool
    {
        return ($data['behavior']['enable_modal'] ?? true) === true;
    }

    /**
     * Construir atributos HTML del componente
     *
     * @param array $data Datos del componente
     * @return string Atributos HTML
     */
    private function buildAttributes(array $data): string
    {
        $attributes = [];

        if ($this->useModal($data)) {
            // Atributos para modal de Bootstrap
            $attributes[] = 'type="button"';
            $attributes[] = 'data-bs-toggle="modal"';

            $modalTarget = $data['content']['modal_target'] ?? '#contactModal';
            $attributes[] = sprintf('data-bs-target="%s"', esc_attr($modalTarget));
        } else {
            // Atributos para enlace
            $customUrl = $data['behavior']['custom_url'] ?? '';
            $attributes[] = sprintf('href="%s"', esc_url($customUrl ?: '#'));

            if (($data['behavior']['open_in_new_tab'] ?? false) === true) {
                $attributes[] = 'target="_blank"';
                $attributes[] = 'rel="noopener noreferrer"';
            }
        }

        // Atributo ARIA para accesibilidad
        $ariaLabel = $data['content']['aria_label'] ?? 'Abrir formulario de contacto';
        if (!empty($ariaLabel)) {
            $attributes[] = sprintf('aria-label="%s"', esc_attr($ariaLabel));
        }

        return !empty($attributes) ? ' ' . implode(' ', $attributes) : '';
    }

    /**
     * Construir contenido del botón
     *
     * @param array $data Datos del componente
     * @return string HTML del contenido
     */
    private function buildContent(array $data): string
    {
        $html = '';

        // Ícono (si está habilitado)
        if ($this->shouldShowIcon($data)) {
            $html .= $this->buildIcon($data);
        }

        // Texto del botón
        $buttonText = $data['content']['button_text'] ?? "Let's Talk";
        $html .= esc_html($buttonText);

        return $html;
    }

    /**
     * Verificar si debe mostrar el ícono
     *
     * @param array $data Datos del componente
     * @return bool
     */
    private function shouldShowIcon(array $data): bool
    {
        return ($data['content']['show_icon'] ?? true) === true;
    }

    /**
     * Construir ícono del componente
     *
     * @param array $data Datos del componente
     * @return string HTML del ícono
     */
    private function buildIcon(array $data): string
    {
        $iconClass = $data['content']['icon_class'] ?? 'bi-lightning-charge-fill';

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

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