import { __awaiter } from "tslib";
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
import React from "react";
import { QoreClient } from "@qorebase/client";
import createQoreHooks from "@qorebase/react";
import { DefaultApiFactory } from "@qorebase/sdk";
const qoreHooks = createQoreHooks(new QoreClient({
    endpoint: "",
}));
const defaultUser = { status: "idle", error: null, user: null };
export const UserContext = React.createContext([defaultUser, () => { }]);
const UserFetcher = () => {
    const client = qore.useClient();
    const user = useCurrentUser();
    React.useEffect(() => {
        if (user.status === "idle") {
            user.refetch();
        }
    }, [client, user.status, user.refetch]);
    return null;
};
const defaultToken = {
    token: "",
    lastFetch: new Date(0),
    isFetching: false,
};
export const StorageTokenContext = React.createContext([defaultToken, () => { }]);
export const useFetchToken = () => {
    const client = qore.useClient();
    const { user } = useCurrentUser();
    const [token, setToken] = React.useContext(StorageTokenContext);
    return React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        if (!user || token.isFetching) {
            return Promise.reject("User is not logged in");
        }
        setToken((token) => (Object.assign(Object.assign({}, token), { isFetching: true })));
        const newToken = yield client.project.axios
            .post("/v1/storage/token")
            .then((res) => res.data.token);
        setToken({ token: newToken, lastFetch: new Date(), isFetching: false });
        return newToken;
    }), [client, user, token.isFetching, setToken]);
};
export const useStorageToken = () => {
    const [token] = React.useContext(StorageTokenContext);
    const fetchToken = useFetchToken();
    React.useEffect(() => {
        if (token.lastFetch.getTime() + 1000 * 60 * 5 < new Date().getTime()) {
            fetchToken().catch(() => { });
        }
    }, [fetchToken, token.token]);
    return token.token;
};
const SDKContext = React.createContext(null);
export const useSDK = () => React.useContext(SDKContext);
export const QoreProvider = (props) => {
    const userContextValue = React.useState(defaultUser);
    const tokenContextValue = React.useState(defaultToken);
    const contextValue = React.useMemo(() => ({ client: props.value }), [props.value]);
    const sdk = React.useMemo(() => {
        var _a, _b;
        return DefaultApiFactory({
            apiKey: props.value.project.config.adminSecret,
            isJsonMime: (mime) => {
                const jsonMime = new RegExp("^(application/json|[^;/ \\t]+/[^;/ \\t]+[+]json)[ \\t]*(;.*)?$", "i");
                return (mime !== null &&
                    (jsonMime.test(mime) ||
                        mime.toLowerCase() === "application/json-patch+json"));
            },
            accessToken: (_b = (_a = props.value.project.config).getToken) === null || _b === void 0 ? void 0 : _b.call(_a),
        }, props.value.project.config.endpoint);
    }, [props.value]);
    return (_jsx(qoreHooks.context.Provider, Object.assign({ value: contextValue }, { children: _jsx(SDKContext.Provider, Object.assign({ value: sdk }, { children: _jsx(UserContext.Provider, Object.assign({ value: userContextValue }, { children: _jsxs(StorageTokenContext.Provider, Object.assign({ value: tokenContextValue }, { children: [_jsx(UserFetcher, {}), props.children] })) })) })) })));
};
export const useCurrentUser = () => {
    const [user, setUser] = React.useContext(UserContext);
    const client = qoreHooks.useClient();
    const refetch = React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
        setUser((user) => (Object.assign(Object.assign({}, user), { status: "loading" })));
        const nextState = yield client
            .currentUser()
            .then((user) => {
            if (typeof user !== "object") {
                return { status: "idle", error: null, user: null };
            }
            return {
                status: "success",
                user,
                error: null,
            };
        })
            .catch((error) => ({
            status: "error",
            user: null,
            error,
        }));
        setUser(nextState);
        return nextState;
    }), [client]);
    const nextUser = React.useMemo(() => (Object.assign(Object.assign({}, user), { refetch })), [user, refetch]);
    return nextUser;
};
const qore = Object.assign(Object.assign({}, qoreHooks), { QoreProvider,
    useCurrentUser,
    useStorageToken,
    useSDK });
export const useClient = qore.useClient;
export default qore;
//# sourceMappingURL=qore.js.map