import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import { Button, Center, ErrorBox, Input, SelectBox, Spinner, useFetch, useToast } from '@vertesia/ui/core';
import { Env } from "@vertesia/ui/env";
import { useLocation } from "@vertesia/ui/router";
import { fetchComposableTokenFromFirebaseToken, useUserSession } from '@vertesia/ui/session';
function getClientInfo(location) {
    const params = new URLSearchParams(location.search);
    let redirect = params.get('redirect_uri');
    const code = params.get('code');
    if (!redirect || !code) {
        return null;
    }
    redirect = decodeURI(redirect);
    if (!redirect.startsWith('http://127.0.0.1:') && !redirect.startsWith('http://localhost:')) {
        return null;
    }
    const profile = params.get('profile') ?? "default";
    const project = params.get('project') ?? undefined;
    const account = params.get('account') ?? undefined;
    return { redirect, code, profile, project, account };
}
export function TerminalLogin() {
    const [payload, setPayload] = useState();
    const [error, setError] = useState();
    const location = useLocation();
    const clientInfo = getClientInfo(location);
    const toast = useToast();
    const onAccept = async (data) => {
        if (!clientInfo)
            return;
        if (!data.profile) {
            toast({
                title: 'Profile is required',
                description: 'Please enter a profile name to save the client authorization',
                status: 'error',
                duration: 2000
            });
            return;
        }
        if (!data.account) {
            toast({
                title: 'Account is required',
                description: 'Please select an account to authorize the client to access the ComposablePrompts servers',
                status: 'error',
                duration: 2000
            });
            return;
        }
        if (!data.project) {
            toast({
                title: 'Project is required',
                description: 'Please select a project to authorize the client to access the ComposablePrompts servers',
                status: 'error',
                duration: 2000
            });
            return;
        }
        // expire in 1 day
        let payload;
        try {
            const token = await fetchComposableTokenFromFirebaseToken(data.account, data.project, 24 * 3600);
            if (token) {
                payload = {
                    ...data,
                    studio_server_url: Env.endpoints.studio,
                    zeno_server_url: Env.endpoints.zeno,
                    token,
                };
                await fetch(clientInfo.redirect, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(payload)
                });
                setPayload(payload);
            }
            else {
                toast({
                    title: 'Failed to get composable token',
                    status: 'error',
                    duration: 5000
                });
            }
        }
        catch (err) {
            if (payload) {
                setError(err);
                setPayload(payload);
            }
            else {
                toast({
                    title: 'Error authorizing client',
                    description: err.message,
                    status: 'error',
                    duration: 5000
                });
            }
        }
    };
    const getPageContent = () => {
        if (!clientInfo) {
            return _jsx(ErrorBox, { title: 'Invalid request', children: "This page should be called by a terminal client to authenticate against the ComposablePrompts servers" });
        }
        return payload
            ? _jsx(AuthDoneScreen, { payload: payload, error: error })
            : _jsx(AuthAcceptScreen, { clientInfo: clientInfo, onAccept: onAccept });
    };
    const page = getPageContent();
    return (_jsx("div", { className: "w-full flex flex-col items-center gap-4 mt-24", children: page }));
}
function AuthAcceptScreen({ onAccept, clientInfo }) {
    const { client, user } = useUserSession();
    const { data: allProjects, error } = useFetch(() => user ? client.projects.list() : Promise.resolve([]), [user]);
    if (error) {
        return _jsx(ErrorBox, { title: 'Error loading projects', children: error.message });
    }
    const getEnvironmentName = () => {
        if (Env.isLocalDev) {
            return "Local Dev";
        }
        else if (Env.isDev) {
            return "Staging";
        }
        return "Production";
    };
    const envName = getEnvironmentName();
    return user && allProjects ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: 'w-1/3', children: [_jsxs("div", { className: "mb-4 text-xl font-semibold text-gray-800", children: ["Authorizing client on ", envName, " environment."] }), _jsxs("div", { className: 'mb-2 text-md text-gray-800', children: [_jsx("div", { children: "A client app wants authorization to access the composable prompt servers in your name." }), _jsxs("div", { children: ["The client app code is ", _jsx("b", { children: clientInfo.code }), ". You can check if the code is correct in the terminal."] })] }), _jsxs("div", { className: 'mb-2 text-sm text-gray-600', children: [_jsx("div", { children: "You must choose the target account and project for the client to access." }), _jsx("div", { children: "Also, enter a profile name that will be used to save the authorization in your client configuration." })] })] }), _jsx(ProfileForm, { onAccept: onAccept, allProjects: allProjects, data: clientInfo })] })) : _jsx(Spinner, { size: 'lg' });
}
function AuthDoneScreen({ payload, error }) {
    const toast = useToast();
    const onCopy = () => {
        if (payload) {
            navigator.clipboard.writeText(JSON.stringify(payload));
            toast({
                title: 'Authentication Payload copied',
                description: error ? 'You can paste the authentication payload in the terminal to authenticate the client.' : 'You can close the page now.',
                status: 'success',
                duration: 5000
            });
        }
    };
    return (_jsxs("div", { children: [error ?
                _jsxs("div", { children: [_jsxs(ErrorBox, { title: 'Failed to send the authorization token to the cli tool', children: ["This can happen due to security checks on Safari. The error is \"", error.message, "\""] }), _jsx("div", { children: "Don't worry, you can still authenticate the cli tool by pasting the authentication token in the terminal. You can close this page." })] })
                : _jsx("div", { children: "The client is authenticated. You can close this page." }), _jsx(Center, { className: "mt-4", children: _jsx(Button, { variant: 'secondary', onClick: onCopy, children: "Copy the Authentication Payload" }) })] }));
}
function ProfileForm({ allProjects, data, onAccept }) {
    const { accounts, account, project } = useUserSession();
    const [currentData, setCurrentData] = useState(() => ({
        profile: data.profile,
        account: data.account ?? account?.id,
        project: data.project ?? project?.id,
    }));
    const onChangeProfile = (value) => {
        setCurrentData({ ...currentData, profile: value });
    };
    const onChangeAccount = (value) => {
        setCurrentData({ ...currentData, account: value.id, project: undefined });
    };
    const onChangeProject = (value) => {
        setCurrentData({ ...currentData, project: value.id });
    };
    const projects = allProjects.filter(p => p.account === currentData.account);
    return (_jsxs("div", { className: 'w-1/3', children: [_jsxs("div", { className: "mb-4 flex flex-col gap-2", children: [_jsx("span", { className: "font-semibold text-gray-600", children: "Profile Name" }), _jsx(Input, { type: 'text', value: currentData.profile, onChange: onChangeProfile })] }), _jsxs("div", { className: "mb-4 flex flex-col gap-2", children: [_jsx("span", { className: "font-semibold text-gray-600", children: "Account" }), _jsx(SelectAccount, { value: currentData.account, onChange: onChangeAccount, accounts: accounts || [] })] }), _jsxs("div", { className: "mb-4 flex flex-col gap-2", children: [_jsx("span", { className: "font-semibold text-gray-600", children: "Project" }), _jsx(SelectProject, { value: currentData.project, onChange: onChangeProject, projects: projects })] }), _jsx("div", { className: "pt-2", children: _jsx(Button, { size: 'xl', onClick: () => onAccept(currentData), children: "Authorize Client" }) })] }));
}
function SelectAccount({ value, accounts, onChange }) {
    const _onChange = (value) => {
        onChange(value);
    };
    return _jsx(SelectBox, { options: accounts, value: accounts?.find(a => a.id === value), onChange: _onChange, by: "id", optionLabel: (option) => option.name, placeholder: 'Select Account' });
}
function SelectProject({ value, projects, onChange }) {
    const _onChange = (value) => {
        onChange(value);
    };
    return (_jsx(SelectBox, { by: "id", value: projects.find(p => p.id === value), options: projects, optionLabel: (option) => option.name, placeholder: 'Select Project', onChange: _onChange }));
}
//# sourceMappingURL=TerminalLogin.js.map