<?php

declare(strict_types=1);

namespace FleekDash\Frontend;

use FleekDash\Core\Template;

// Load debug helpers
if (!function_exists('fleekdash_log_error')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}
use FleekDash\Traits\Base;
use FleekDash\Libs\Assets as AssetsLib;

/**
 * Class Assets
 *
 * Handles frontend assets (scripts and styles) for the FleekDash.
 *
 * @package FleekDash\Frontend
 */
class Assets
{
    use Base;

    /**
     * Script handle for FleekDash.
     */
    const HANDLE = 'fleekdash-frontend';

    /**
     * JS Object name for FleekDash.
     */
    const OBJ_NAME = 'FleekDashFrontend';

    /**
     * Development script path for FleekDash.
     */
    const DEV_SCRIPT = 'src/frontend/main.tsx';

    /**
     * WordPress admin screen IDs (WP_Screen::$id) where the frontend app may enqueue
     * when no post ID is available for template detection. Do not store page template
     * filenames here — compare those via get_page_template_slug() only.
     *
     * @var list<string>
     */
    private array $allowedScreens = array(
        'toplevel_page_fleekdash',
    );

    /**
     * Frontend bootstrapper.
     *
     * @return void
     */
    public function bootstrap()
    {
        \add_action('wp_enqueue_scripts', array($this, 'enqueueScript'));
        // Load admin bar styles with HIGH priority (999) to ensure it loads after WordPress defaults
        // WordPress default CSS loads first, then our custom CSS overrides with higher specificity
        \add_action('wp_enqueue_scripts', array($this, 'maybeEnqueueAdminBarStyles'), 999);

        // USE SINGLETON: Prevents duplicate hook registration (also called in Admin/Dashboard)
        $adminBarCustomizer = \FleekDash\Admin\AdminBarCustomizer::getInstance();
        $adminBarCustomizer->bootstrap();
    }

    /**
     * Enqueue admin bar styles on frontend
     *
     * WordPress shows admin bar for logged-in users by default on frontend.
     * This method loads FleekDash custom styles for the admin bar.
     *
     * @return void
     */
    public function maybeEnqueueAdminBarStyles(): void
    {
        $admin_bar_style = \get_option('fleekdash_admin_bar_style', 'modern');
        $should_enqueue = !is_admin()
            && \is_user_logged_in()
            && is_admin_bar_showing()
            && $admin_bar_style === 'modern';

        if (!$should_enqueue) {
            return;
        }

        // Don't remove WordPress default CSS - let it load and override with our custom CSS
        // WordPress default CSS provides base functionality (positioning, structure, etc)
        // Our custom CSS will override styles (colors, spacing, etc) with higher specificity
        // Note: On frontend, we ALWAYS load admin bar styles for logged-in users
        // The adminbar=true parameter is only used for iframe contexts

        // Enqueue admin bar styles with HIGH priority to load after WordPress defaults
        // Use getCssUrl() helper to get correct path (dev: includes/css, prod: assets)
        // This ensures the CSS file is found correctly in both development and production
        // The Vite build process copies admin-bar.css from includes/css/ to assets/ in production
        \wp_enqueue_style(
            'fleekdash-admin-bar-frontend',
            \FleekDash\Libs\Assets\getCssUrl('admin-bar'),
            array('admin-bar'), // Depend on WordPress default admin-bar CSS
            FLEEKDASH_VERSION,
            'all' // Media type
        );

        // Add CSS variables fallback for frontend (where design system tokens are not loaded)
        // These fallback values ensure admin bar styling works even without the full FleekDash app
        // The script below will read from localStorage to apply the correct theme (light/dark)
        \wp_add_inline_style('fleekdash-admin-bar-frontend', "
            /* ====================================================================
             * ADMIN BAR CSS VARIABLES FALLBACK
             * These are standalone fallbacks for when FleekDash design system
             * tokens are not loaded (frontend pages without the app)
             * ==================================================================== */

            /* Light mode (default) */
            #wpadminbar {
                --background: #ffffff;
                --foreground: #18181b;
                --card: #ffffff;
                --card-foreground: #18181b;
                --muted: #f4f4f5;
                --muted-foreground: #71717a;
                --accent: #f4f4f5;
                --accent-foreground: #18181b;
                --border: #e4e4e7;
                --input: #e4e4e7;
                --primary: #6366f1;
                --primary-foreground: #ffffff;
                --popover: #ffffff;
                --popover-foreground: #18181b;
            }

            /* Dark mode - applied via .dark class on html/body or via data-theme */
            html.dark #wpadminbar,
            body.dark #wpadminbar,
            [data-theme='dark'] #wpadminbar,
            .vx-dark-mode #wpadminbar {
                --background: #09090b;
                --foreground: #fafafa;
                --card: #09090b;
                --card-foreground: #fafafa;
                --muted: #27272a;
                --muted-foreground: #a1a1aa;
                --accent: #27272a;
                --accent-foreground: #fafafa;
                --border: #27272a;
                --input: #27272a;
                --primary: #6366f1;
                --primary-foreground: #ffffff;
                --popover: #18181b;
                --popover-foreground: #fafafa;
            }

