<?php

// =============================================================================
// AUTOLOADER PARA COMPONENTES
// =============================================================================

spl_autoload_register(function ($class) {
    // Mapeo de namespaces a directorios
    $prefixes = [
        'ROITheme\\Shared\\' => get_template_directory() . '/Shared/',
        'ROITheme\\Public\\' => get_template_directory() . '/Public/',
        'ROITheme\\Admin\\' => get_template_directory() . '/Admin/',
    ];

    foreach ($prefixes as $prefix => $base_dir) {
        $len = strlen($prefix);
        if (strncmp($prefix, $class, $len) === 0) {
            $relative_class = substr($class, $len);
            $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php';

            if (file_exists($file)) {
                require $file;
                return;
            }
        }
    }
});

// =============================================================================
// FONT PRELOAD - Previene CLS por font swap
// =============================================================================

/**
 * Precarga fuentes críticas para prevenir CLS por font swap
 *
 * Las fuentes Poppins se precargan con alta prioridad para que estén
 * disponibles cuando el CSS las necesite, evitando el "flash" de
 * fuente de respaldo que causa layout shift.
 */
add_action('wp_head', function() {
    $theme_url = get_template_directory_uri();

    // Fuentes críticas: regular y 600 (usadas en títulos y body)
    $critical_fonts = [
        'poppins-v24-latin-regular.woff2',
        'poppins-v24-latin-600.woff2',
    ];

    foreach ($critical_fonts as $font) {
        printf(
            '<link rel="preload" href="%s/Assets/Fonts/%s" as="font" type="font/woff2" crossorigin>%s',
            esc_url($theme_url),
            esc_attr($font),
            "\n"
        );
    }
}, 1); // Priority 1 = muy temprano en wp_head

// =============================================================================
// HELPER FUNCTION: roi_get_component_setting() - GENÉRICA
// =============================================================================

/**
 * Obtiene un valor de configuración de cualquier componente desde la BD
 *
 * Reemplaza a roi_get_option() legacy - lee de wp_roi_theme_component_settings
 *
 * @param string $component Nombre del componente (ej: 'featured-image', 'navbar')
 * @param string $group Nombre del grupo (ej: 'visibility', 'content')
 * @param string $attribute Nombre del atributo (ej: 'is_enabled', 'show_on_pages')
 * @param mixed $default Valor por defecto si no existe
 * @return mixed Valor del atributo
 */
function roi_get_component_setting(string $component, string $group, string $attribute, $default = null) {
    global $wpdb;

    $table = $wpdb->prefix . 'roi_theme_component_settings';
    $value = $wpdb->get_var($wpdb->prepare(
        "SELECT attribute_value FROM {$table}
         WHERE component_name = %s
         AND group_name = %s
         AND attribute_name = %s",
        $component,
        $group,
        $attribute
    ));

    if ($value === null) {
        return $default;
    }

    // Convertir booleanos
    if ($value === '1') return true;
    if ($value === '0') return false;

    // Intentar decodificar JSON
    $decoded = json_decode($value, true);
    if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
        return $decoded;
    }

    return $value;
}

// =============================================================================
// HELPER FUNCTION: roi_get_navbar_setting()
// =============================================================================

/**
 * Obtiene un valor de configuración del navbar desde la BD
 *
 * @param string $group Nombre del grupo (ej: 'media', 'visibility')
 * @param string $attribute Nombre del atributo (ej: 'show_brand', 'logo_url')
 * @param mixed $default Valor por defecto si no existe
 * @return mixed Valor del atributo
 */
function roi_get_navbar_setting(string $group, string $attribute, $default = null) {
    global $wpdb;

    $table = $wpdb->prefix . 'roi_theme_component_settings';
    $value = $wpdb->get_var($wpdb->prepare(
        "SELECT attribute_value FROM {$table}
         WHERE component_name = 'navbar'
         AND group_name = %s
         AND attribute_name = %s",
        $group,
        $attribute
    ));

    if ($value === null) {
        return $default;
    }

    // Convertir booleanos
    if ($value === '1') return true;
    if ($value === '0') return false;

    // Intentar decodificar JSON
    $decoded = json_decode($value, true);
    if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
        return $decoded;
    }

    return $value;
}

