<?php

declare(strict_types=1);

namespace FleekDash\Admin;

/**
 * Class Mount
 *
 * Manages the React mount point in the admin.
 *
 * @package FleekDash\Admin
 */
class Mount
{
    /**
     * Initializes hooks related to the mount point
     */
    public function bootstrap()
    {
        // Adds the React mount point to all admin pages
        \add_action('in_admin_header', array($this, 'addMountPoint'), 0);
    }

    /**
     * Adds the React mount point
     */
    public function addMountPoint()
    {
        // Adds the mount point only if not in an iframe and on the FleekDash page
        if (
            !isset($_GET['fleekdash-frame'])
            && isset($_GET['page'])
            && $_GET['page'] === 'fleekdash'
        ) {
            remove_all_actions('admin_notices');
            remove_all_actions('all_admin_notices');
            ?>
            <style>
                @keyframes fleekdash-boot-spin { to { transform: rotate(360deg); } }
                #fleekdash.fleekdash-app {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    min-height: 100vh;
                    background-color: #ffffff;
                }
                #fleekdash:not(.fleekdash-app) {
                    display: block;
                    width: 100%;
                    min-height: 100vh;
                }
                #fleekdash .fleekdash-boot-fallback {
                    width: 2rem;
                    height: 2rem;
                    border: 3px solid #e5e7eb;
                    border-top-color: #9ca3af;
                    border-radius: 9999px;
                    animation: fleekdash-boot-spin 0.75s linear infinite;
                    box-sizing: border-box;
                }
                .fleekdash-admin-recovery {
                    position: fixed;
                    inset: auto 1rem 1rem 1rem;
                    z-index: 100000;
                    display: flex;
                    flex-direction: column;
                    gap: 0.75rem;
                    max-width: 38rem;
                    margin: 0 auto;
                    padding: 1rem 1.125rem;
                    border-radius: 0.75rem;
                    border: 1px solid #f97316;
                    border-left-width: 4px;
                    background: #fff7ed;
                    color: #9a3412;
                    box-shadow: 0 10px 30px rgba(15, 23, 42, 0.15);
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                    font-size: 13px;
                    line-height: 1.5;
                }
                .fleekdash-admin-recovery[hidden] {
                    display: none !important;
                }
                .fleekdash-admin-recovery__header {
                    display: flex;
                    align-items: flex-start;
                    gap: 0.625rem;
                }
                .fleekdash-admin-recovery__icon {
                    flex-shrink: 0;
                    width: 1.25rem;
                    height: 1.25rem;
                    margin-top: 0.125rem;
                    color: #ea580c;
                }
                .fleekdash-admin-recovery__title {
                    flex: 1;
                    margin: 0;
                    font-weight: 600;
                    color: #7c2d12;
                }
                .fleekdash-admin-recovery__dismiss {
                    flex-shrink: 0;
                    margin: 0;
                    padding: 0.125rem 0.375rem;
                    border: 0;
                    border-radius: 0.375rem;
                    background: transparent;
                    color: #9a3412;
                    font-size: 1.125rem;
                    line-height: 1;
                    cursor: pointer;
                }
                .fleekdash-admin-recovery__dismiss:hover {
                    background: rgba(234, 88, 12, 0.12);
                }
                .fleekdash-admin-recovery__actions {
                    display: flex;
                    flex-wrap: wrap;
                    gap: 0.5rem;
                    padding-left: 1.875rem;
                }
                .fleekdash-admin-recovery__action {
                    display: inline-flex;
                    align-items: center;
                    justify-content: center;
                    min-height: 2rem;
                    padding: 0.375rem 0.875rem;
                    border-radius: 0.5rem;
                    font-weight: 600;
                    font-size: 12px;
                    line-height: 1.2;
                    text-decoration: none;
                    transition: background-color 0.15s ease, color 0.15s ease;
                }
                .fleekdash-admin-recovery__action--primary {
                    border: 1px solid #fdba74;
                    background: #ffffff;
                    color: #9a3412;
                }
                .fleekdash-admin-recovery__action--primary:hover {
                    background: #ffedd5;
                    color: #7c2d12;
                }
                .fleekdash-admin-recovery__action--danger {
                    border: 1px solid #fecaca;
                    background: #fef2f2;
                    color: #b91c1c;
                }
                .fleekdash-admin-recovery__action--danger:hover {
                    background: #fee2e2;
                    color: #991b1b;
                }
                .fleekdash-admin-recovery-hint {
                    position: fixed;
                    inset: auto 1rem 1rem 1rem;
                    z-index: 99999;
                    max-width: 32rem;
                    margin: 0 auto;
                    padding: 0.75rem 1rem;
                    border-radius: 0.625rem;
                    border: 1px solid #e2e8f0;
                    background: #f8fafc;
                    color: #475569;
                    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08);
                    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                    font-size: 13px;
                    line-height: 1.45;
                }
                .fleekdash-admin-recovery-hint[hidden] {
                    display: none !important;
                }
                .fleekdash-admin-recovery-hint p {
                    margin: 0 0 0.5rem;
                }
                .fleekdash-admin-recovery-hint a {
                    color: #334155;
                    font-weight: 600;
                    text-decoration: underline;
                }
            </style>
            <div id="fleekdash" class="fleekdash-app" data-fleekdash-boot-state="pending" style="display: flex; min-height: 100vh; background-color: #ffffff;">
                <output class="fleekdash-boot-fallback" aria-label="Loading"></output>
            </div>
            <?php
            $this->renderAdminRecoveryFallback();
            // Prevents WordPress from rendering the default wpbody
            remove_all_actions('admin_footer');
            \add_action('admin_footer', function () {
                // Adds only necessary scripts
                \do_action('admin_print_footer_scripts');
            });
        }
    }

    /**
     * Server-rendered escape hatch when the React shell fails to boot (no JS required for noscript).
     */
    private function renderAdminRecoveryFallback(): void
    {
        $classic_url = \esc_url(\admin_url('index.php?fleekdash=off'));
        $disable_url = \esc_url(\admin_url('plugins.php?fleekdash=disable'));
        ?>
        <div id="fleekdash-admin-recovery-hint" class="fleekdash-admin-recovery-hint" hidden>
            <p><?php echo \esc_html__('Still loading FleekDash… On slower connections this can take up to a minute.', 'fleekdash'); ?></p>
            <a href="<?php echo $classic_url; ?>"><?php echo \esc_html__('Open classic WordPress admin', 'fleekdash'); ?></a>
        </div>
        <div id="fleekdash-admin-recovery" class="fleekdash-admin-recovery" hidden role="alert">
            <div class="fleekdash-admin-recovery__header">
                <svg class="fleekdash-admin-recovery__icon" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                    <path d="M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
                <p class="fleekdash-admin-recovery__title"><?php echo \esc_html__('FleekDash could not finish loading.', 'fleekdash'); ?></p>
                <button type="button" class="fleekdash-admin-recovery__dismiss" data-fleekdash-recovery-dismiss aria-label="<?php echo \esc_attr__('Dismiss', 'fleekdash'); ?>">&times;</button>
            </div>
            <div class="fleekdash-admin-recovery__actions">
                <a class="fleekdash-admin-recovery__action fleekdash-admin-recovery__action--primary" href="<?php echo $classic_url; ?>"><?php echo \esc_html__('Open native WordPress admin', 'fleekdash'); ?></a>
                <a class="fleekdash-admin-recovery__action fleekdash-admin-recovery__action--danger" href="<?php echo $disable_url; ?>"><?php echo \esc_html__('Disable FleekDash (emergency)', 'fleekdash'); ?></a>
            </div>
        </div>
        <noscript>
            <div class="fleekdash-admin-recovery" role="alert">
                <div class="fleekdash-admin-recovery__header">
                    <svg class="fleekdash-admin-recovery__icon" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                        <path d="M12 9v4m0 4h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                    <p class="fleekdash-admin-recovery__title"><?php echo \esc_html__('JavaScript is required for FleekDash.', 'fleekdash'); ?></p>
                </div>
                <div class="fleekdash-admin-recovery__actions">
                    <a class="fleekdash-admin-recovery__action fleekdash-admin-recovery__action--primary" href="<?php echo $classic_url; ?>"><?php echo \esc_html__('Open native WordPress admin', 'fleekdash'); ?></a>
                    <a class="fleekdash-admin-recovery__action fleekdash-admin-recovery__action--danger" href="<?php echo $disable_url; ?>"><?php echo \esc_html__('Disable FleekDash (emergency)', 'fleekdash'); ?></a>
                </div>
            </div>
        </noscript>
        <script id="fleekdash-admin-recovery-watch">
        (function () {
            var mount = document.getElementById("fleekdash");
            var recovery = document.getElementById("fleekdash-admin-recovery");
            var hint = document.getElementById("fleekdash-admin-recovery-hint");
            if (!mount || !recovery) {
                return;
            }

            var HINT_DELAY_MS = 20000;
            var ALERT_DELAY_MS = 75000;

            function hideRecoveryUi() {
                recovery.hidden = true;
                if (hint) {
                    hint.hidden = true;
                }
            }

            function isBootPending() {
                return mount.getAttribute("data-fleekdash-boot-state") === "pending";
            }

            function markBootReady() {
                mount.setAttribute("data-fleekdash-boot-state", "ready");
                hideRecoveryUi();
            }

            globalThis.__fleekdashMarkBootReady = markBootReady;

            function showHint() {
                if (!isBootPending() || !hint || !recovery.hidden) {
                    return;
                }
                hint.hidden = false;
            }

            function showAlert() {
                if (!isBootPending()) {
                    return;
                }
                if (hint) {
                    hint.hidden = true;
                }
                recovery.hidden = false;
            }

            function isFleekdashAssetUrl(url) {
                if (!url) {
                    return false;
                }
                return url.indexOf("fleekdash") !== -1 || url.indexOf("/plugins/fleekdash/") !== -1;
            }

            function maybeShowAlertFromBootFailure(source) {
                if (!isBootPending()) {
                    return;
                }
                if (!isFleekdashAssetUrl(source)) {
                    return;
                }
                showAlert();
            }

            var dismissButton = recovery.querySelector("[data-fleekdash-recovery-dismiss]");
            if (dismissButton) {
                dismissButton.addEventListener("click", hideRecoveryUi);
            }

            var observer = new MutationObserver(function () {
                if (!isBootPending()) {
                    hideRecoveryUi();
                }
            });
            observer.observe(mount, {
                attributes: true,
                attributeFilter: ["data-fleekdash-boot-state", "class"],
            });

            globalThis.addEventListener(
                "error",
                function (event) {
                    var target = event.target;
                    if (!target || typeof target !== "object") {
                        return;
                    }
                    var tagName = target.tagName || "";
                    if (tagName !== "SCRIPT" && tagName !== "LINK") {
                        return;
                    }
                    maybeShowAlertFromBootFailure(target.src || target.href || "");
                },
                true,
            );

            globalThis.addEventListener("unhandledrejection", function (event) {
                var reason = event.reason;
                var message =
                    reason && typeof reason === "object" && reason.message
                        ? String(reason.message)
                        : String(reason || "");
                if (
                    /Failed to fetch dynamically imported module|Unable to preload CSS|Importing a module script failed/i.test(
                        message,
                    )
                ) {
                    showAlert();
                }
            });

            globalThis.setTimeout(showHint, HINT_DELAY_MS);
            globalThis.setTimeout(function () {
                if (isBootPending()) {
                    showAlert();
                }
            }, ALERT_DELAY_MS);
        })();
        </script>
        <?php
    }

}
