<?php

declare(strict_types=1);

namespace FleekDash\Frontend;

use FleekDash\Libs\Assets as AssetsLib;
use FleekDash\Traits\Base;
use FleekDash\Traits\RemoveAdminBar;
use FleekDash\Services\Theme\ThemeStylesService;

class Login
{
    use Base;
    use RemoveAdminBar;

    const TEMPLATE_PATH = 'views/login-template.php';
    const PAGE_SLUG = 'login';
    const HANDLE = 'fleekdash-login';
    const DEV_SCRIPT = 'src/public/login-entry.tsx';

    public function bootstrap(): void
    {
        LoginStylesGuard::bootstrap();

        \add_filter('template_include', [$this, 'overrideLoginTemplate'], 99);
        \add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);
        \add_filter('login_url', [$this, 'customLoginUrl'], 10, 1);
        \add_filter('logout_redirect', [$this, 'customLogoutRedirect'], 10, 3);
        \add_action('template_redirect', [$this, 'redirectUnauthenticatedUsers']);

        // Add custom login route
        \add_action('init', [$this, 'handleCustomLoginRoute']);

        // Remove admin bar on login page (early priority to prevent space)
        \add_action('template_redirect', [$this, 'maybeRemoveAdminBar'], 1);

        // Inject palette CSS on login page (priority 0 to run before React)
        \add_action('wp_head', [$this, 'injectPaletteCss'], 0);