// =============================================================================
// CRITICAL CSS SERVICE SINGLETON
// =============================================================================

/**
 * Obtiene la instancia singleton del CriticalCSSService
 *
 * Este servicio consulta la BD para componentes con is_critical=true
 * y genera su CSS en wp_head ANTES de que los componentes rendericen.
 *
 * @return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService
 */
function roi_get_critical_css_service(): \ROITheme\Shared\Infrastructure\Services\CriticalCSSService {
    global $wpdb;
    static $cssGenerator = null;

    if ($cssGenerator === null) {
        $cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();
    }

    return \ROITheme\Shared\Infrastructure\Services\CriticalCSSService::getInstance($wpdb, $cssGenerator);
}

// =============================================================================
// HELPER FUNCTION: roi_render_component()
// =============================================================================

/**
 * Renderiza un componente por su nombre
 *
 * @param string $componentName Nombre del componente
 * @return string HTML del componente renderizado
 */
function roi_render_component(string $componentName): string {
    global $wpdb;

    // DEBUG: Trace component rendering
    error_log("ROI Theme DEBUG: roi_render_component called with: {$componentName}");

    try {
        // Obtener datos del componente desde BD normalizada
        $table = $wpdb->prefix . 'roi_theme_component_settings';
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT group_name, attribute_name, attribute_value
             FROM {$table}
             WHERE component_name = %s
             ORDER BY group_name, attribute_name",
            $componentName
        ));

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

        // Reconstruir estructura de datos agrupada
        $data = [];
        foreach ($rows as $row) {
            if (!isset($data[$row->group_name])) {
                $data[$row->group_name] = [];
            }
            // Decodificar valor
            $value = $row->attribute_value;

            // Convertir booleanos almacenados como '1' o '0'
            if ($value === '1' || $value === '0') {
                $value = ($value === '1');
            } else {
                // Intentar decodificar JSON
                $decoded = json_decode($value, true);
                if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                    $value = $decoded;
                }
            }

            $data[$row->group_name][$row->attribute_name] = $value;
        }

        // Crear Value Objects requeridos
        $name = new \ROITheme\Shared\Domain\ValueObjects\ComponentName($componentName);
        $configuration = new \ROITheme\Shared\Domain\ValueObjects\ComponentConfiguration($data);

        // =====================================================================
        // VALIDACIÓN DE VISIBILIDAD POR DISPOSITIVO (Previene CLS)
        // =====================================================================
        // Si el componente no debe mostrarse en el dispositivo actual,
        // NO renderizar nada. Esto evita CLS causado por elementos que
        // se renderizan y luego se ocultan con CSS.
        // =====================================================================

        // Leer configuración de visibilidad desde BD
        $isEnabled = ($data['visibility']['is_enabled'] ?? true) === true;
        $showOnDesktop = ($data['visibility']['show_on_desktop'] ?? true) === true;
        $showOnMobile = ($data['visibility']['show_on_mobile'] ?? true) === true;

        // Si no está habilitado, no renderizar
        if (!$isEnabled) {
            return '';
        }

        // Detectar dispositivo actual y validar visibilidad
        // wp_is_mobile() detecta móviles y tablets via User-Agent
        $isMobileDevice = wp_is_mobile();

        if ($isMobileDevice && !$showOnMobile) {
            // Dispositivo móvil pero show_on_mobile = false → NO renderizar
            return '';
        }

        if (!$isMobileDevice && !$showOnDesktop) {
            // Dispositivo desktop pero show_on_desktop = false → NO renderizar
            return '';
        }

        // Crear ComponentVisibility con datos reales de BD
        $visibility = new \ROITheme\Shared\Domain\ValueObjects\ComponentVisibility(
            enabled: $isEnabled,
            visibleDesktop: $showOnDesktop,
            visibleTablet: $showOnMobile, // tablet tratado como mobile
            visibleMobile: $showOnMobile
        );

        // Crear instancia del componente
        $component = new \ROITheme\Shared\Domain\Entities\Component(
            $name,
            $configuration,
            $visibility
        );

        // Obtener renderer específico para el componente
        $renderer = null;

        // Crear instancia del CSSGeneratorService (reutilizable para todos los renderers)
        $cssGenerator = new \ROITheme\Shared\Infrastructure\Services\CSSGeneratorService();

        switch ($componentName) {
            // Componentes con soporte de CSS Crítico (above-the-fold)
            // Nota: Si is_critical=true, el CSS ya fue inyectado en <head> por CriticalCSSService
            case 'top-notification-bar':
                $renderer = new \ROITheme\Public\TopNotificationBar\Infrastructure\Ui\TopNotificationBarRenderer($cssGenerator);
                break;
            case 'navbar':
                $renderer = new \ROITheme\Public\Navbar\Infrastructure\Ui\NavbarRenderer($cssGenerator);
                break;
            case 'hero':
                error_log("ROI Theme DEBUG: Creating HeroRenderer");
                $renderer = new \ROITheme\Public\Hero\Infrastructure\Ui\HeroRenderer($cssGenerator);
                error_log("ROI Theme DEBUG: HeroRenderer created successfully");
                break;

            // Componentes sin soporte de CSS Crítico (below-the-fold)
            case 'cta-lets-talk':
                $renderer = new \ROITheme\Public\CtaLetsTalk\Infrastructure\Ui\CtaLetsTalkRenderer($cssGenerator);
                break;
            case 'featured-image':
                $renderer = new \ROITheme\Public\FeaturedImage\Infrastructure\Ui\FeaturedImageRenderer($cssGenerator);
                break;
            case 'table-of-contents':
                $renderer = new \ROITheme\Public\TableOfContents\Infrastructure\Ui\TableOfContentsRenderer($cssGenerator);
                break;
            case 'cta-box-sidebar':
                $renderer = new \ROITheme\Public\CtaBoxSidebar\Infrastructure\Ui\CtaBoxSidebarRenderer($cssGenerator);
                break;
            case 'social-share':
                $renderer = new \ROITheme\Public\SocialShare\Infrastructure\Ui\SocialShareRenderer($cssGenerator);
                break;
            case 'cta-post':
                $renderer = new \ROITheme\Public\CtaPost\Infrastructure\Ui\CtaPostRenderer($cssGenerator);
                break;
            case 'related-post':
                $renderer = new \ROITheme\Public\RelatedPost\Infrastructure\Ui\RelatedPostRenderer($cssGenerator);
                break;
            case 'contact-form':
                $renderer = new \ROITheme\Public\ContactForm\Infrastructure\Ui\ContactFormRenderer($cssGenerator);
                break;
            case 'footer':
                $renderer = new \ROITheme\Public\Footer\Infrastructure\Ui\FooterRenderer($cssGenerator);
                break;
        }

        if (!$renderer) {
            error_log("ROI Theme DEBUG: No renderer for {$componentName}");
            return '';
        }

        error_log("ROI Theme DEBUG: Calling render() for {$componentName}");
        $output = $renderer->render($component);
        error_log("ROI Theme DEBUG: render() returned " . strlen($output) . " chars for {$componentName}");
        return $output;

    } catch (\Exception $e) {
        // Always log errors for debugging
        error_log('ROI Theme ERROR: Exception rendering component ' . $componentName . ': ' . $e->getMessage());
        error_log('ROI Theme ERROR: Stack trace: ' . $e->getTraceAsString());
        return '';
    }
}

