<?php

declare(strict_types=1);

namespace FleekDash\Admin\Iframe;

use FleekDash\Admin\AdminWordPressToolbarPolicy;

/**
 * Native WP admin bar visibility inside FleekDash shell iframes (fleekdash-frame=1).
 */
final class EmbeddedShellAdminBarPolicy
{
    /**
     * Set on {@see apply} for first-paint scripts (admin_head blocking).
     */
    private static bool $nativeAdminBarVisibleInEmbed = false;

    /**
     * Prevents duplicate filter registration when policy runs on current_screen and again on admin_head.
     * Scoped to the current HTTP request — reset via {@see resetRequestState} on plugins_loaded.
     */
    private static bool $applied = false;

    /**
     * Clears per-request static state (PHP-FPM workers reuse the same process across requests).
     */
    public static function resetRequestState(): void
    {
        self::$applied = false;
        self::$nativeAdminBarVisibleInEmbed = false;
    }

    /** @var list<string> */
    private const IFRAME_WINDOWED_COMPAT_MODES = [
        'windowed',
        'windowed-light',
        'windowed-dark',
        'trusted',
    ];

    public static function isNativeAdminBarVisibleInEmbed(): bool
    {
        return self::$nativeAdminBarVisibleInEmbed;
    }

    /**
     * FleekDash shell iframe: hide the native WP toolbar for fleekdash-frame=1 by default (protected / minimal).
     *
     * Fires action `fleekdash_iframe_admin_bar_current_screen` with the active screen (extension point).
     */
    public static function apply(\WP_Screen $screen): void
    {
        if (self::$applied) {
            return;
        }

        if (!IframeRequestContext::detectIframeContext()) {
            return;
        }

        self::$applied = true;
        self::$nativeAdminBarVisibleInEmbed = false;

        \do_action('fleekdash_iframe_admin_bar_current_screen', $screen);

        $adminbarParam = isset($_GET['adminbar']) ? \sanitize_text_field((string) $_GET['adminbar']) : '';
        $adminbarParam = self::normalizeIframeAdminbarQueryForScreen($screen, $adminbarParam);
        $_GET['adminbar'] = $adminbarParam;

        $wantsNativeBar = $adminbarParam === 'true' || $adminbarParam === 'on';

        if (!$wantsNativeBar) {
            $_GET['adminbar'] = 'false';
            $adminbarParam = 'false';
        }

        $hideAdminbar = $adminbarParam === 'false' || $adminbarParam === 'off';
        if ($hideAdminbar) {
            \add_filter('show_admin_bar', '__return_false');
            \add_filter('admin_body_class', fn ($classes) => $classes . ' fleekdash-adminbar-hidden');
            \add_filter('body_class', fn (array $classes) => array_merge($classes, ['fleekdash-adminbar-hidden']));

            return;
        }

        if (self::shouldExposeNativeAdminBarInEmbed($screen, $adminbarParam)) {
            self::$nativeAdminBarVisibleInEmbed = true;
            \add_filter(
                'admin_body_class',
                fn ($classes) => $classes . ' fleekdash-adminbar-native-visible',
            );
            \add_filter(
                'body_class',
                fn (array $classes) => array_merge($classes, ['fleekdash-adminbar-native-visible']),
            );
        }
    }

    /**
     * Apply policy before first-paint scripts when {@see current_screen} has not run yet.
     */
    public static function ensureApplied(): void
    {
        $canApply = !self::$applied
            && IframeRequestContext::detectIframeContext()
            && \function_exists('get_current_screen');

        if (!$canApply) {
            return;
        }

        $screen = \get_current_screen();
        if ($screen instanceof \WP_Screen) {
            self::apply($screen);
        }
    }

    /**
     * @param 'true'|'false'|'on'|'off' $adminbarParam
     */
    private static function shouldExposeNativeAdminBarInEmbed(\WP_Screen $screen, string $adminbarParam): bool
    {
        $wantsNativeBar = $adminbarParam === 'true' || $adminbarParam === 'on';
        $isBlockEditor = \method_exists($screen, 'is_block_editor') && $screen->is_block_editor();

        global $pagenow;
        $isSiteEditor = isset($pagenow) && $pagenow === 'site-editor.php';
        $fromFilter = (bool) \apply_filters('fleekdash_admin_bar_native_visible_in_embed', false, $screen);

        return $wantsNativeBar && ($isBlockEditor || $isSiteEditor || $fromFilter);
    }

    /**
     * @param 'true'|'false'|'on'|'' $current
     * @return 'true'|'false'|'on'
     */
    private static function normalizeIframeAdminbarQueryForScreen(\WP_Screen $screen, string $current): string
    {
        if (self::isExplicitAdminbarOff($current)) {
            return 'false';
        }

        if (self::isWindowedCompatMode()) {
            return self::normalizeWindowedAdminbarParam($screen, $current);
        }

        return self::normalizeShellLikeAdminbarParam($screen, $current);
    }

    private static function isExplicitAdminbarOff(string $current): bool
    {
        return $current === 'false' || $current === 'off';
    }

    private static function isExplicitAdminbarOn(string $current): bool
    {
        return $current === 'true' || $current === 'on';
    }

    private static function isWindowedCompatMode(): bool
    {
        $compat = isset($_GET['fleek-compat']) ? \sanitize_text_field((string) $_GET['fleek-compat']) : '';

        return \in_array($compat, self::IFRAME_WINDOWED_COMPAT_MODES, true);
    }

    /**
     * @param 'true'|'false'|'on'|'' $current
     * @return 'true'|'false'
     */
    private static function normalizeWindowedAdminbarParam(\WP_Screen $screen, string $current): string
    {
        if (self::isExplicitAdminbarOn($current)) {
            return 'true';
        }

        return self::shouldSuppressAdminbarOnWindowedScreen($screen) ? 'false' : 'true';
    }

    private static function shouldSuppressAdminbarOnWindowedScreen(\WP_Screen $screen): bool
    {
        $fromFilter = (bool) \apply_filters('fleekdash_admin_bar_suppress_on_admin_screen', false, $screen);
        $markerBleed = AdminWordPressToolbarPolicy::screenIdSuggestsFullBleedPackagedUi($screen);

        return $fromFilter || $markerBleed;
    }

    /**
     * @param 'true'|'false'|'on'|'' $current
     * @return 'true'|'false'|'on'
     */
    private static function normalizeShellLikeAdminbarParam(\WP_Screen $screen, string $current): string
    {
        $normalized = 'false';

        if (self::isAdminPhpScreen()) {
            $normalized = self::screenUsesBlockEditor($screen) ? 'true' : 'false';
        } elseif (self::isExplicitAdminbarOn($current)) {
            $normalized = $current;
        }

        return $normalized;
    }

    private static function isAdminPhpScreen(): bool
    {
        global $pagenow;

        return isset($pagenow) && \is_string($pagenow) && $pagenow === 'admin.php';
    }

    private static function screenUsesBlockEditor(\WP_Screen $screen): bool
    {
        return \method_exists($screen, 'is_block_editor') && $screen->is_block_editor();
    }
}
