import { create, type StoreApi, type UseBoundStore } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";

export type User = {
  id: string;
  name: string;
  email: string;
};

export type Household = {
  id: string;
  name: string;
  role: string;
};

export type AuthState = {
  user: User | null;
  activeHouseholdId: string | null;
  households: Household[];
  isAuthenticated: boolean;
  pendingInvitationId: string | null;
  setUser: (user: User | null) => void;
  setActiveHousehold: (id: string) => void;
  setHouseholds: (households: Household[]) => void;
  setPendingInvitationId: (id: string | null) => void;
  clearAuth: () => void;
  clearSession: () => void;
};

export const authStateCreator = (
  set: (partial: Partial<AuthState>) => void,
): AuthState => ({
  user: null,
  activeHouseholdId: null,
  households: [],
  isAuthenticated: false,
  pendingInvitationId: null,
  setUser: (user) => set({ user, isAuthenticated: !!user }),
  setActiveHousehold: (activeHouseholdId) => set({ activeHouseholdId }),
  setHouseholds: (households) => set({ households }),
  setPendingInvitationId: (pendingInvitationId) => set({ pendingInvitationId }),
  clearAuth: () =>
    set({
      user: null,
      activeHouseholdId: null,
      households: [],
      isAuthenticated: false,
      pendingInvitationId: null,
    }),
  clearSession: () =>
    set({
      user: null,
      activeHouseholdId: null,
      households: [],
      isAuthenticated: false,
    }),
});

// Lazily import SecureStore so it's only resolved at runtime, not at module load.
// This keeps bun:test able to test authStateCreator without React Native internals.
async function getSecureStorage() {
  const SecureStore = await import("expo-secure-store");
  return {
    getItem: (key: string) => SecureStore.getItemAsync(key),
    setItem: (key: string, value: string) => SecureStore.setItemAsync(key, value),
    removeItem: (key: string) => SecureStore.deleteItemAsync(key),
  };
}

let _store: UseBoundStore<StoreApi<AuthState>> | null = null;

export async function getAuthStore() {
  if (_store) return _store;
  const storage = await getSecureStorage();
  _store = create<AuthState>()(
    persist(authStateCreator, {
      name: "auth-store",
      storage: createJSONStorage(() => storage),
    }),
  );
  return _store;
}

// Synchronous store for use in non-async contexts (components).
// Storage hydration happens async — initial state is always the default.
export const useAuthStore = create<AuthState>()(
  persist(authStateCreator, {
    name: "auth-store",
    storage: createJSONStorage(() => ({
      // Lazy proxy — defers the actual SecureStore call to runtime
      getItem: async (key: string) => {
        const { getItemAsync } = await import("expo-secure-store");
        return getItemAsync(key);
      },
      setItem: async (key: string, value: string) => {
        const { setItemAsync } = await import("expo-secure-store");
        return setItemAsync(key, value);
      },
      removeItem: async (key: string) => {
        const { deleteItemAsync } = await import("expo-secure-store");
        return deleteItemAsync(key);
      },
    })),
  }),
);