// =============================================================================
// REGISTRO DE CRITICAL CSS HOOKS
// =============================================================================

/**
 * Registra hooks para inyectar CSS crítico en <head>
 *
 * FLUJO:
 * 1. wp_head (priority 0) → CriticalBootstrapService::render()
 *    - Inyecta critical-bootstrap.css inline (grid, navbar, utilities)
 *    - Permite diferir bootstrap-subset.min.css
 *
 * 2. wp_head (priority 1) → CriticalCSSService::render()
 *    - Consulta BD por componentes con is_critical=true
 *    - Genera CSS usando los métodos públicos generateCSS() de los Renderers
 *    - Output: <style id="roi-critical-css">...</style>
 *
 * IMPORTANTE: CriticalBootstrapService HABILITADO para mejorar LCP.
 * critical-bootstrap.css incluye grid system para evitar CLS.
 */
add_action('after_setup_theme', function() {
    // 1. Critical Bootstrap CSS (priority 0) - inline bootstrap crítico
    $criticalBootstrapService = \ROITheme\Shared\Infrastructure\Services\CriticalBootstrapService::getInstance();
    add_action('wp_head', [$criticalBootstrapService, 'render'], 0);

    // 2. Critical Component CSS (priority 1) - CSS de componentes críticos
    $criticalCSSService = roi_get_critical_css_service();
    $hooksRegistrar = new \ROITheme\Shared\Infrastructure\Wordpress\CriticalCSSHooksRegistrar($criticalCSSService);
    $hooksRegistrar->register();

    // 3. Body Class Hooks (Plan 99.15) - CSS failsafe para componentes ocultos
    $container = \ROITheme\Shared\Infrastructure\Di\DIContainer::getInstance();
    $bodyClassHooksRegistrar = $container->getBodyClassHooksRegistrar();
    $bodyClassHooksRegistrar->register();
});