        // Custom cookie expiration
        \add_filter('auth_cookie_expiration', [$this, 'customCookieExpiration'], 10, 3);
    }

    /**
     * Inject palette CSS variables into wp_head for login pages
     * This ensures custom palette colors are available even for non-logged-in users
     */
    public function injectPaletteCss(): void
    {
        if (!$this->isLoginPage() && !isset($_GET['fleek_login']) && !isset($_GET['fleekpage'])) {
            return;
        }

        // First, inject dark mode detection script (must run before CSS)
        $this->injectDarkModeScript();

        $themeStylesService = new ThemeStylesService();
        $paletteCss = $themeStylesService->getPaletteCss();

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

        echo '<style id="fleekdash-server-palette-vars">' . $paletteCss . '</style>';
    }

    /**
     * Inject dark mode detection script
     * Applies 'dark' or 'light' class to HTML element based on localStorage or system preference
     */
    private function injectDarkModeScript(): void
    {
        $storageKey = 'fleekdash-dark-mode';
        $script = <<<JS
        (function() {
            try {
                var root = document.documentElement;
                if (!root) { return; }
                var key = '{$storageKey}';
                var stored = null;
                try {
                    stored = window.localStorage ? localStorage.getItem(key) : null;
                } catch (e) {
                    stored = null;
                }

                var applyDark = function(flag) {
                    if (flag) {
                        root.classList.add('dark');
                        root.classList.remove('light');
                        root.setAttribute('data-fleekdash-dark-mode', 'true');
                    } else {
                        root.classList.remove('dark');
                        root.classList.add('light');
                        root.setAttribute('data-fleekdash-dark-mode', 'false');
                    }
                };

                if (stored === 'true') {
                    applyDark(true);
                } else if (stored === 'false') {
                    applyDark(false);
                } else {
                    var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
                    applyDark(prefersDark);
                }
            } catch (e) {
                console.warn('[FleekDash] Dark mode bootstrap error:', e);
            }
        })();
JS;

        echo '<script id="fleekdash-dark-mode-bootstrap">' . $script . '</script>';
    }

    /**
     * Remove admin bar if on login page
     *
     * ALWAYS remove admin bar on login page - no exceptions
     */
    public function maybeRemoveAdminBar(): void
    {
        if ($this->isLoginPage() || isset($_GET['fleek_login'])) {
            $this->remove_admin_bar_on_page();
        }
    }

    private function isLoginPage(): bool
    {
        $page_id = \get_option('fleekdash_login_page_id');

        if (!$page_id) {
            return \is_page(self::PAGE_SLUG);
        }

        $matches_configured = \is_page($page_id);
        if (!$matches_configured) {
            global $wp_query;
            $current_page_id = (int) ($wp_query->queried_object_id ?? 0);
            $matches_configured = $current_page_id === (int) $page_id;
        }
        if (!$matches_configured) {
            $queried_object = \get_queried_object();
            $matches_configured = $queried_object
                && isset($queried_object->ID)
                && (int) $queried_object->ID === (int) $page_id;
        }

        return $matches_configured;
    }

    public function handleCustomLoginRoute(): void
    {
        // Allow accessing the login page with ?fleek_login=1
        if (isset($_GET['fleek_login']) && $_GET['fleek_login'] === '1') {
            $this->renderLoginPage();
            exit;
        }
    }

    public function renderLoginPage(): void
    {
        // Clear any previous output
        if (\ob_get_level()) {
            \ob_end_clean();
        }

        // Enqueue assets for the login page
        $this->enqueueLoginAssets();

        // Load the template
        $template_path = \FLEEKDASH_DIR . self::TEMPLATE_PATH;
        if (\file_exists($template_path)) {
            include_once $template_path;
        } else {
            \wp_die('Login template not found at: ' . $template_path);
        }
    }

    public function enqueueLoginAssets(): void
    {
        AssetsLib\enqueueAsset(
            \FLEEKDASH_DIR . '/assets',
            self::DEV_SCRIPT,
            [
                'dependencies' => [],
                'handle' => self::HANDLE,
                'in_footer' => true,
            ],
        );
        \wp_localize_script(self::HANDLE, 'fleekdashLogin', $this->getData());
    }

    public function overrideLoginTemplate(string $template): string
    {
        // Check if this is a login page (works even with 404 fixes)
        if ($this->isLoginPage()) {
            $new_template = \FLEEKDASH_DIR . self::TEMPLATE_PATH;
            if (\file_exists($new_template)) {
                return $new_template;
            }
        }

        // Additional check: If page was found via ensure_page_template and is login page
        global $wp_query;
        if (!$wp_query->is_404 && $wp_query->is_page) {
            $page_id = \get_option('fleekdash_login_page_id');
            $current_page_id = $wp_query->queried_object_id ?? 0;

            if ($page_id && (int) $current_page_id === (int) $page_id) {
                $new_template = \FLEEKDASH_DIR . self::TEMPLATE_PATH;
                if (\file_exists($new_template)) {
                    return $new_template;
                }
            }
        }

        return $template;
    }

    public function enqueueAssets(): void
    {
        if ($this->isLoginPage() || isset($_GET['fleek_login'])) {
            AssetsLib\enqueueAsset(
                FLEEKDASH_DIR . '/assets',
                self::DEV_SCRIPT,
                [
                    'dependencies' => [],
                    'handle' => self::HANDLE,
                    'in_footer' => true,
                ],
            );
            \wp_localize_script(self::HANDLE, 'fleekdashLogin', $this->getData());
        }
    }

    public function getData(): array
    {
        return [
            'pluginUrl' => FLEEKDASH_PLUGIN_URL,
            'siteTitle' => \get_bloginfo('name'),
            'siteIcon' => \get_site_icon_url(),
            'appearanceSettings' => [
                'logo' => \get_option('_fleekdash_logo', ''),
                'dark_logo' => \get_option('_fleekdash_dark_logo', ''),
                'use_dark_logo' => \get_option('_fleekdash_use_dark_logo', false),
                'auto_invert_logo_dark_mode' => \get_option('_fleekdash_auto_invert_logo_dark_mode', true),
                'favicon' => \get_option('_fleekdash_favicon', ''),
                'primary_color' => \get_option('_fleekdash_primary_color', '#3858e9'),
                'secondary_color' => \get_option('_fleekdash_secondary_color', '#64748b'),
                'accent_color' => \get_option('_fleekdash_accent_color', '#f59e0b'),
                'sidebar_width' => \get_option('_fleekdash_sidebar_width', '280'),
                'enable_animations' => \get_option('_fleekdash_enable_animations', true),
                'enable_shadows' => \get_option('_fleekdash_enable_shadows', true),
                'enable_rounded_corners' => \get_option('_fleekdash_enable_rounded_corners', true),
                'brand_name' => \get_option('_fleekdash_brand_name', \get_bloginfo('name'))
            ],
            'loginSettings' => [
                'template' => \get_option('fleekdash_login_template', 'split'),
                'split_position' => \get_option('fleekdash_login_split_position', 'right'),
                'custom_illustration' => \get_option('fleekdash_login_custom_illustration', ''),
                'remember_me_default' => (bool)\get_option('fleekdash_login_remember_me_default', false),
                'demo_enabled' => (bool)\get_option('fleekdash_login_demo_enabled', false),
                'demo_user' => $this->getDemoUserData(),
            ]
        ];
    }

    /**
     * Get demo user data for localized script
     *
     * @return array|null
     */
    private function getDemoUserData(): ?array
    {
        $demo_user_id = \get_option('fleekdash_login_demo_user_id', 0);
        if (!$demo_user_id) {
            return null;
        }

        $user = \get_userdata($demo_user_id);
        if (!$user) {
            return null;
        }

        return [
            'user_login' => $user->user_login,
            'user_email' => $user->user_email,
            'display_name' => $user->display_name,
            'demo_token' => \get_option('fleekdash_login_demo_token', ''),
        ];
    }

    /**
     * WordPress passes the default login URL; we replace it from plugin options.
     *
     * @param string $login_url Default URL from core (unused)
     */
    public function customLoginUrl(string $login_url): string // NOSONAR S1172 — required by login_url filter arity
    {
        $page_id = \get_option('fleekdash_login_page_id');
        if ($page_id) {
            return \get_permalink($page_id);
        }

        // Get the URL of the page with slug 'login'
        $login_page = \get_page_by_path(self::PAGE_SLUG);
        if ($login_page) {
            return \get_permalink($login_page->ID);
        }

        // Fallback: Use FleekPages pseudo-page
        return FleekPages::getUrl('login');
    }

    /**
     * Custom logout redirect to use our custom login page
     *
     * @param string $redirect_to The redirect destination URL
     * @param string $requested_redirect_to Requested redirect (unused)
     * @param \WP_User|\WP_Error $user User or error (unused)
     */
    public function customLogoutRedirect(string $redirect_to, string $requested_redirect_to, $user): string // NOSONAR S1172 — logout_redirect passes 3 args
    {
        return $this->customLoginUrl($redirect_to);
    }

    public function redirectUnauthenticatedUsers(): void
    {
        // If trying to access admin and not logged in, redirect to our login page.
        if (\is_admin() && !\is_user_logged_in() && !defined('DOING_AJAX')) {
            \wp_redirect($this->customLoginUrl(\site_url('wp-login.php')));
            exit;
        }
    }

    /**
     * @param int $user_id User ID (unused; auth_cookie_expiration filter arity)
     */
    public function customCookieExpiration(int $expiration, int $user_id, bool $remember): int // NOSONAR S1172 — auth_cookie_expiration passes user id
    {
        if ($remember) {
            $duration_setting = \get_option('fleekdash_login_remember_me_duration', '2_weeks');
            $duration = 14 * DAY_IN_SECONDS; // Default

            switch ($duration_setting) {
                case '1_day':
                    $duration = DAY_IN_SECONDS;
                    break;
                case '1_week':
                    $duration = WEEK_IN_SECONDS;
                    break;
                case '2_weeks':
                    $duration = 2 * WEEK_IN_SECONDS;
                    break;
                case '1_month':
                    $duration = 30 * DAY_IN_SECONDS;
                    break;
                case '3_months':
                    $duration = 90 * DAY_IN_SECONDS;
                    break;
                case '6_months':
                    $duration = 180 * DAY_IN_SECONDS;
                    break;
                case '1_year':
                    $duration = 365 * DAY_IN_SECONDS;
                    break;
                default:
                    break;
            }

            return $duration;
        }

        return $expiration;
    }
}
