import { browser } from "$app/environment";
import type { UserRole } from "$lib/server/auth/authorization-service";
import { writable } from "svelte/store";

export interface PasskeyAuthData {
  authenticatorData: string;
  passkeyId: string;
  email: string;
  prfOutput?: string; // Base64-encoded PRF output for staff crypto key derivation
}

export interface AuthState {
  isAuthenticated: boolean;
  refreshPromise: Promise<Response> | null;
  user?: {
    id: string;
    email: string;
    name: string;
    role: UserRole;
    // The currently selected tenant
    tenantId?: string | null;
  };
  passkeyAuthData?: PasskeyAuthData;
}

function createAuthStore() {
  const store = writable<AuthState>({
    isAuthenticated: false,
    refreshPromise: null,
  });

  return {
    ...store,
    setAuthenticated: (isAuthenticated: boolean) => {
      store.update((state) => ({ ...state, isAuthenticated }));
    },
    setRefreshPromise: (promise: Promise<Response> | null) => {
      store.update((state) => ({ ...state, refreshPromise: promise }));
    },
    setUser: (user: AuthState["user"]) => {
      store.update((state) => ({ ...state, isAuthenticated: true, user }));

      if (browser && user) {
        const storageItem = sessionStorage.getItem("passkeyAuthData");
        if (storageItem) {
          const passkeyAuthData: PasskeyAuthData = JSON.parse(storageItem);
          store.update((state) => ({ ...state, passkeyAuthData }));
        }
      }
    },
    setTenantId: (tenantId: string | null) => {
      store.update((state) => {
        if (!state.user) return state;
        return { ...state, user: { ...state.user, tenantId } };
      });
    },
    reset: () => {
      store.set({
        isAuthenticated: false,
        refreshPromise: null,
        user: undefined,
        passkeyAuthData: undefined,
      });
    },
    setPasskeyAuthData: (data: PasskeyAuthData) => {
      store.update((state) => ({ ...state, passkeyAuthData: data }));
      sessionStorage.setItem("passkeyAuthData", JSON.stringify(data));
    },
    getPasskeyAuthData: (): PasskeyAuthData | undefined => {
      let authState: AuthState;
      const unsubscribe = store.subscribe((state) => {
        authState = state;
      });
      unsubscribe();
      return authState!.passkeyAuthData;
    },
    clearPasskeyAuthData: () => {
      store.update((state) => ({ ...state, passkeyAuthData: undefined }));
      sessionStorage.removeItem("passkeyAuthData");
    },
    isAuthenticated: () => {
      let authState: AuthState;
      const unsubscribe = store.subscribe((state) => {
        authState = state;
      });
      unsubscribe();
      return authState!.isAuthenticated;
    },
    getTenant: () => {
      let authState: AuthState;
      const unsubscribe = store.subscribe((state) => {
        authState = state;
      });
      unsubscribe();
      return authState!.user?.tenantId || null;
    },
    waitForRefresh: async () => {
      let authState: AuthState;
      const unsubscribe = store.subscribe((state) => {
        authState = state;
      });
      unsubscribe();

      if (authState!.refreshPromise) {
        await authState!.refreshPromise;
      }
    },
  };
}

export const auth = createAuthStore();