// =============================================================================
// NOTA: Los estilos de TOC y CTA Box Sidebar se generan dinámicamente
// desde la base de datos a través de sus respectivos Renderers.
// NO hardcodear CSS aquí - viola la arquitectura Clean Architecture.
// =============================================================================

// =============================================================================
// HELPER FUNCTION: roi_should_render_wrapper() - Plan 99.15
// =============================================================================

/**
 * Verifica si el wrapper de un componente debe renderizarse
 *
 * Evalúa:
 * - is_enabled
 * - show_on_mobile / show_on_desktop
 * - Exclusiones (categoría, post ID, URL pattern, page visibility)
 *
 * USO EN TEMPLATES:
 * ```php
 * if (roi_should_render_wrapper('navbar')) {
 *     echo '<nav class="navbar">';
 *     echo roi_render_component('navbar');
 *     echo '</nav>';
 * }
 * ```
 *
 * @param string $componentName Nombre del componente (kebab-case)
 * @return bool True si el wrapper debe renderizarse
 * @see Plan 99.15 - Fix Empty Layout Wrappers
 */
function roi_should_render_wrapper(string $componentName): bool {
    return \ROITheme\Shared\Infrastructure\Services\WrapperVisibilityService::shouldRenderWrapper($componentName);
}

/**
 * Verifica si AL MENOS UN componente de una lista debe renderizarse
 *
 * Útil para determinar si mostrar columna sidebar
 *
 * @param array<string> $componentNames Lista de nombres de componentes
 * @return bool True si al menos uno debe mostrarse
 */
function roi_should_render_any_wrapper(array $componentNames): bool {
    return \ROITheme\Shared\Infrastructure\Services\WrapperVisibilityService::shouldRenderAnyWrapper($componentNames);
}

// =============================================================================
// HELPER FUNCTION: roi_get_adsense_search_config()
// =============================================================================

