import { jsx } from "react/jsx-runtime";
import { createContext, useState, useCallback, useEffect, useMemo } from "react";
import { useSessionToken } from "@contember/react-client";
import { Message, ContainerSpinner } from "@contember/ui";
import { MiscPageLayout } from "../MiscPageLayout.js";
import { InvalidIdentityFallback } from "./InvalidIdentityFallback.js";
import { useLogout } from "./useLogout.js";
import { EnvironmentExtensionProvider } from "@contember/binding";
import { identityEnvironmentExtension } from "./IdentityEnvironmentExtension.js";
import { useFetchMe } from "../../tenant/queries/me.js";
const IdentityContext = createContext(void 0);
const IdentityRefreshContext = createContext(() => {
  throw new Error("IdentityRefreshContext is not initialized");
});
const IdentityProvider = ({ children, onInvalidIdentity, allowUnauthenticated }) => {
  const sessionToken = useSessionToken();
  const fetchMe = useFetchMe();
  const [identityState, setIdentityState] = useState(() => ({ state: sessionToken ? "loading" : "none" }));
  const logout = useLogout();
  const clearIdentity = useCallback(() => setIdentityState({ state: "cleared" }), []);
  const refetch = useCallback(async () => {
    setIdentityState({ state: "loading" });
    try {
      const response = await fetchMe();
      const person = response.data.me.person;
      const projects = response.data.me.projects;
      const permissions = response.data.me.permissions;
      setIdentityState({
        state: "success",
        identity: {
          id: response.data.me.id,
          person: person ?? void 0,
          projects: projects.map((it) => ({
            name: it.project.name,
            slug: it.project.slug,
            roles: it.memberships.map((it2) => it2.role)
          })),
          permissions,
          email: person?.email ?? void 0,
          otpEnabled: person?.otpEnabled ?? void 0,
          personId: person?.id ?? void 0
        }
      });
    } catch (e) {
      console.error(e);
      if (typeof e === "object" && e !== null && "status" in e && e.status === 401) {
        logout({ noRedirect: true });
        clearIdentity();
        if (onInvalidIdentity) {
          onInvalidIdentity();
        } else if (window.location.pathname !== "/") {
          window.location.href = "/";
        }
      } else {
        setIdentityState({ state: "failed" });
      }
    }
  }, [clearIdentity, fetchMe, logout, onInvalidIdentity]);
  useEffect(
    () => {
      if (sessionToken === void 0) {
        setIdentityState({ state: "none" });
        if (!allowUnauthenticated) {
          if (onInvalidIdentity) {
            onInvalidIdentity();
          } else if (window.location.pathname !== "/") {
            window.location.href = "/";
          }
        }
        return;
      }
    },
    [sessionToken, allowUnauthenticated, onInvalidIdentity]
  );
  useEffect(
    () => {
      if (sessionToken !== void 0) {
        refetch();
      }
    },
    [sessionToken, refetch]
  );
  const identityContextValue = useMemo(
    () => identityState.state === "success" ? { clearIdentity, identity: identityState.identity } : void 0,
    [identityState, clearIdentity]
  );
  if (identityState.state === "cleared") {
    return /* @__PURE__ */ jsx(MiscPageLayout, { children: /* @__PURE__ */ jsx(Message, { size: "large", flow: "generousBlock", children: "Logging out…" }) });
  }
  if (identityState.state === "failed") {
    return /* @__PURE__ */ jsx(InvalidIdentityFallback, {});
  }
  if (identityState.state === "loading" || !allowUnauthenticated && identityState.state === "none") {
    return /* @__PURE__ */ jsx(ContainerSpinner, {});
  }
  return /* @__PURE__ */ jsx(EnvironmentExtensionProvider, { extension: identityEnvironmentExtension, state: identityContextValue?.identity ?? null, children: /* @__PURE__ */ jsx(IdentityContext.Provider, { value: identityContextValue, children: /* @__PURE__ */ jsx(IdentityRefreshContext.Provider, { value: refetch, children }) }) });
};
export {
  IdentityContext,
  IdentityProvider,
  IdentityRefreshContext
};
//# sourceMappingURL=IdentityProvider.js.map
