import { createEffect, createSignal, createMemo, JSXElement } from "solid-js";
import html from "solid-js/html";
import { useAuth } from "./AuthContext.ts";
import { getToken } from "./useAuthFetch.js";
import { hasPermission } from "./permissions.ts";
import { Loader } from "../kit/General.tsx";

interface ProtectedRouteProps {
    permissions?: string[];
    children?: JSXElement;
}

export function ProtectedRoute(props: ProtectedRouteProps) {
    const auth = useAuth();
    const [isRedirecting, setIsRedirecting] = createSignal(false);

    createEffect(() => {
        // Redirect to login ONLY when there is genuinely no session. A real
        // 401 clears the token (so getToken() is null here), but a transient
        // check failure preserves it -- in that case we keep the user here and
        // show a retry screen instead of logging them out. -mta 6/3/26
        if (!auth.loading() && !auth.isAuthenticated() && !getToken() && !isRedirecting()) {
            setIsRedirecting(true);
            const returnUrl = encodeURIComponent(window.location.pathname + window.location.search);
            window.location.replace(`/login?redirect=${returnUrl}`);
        }
    });

    const hasRequiredPermissions = createMemo(() => {
        const permissions = props.permissions || [];
        if (permissions.length === 0) return true;
        const userPermissions = auth.identity()?.permissions || [];
        return permissions.every((perm) => hasPermission(userPermissions, perm));
    });

    const state = createMemo(() => {
        if (isRedirecting() || auth.loading()) return 'loading';
        if (!auth.isAuthenticated()) {
            // Token still present => the check failed transiently => offer a
            // retry. No token => the redirect effect is taking over.
            return getToken() ? 'error' : 'loading';
        }
        if (!hasRequiredPermissions()) return 'unauthorized';
        return 'ready';
    });

    return html`<div>
        ${() => state() === 'loading' && html`<${Loader} />`}
        ${() => state() === 'error' && html`<div class="flex flex-col items-center justify-center min-h-[50vh] text-center p-8">
            <h1 class="text-2xl font-semibold text-neutral-800 mb-2">Connection problem</h1>
            <p class="text-neutral-600 mb-4">We couldn't verify your session. You're still signed in -- please try again.</p>
            <button onclick=${() => auth.checkAuth()} class="text-sky-600 hover:text-sky-800 hover:underline">Retry</button>
        </div>`}
        ${() => state() === 'unauthorized' && html`<div class="flex flex-col items-center justify-center min-h-[50vh] text-center p-8">
            <h1 class="text-2xl font-semibold text-neutral-800 mb-2">Access Denied</h1>
            <p class="text-neutral-600 mb-4">You don't have permission to access this page.</p>
            <a href="/app/dashboard" class="text-sky-600 hover:text-sky-800 hover:underline">Return to Dashboard</a>
        </div>`}
        ${() => state() === 'ready' && props.children}
    </div>`;
}