/**
 * Obtiene la configuracion de AdSense para resultados de busqueda
 *
 * Esta funcion es la API publica que el plugin roi-apu-search consume.
 * El plugin NO debe acceder directamente a la tabla del tema.
 *
 * OPTIMIZACION: Una sola query carga todos los settings del componente.
 *
 * @return array Configuracion para JavaScript
 */
function roi_get_adsense_search_config(): array {
    global $wpdb;

    // =========================================================================
    // CARGAR TODOS LOS SETTINGS EN UNA SOLA QUERY
    // =========================================================================
    $table = $wpdb->prefix . 'roi_theme_component_settings';
    $rows = $wpdb->get_results($wpdb->prepare(
        "SELECT group_name, attribute_name, attribute_value
         FROM {$table}
         WHERE component_name = %s",
        'adsense-placement'
    ));

    if (empty($rows)) {
        return ['enabled' => false];
    }

    // Organizar en array asociativo por grupo/atributo
    $settings = [];
    foreach ($rows as $row) {
        if (!isset($settings[$row->group_name])) {
            $settings[$row->group_name] = [];
        }
        // Decodificar valor
        $value = $row->attribute_value;
        if ($value === '1') $value = true;
        elseif ($value === '0') $value = false;
        else {
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE && is_array($decoded)) {
                $value = $decoded;
            }
        }
        $settings[$row->group_name][$row->attribute_name] = $value;
    }

    // Helper para obtener valor con default
    $get = function(string $group, string $attr, $default = null) use ($settings) {
        return $settings[$group][$attr] ?? $default;
    };

    // =========================================================================
    // VALIDAR CONDICIONES GLOBALES
    // =========================================================================

    // AdSense global deshabilitado
    if ($get('visibility', 'is_enabled', false) !== true) {
        return ['enabled' => false];
    }

    // Ads en busqueda deshabilitados
    if ($get('search_results', 'search_ads_enabled', false) !== true) {
        return ['enabled' => false];
    }

    // Publisher ID vacio
    $publisherId = $get('content', 'publisher_id', '');
    if (empty($publisherId)) {
        return ['enabled' => false];
    }

    // =========================================================================
    // VALIDAR EXCLUSIONES (igual que el resto del sistema)
    // =========================================================================

    // Ocultar para usuarios logueados
    if ($get('visibility', 'hide_for_logged_in', false) === true && is_user_logged_in()) {
        return ['enabled' => false];
    }

    // Visibilidad por dispositivo
    $isMobile = wp_is_mobile();
    if ($isMobile && $get('visibility', 'show_on_mobile', true) !== true) {
        return ['enabled' => false];
    }
    if (!$isMobile && $get('visibility', 'show_on_desktop', true) !== true) {
        return ['enabled' => false];
    }

    // =========================================================================
    // CONSTRUIR CONFIGURACION
    // =========================================================================
    return [
        'enabled' => true,
        'publisherId' => $publisherId,
        'slots' => [
            'auto' => $get('content', 'slot_auto', ''),
            'inArticle' => $get('content', 'slot_inarticle', ''),
            'autorelaxed' => $get('content', 'slot_autorelaxed', ''),
            'display' => $get('content', 'slot_display', ''),
        ],
        'topAd' => [
            'enabled' => $get('search_results', 'search_top_ad_enabled', true) === true,
            'format' => $get('search_results', 'search_top_ad_format', 'auto'),
        ],
        'betweenAds' => [
            'enabled' => $get('search_results', 'search_between_enabled', true) === true,
            'max' => min(3, max(1, (int) $get('search_results', 'search_between_max', '1'))),
            'format' => $get('search_results', 'search_between_format', 'in-article'),
            'position' => $get('search_results', 'search_between_position', 'random'),
            'every' => (int) $get('search_results', 'search_between_every', '5'),
        ],
        'delay' => [
            'enabled' => $get('forms', 'delay_enabled', true) === true,
            'timeout' => (int) $get('forms', 'delay_timeout', '5000'),
        ],
    ];
}