            /* Ensure admin bar stays at top (no margin on html) */
            html,
            html.wp-toolbar {
                margin-top: 0 !important;
                padding-top: 0 !important;
            }

            /* NOTE: Frontend auto-hide handles spacing, no body/top compensation */
        ");

        // Add JavaScript to sync theme from localStorage to HTML element
        // This ensures the admin bar respects the user's theme preference stored in localStorage
        \add_action('wp_head', [$this, 'injectAdminBarThemeSync'], 1);
    }

    /**
     * Inject JavaScript to sync admin bar theme from localStorage
     *
     * Reads the user's theme preference from localStorage and applies
     * the appropriate dark/light class to the HTML element.
     *
     * @return void
     */
    public function injectAdminBarThemeSync(): void
    {
        // Only run on frontend for logged-in users with admin bar
        if (is_admin() || !\is_user_logged_in() || !\is_admin_bar_showing()) {
            return;
        }

        // Only inject theme sync if "modern" style is selected
        $admin_bar_style = \get_option('fleekdash_admin_bar_style', 'modern');
        if ($admin_bar_style !== 'modern') {
            return;
        }

        ?>
        <script type="text/javascript">
            (function() {
                // Define applyTheme function once (not redefined on each call)
                // This prevents unnecessary closures and ensures consistent behavior
                var html = document.documentElement;
                var applyTheme = function(dark) {
                    // Validate parameter - ensure it's a boolean
                    // Prevents errors from null/undefined/other types
                    var isDarkMode = dark === true || dark === 'true';

                    try {
                        if (isDarkMode) {
                            html.classList.add('dark');
                            html.classList.remove('light');
                            // Also apply to body when ready
                            if (document.body) {
                                document.body.classList.add('dark');
                                document.body.classList.remove('light');
                            }
                        } else {
                            html.classList.add('light');
                            html.classList.remove('dark');
                            if (document.body) {
                                document.body.classList.add('light');
                                document.body.classList.remove('dark');
                            }
                        }
                    } catch (error) {
                        // Log error but don't break execution
                        // This ensures the rest of the sync logic continues
                        console.warn('[FleekDash AdminBar] Error applying theme:', error);
                    }
                };

                // Read dark mode from localStorage (FleekDash stores it as 'fleekdash-dark-mode')
                // Value is stored as string "true" or "false"
                var isDarkStored = localStorage.getItem('fleekdash-dark-mode');
                var isDark;

                // If stored value exists, use it
                if (isDarkStored === 'true') {
                    isDark = true;
                } else if (isDarkStored === 'false') {
                    isDark = false;
                } else {
                    // No stored preference - check system preference
                    try {
                        isDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
                        // Ensure isDark is always boolean (not undefined)
                        isDark = isDark === true;
                    } catch (error) {
                        // Fallback to light mode if media query fails
                        isDark = false;
                    }
                }

                // Validate isDark before applying (prevents null/undefined errors)
                // Apply immediately to html
                if (typeof isDark === 'boolean') {
                    applyTheme(isDark);
                }

                // Re-apply when DOM is ready (to ensure body exists)
                if (document.readyState === 'loading') {
                    document.addEventListener('DOMContentLoaded', function() {
                        // Re-read from localStorage instead of using closure variable
                        // This prevents stale values if localStorage changed between script execution and DOM ready
                        var currentIsDarkStored = localStorage.getItem('fleekdash-dark-mode');
                        var currentIsDark;

                        if (currentIsDarkStored === 'true') {
                            currentIsDark = true;
                        } else if (currentIsDarkStored === 'false') {
                            currentIsDark = false;
                        } else {
                            // No stored value - check system preference
                            try {
                                currentIsDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
                                currentIsDark = currentIsDark === true; // Ensure boolean
                            } catch (error) {
                                currentIsDark = false;
                            }
                        }

                        // Validate before applying
                        if (typeof currentIsDark === 'boolean') {
                            applyTheme(currentIsDark);
                        }
                    });
                }

                // Also listen for changes in localStorage (cross-tab sync)
                window.addEventListener('storage', function(e) {
                    if (e.key === 'fleekdash-dark-mode') {
                        // Validate newValue before applying
                        var newIsDark = e.newValue === 'true';
                        applyTheme(newIsDark);
                    }
                });
            })();
        </script>
        <?php
    }

    /**
     * Enqueue frontend React app script
     *
     * Loads the FleekDash frontend React app only when using the
     * frontend-template.php page template.
     *
     * Note: Login and Voxel integrations have their own dedicated asset handlers.
     * This method only handles the explicit frontend template.
     *
     * Note: wp_enqueue_scripts hook doesn't pass parameters to callbacks by default.
     * We detect the current screen/template ourselves using WordPress functions.
     *
     * @return void
     */
    public function enqueueScript(): void
    {
        $admin_screen_id = $this->getCurrentWordPressScreenId();
        $template_file_name = Template::FRONTEND_TEMPLATE;
        $template_matches = is_admin()
            ? $this->templateMatchesFleekFrontendInAdmin($template_file_name, $admin_screen_id)
            : (get_page_template_slug() === $template_file_name);

        if (!$template_matches) {
            return;
        }

        $result = AssetsLib\enqueueAsset(
            FLEEKDASH_DIR . '/assets',
            self::DEV_SCRIPT,
            $this->getConfig(),
        );

        if (!$result) {
            fleekdash_log_error('FleekDash Frontend: Failed to enqueue assets from unified structure');
        }

        \wp_localize_script(self::HANDLE, self::OBJ_NAME, $this->getData());
    }

    private function getCurrentWordPressScreenId(): ?string
    {
        if (!function_exists('get_current_screen')) {
            return null;
        }

        $screen_obj = get_current_screen();

        return $screen_obj ? $screen_obj->id : null;
    }

    private function tryResolvePostIdFromPageEditScreen(): ?int
    {
        if (!function_exists('get_current_screen')) {
            return null;
        }

        $screen = get_current_screen();
        if (
            !$screen
            || !isset($screen->post_type, $screen->base)
            || $screen->post_type !== 'page'
            || strpos((string) $screen->base, 'post') === false
            || !isset($_GET['post'])
        ) {
            return null;
        }

        $post_param = \sanitize_text_field((string) $_GET['post']);

        return is_numeric($post_param) ? (int) $post_param : null;
    }

    private function resolvePostIdForAdminEnqueue(): ?int
    {
        $post_id = null;

        if (isset($_GET['post'])) {
            $post_param = \sanitize_text_field((string) $_GET['post']);
            if (is_numeric($post_param)) {
                $post_id = (int) $post_param;
            }
        }

        if ($post_id === null && isset($GLOBALS['post']) && $GLOBALS['post'] instanceof \WP_Post && $GLOBALS['post']->ID > 0) {
            $post_id = (int) $GLOBALS['post']->ID;
        }

        if ($post_id === null && get_queried_object_id() > 0) {
            $post_id = get_queried_object_id();
        }

        if ($post_id === null) {
            $post_id = $this->tryResolvePostIdFromPageEditScreen();
        }

        return $post_id;
    }

    private function templateMatchesFleekFrontendInAdmin(string $template_file_name, ?string $admin_screen_id): bool
    {
        $post_id = $this->resolvePostIdForAdminEnqueue();
        if ($post_id !== null && $post_id > 0) {
            return get_page_template_slug($post_id) === $template_file_name;
        }

        return $admin_screen_id !== null
            && is_string($admin_screen_id)
            && in_array($admin_screen_id, $this->allowedScreens, true);
    }



    /**
     * Get the script configuration.
     *
     * @return array The script configuration.
     */
    public function getConfig(): array
    {
        return array(
            'dependencies' => array('react', 'react-dom'),
            'handle' => self::HANDLE,
            'in_footer' => true,
        );
    }

    /**
     * Get data for script localization.
     *
     * @return array The localized script data.
     */
    public function getData(): array
    {
        return array(
            'developer' => 'Fleek',
            'isAdmin' => is_admin(),
            'apiUrl' => rest_url(),
            'userInfo' => $this->getUserData(),
        );
    }

    /**
     * Get user data for script localization.
     *
     * @return array The user data.
     */
    private function getUserData(): array
    {
        if (!\is_user_logged_in()) {
            return array(
                'id' => 0,
                'username' => '',
                'name' => '',
                'display_name' => '',
                'avatar' => '',
                'email' => '',
                'role' => '',
                'first_name' => '',
                'last_name' => '',
                'nickname' => '',
                'description' => ''
            );
        }

        // Get current user's data
        $current_user = \wp_get_current_user();

        return array(
            'id' => $current_user->ID,
            'username' => $current_user->user_login,
            'name' => $current_user->display_name,
            'display_name' => $current_user->display_name,
            'avatar' => get_avatar_url($current_user->ID),
            'email' => $current_user->user_email,
            'role' => isset($current_user->roles[0]) ? $current_user->roles[0] : '',
            'first_name' => \get_user_meta($current_user->ID, 'first_name', true),
            'last_name' => \get_user_meta($current_user->ID, 'last_name', true),
            'nickname' => \get_user_meta($current_user->ID, 'nickname', true),
            'description' => \get_user_meta($current_user->ID, 'description', true)
        );
    }
}
