import AsyncStorage from "@react-native-async-storage/async-storage"; import { create } from "zustand"; import { createJSONStorage, persist } from "zustand/middleware"; import { DEMO_USER } from "@/lib/data/seed"; export type AuthProvider = | "google" | "email" | "phone" | "telegram" | "guest"; export type AuthUser = { id: string; name: string; phone: string; email?: string; points: number; tier: "bronze" | "silver" | "gold"; isGuest: boolean; biometricEnabled: boolean; avatarUri?: string | null; referralCode?: string; activeVoucher?: string | null; /** How the user signed in (demo providers included). */ authProvider?: AuthProvider; }; export type PointsEntry = { id: string; at: string; label: string; delta: number; balance: number; }; type AuthState = { user: AuthUser | null; hasOnboarded: boolean; ledger: PointsEntry[]; setHasOnboarded: (v: boolean) => void; signIn: ( payload: Partial & { phone: string; name: string; authProvider?: AuthProvider; } ) => void; signOut: () => void; setBiometric: (enabled: boolean) => void; setAvatar: (uri: string | null) => void; updateProfile: ( patch: Partial> ) => void; addPoints: (pts: number, label?: string) => void; redeemPoints: (pts: number) => boolean; setActiveVoucher: (code: string | null) => void; ensureDemoUser: () => void; }; function tierFor(points: number): AuthUser["tier"] { if (points >= 1000) return "gold"; if (points >= 300) return "silver"; return "bronze"; } const seedLedger: PointsEntry[] = [ { id: "pts_1", at: new Date(Date.now() - 1000 * 60 * 60 * 24 * 20).toISOString(), label: "Welcome bonus", delta: 50, balance: 50, }, { id: "pts_2", at: new Date(Date.now() - 1000 * 60 * 60 * 24 * 12).toISOString(), label: "Order reward", delta: 28, balance: 78, }, { id: "pts_3", at: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5).toISOString(), label: "Referral bonus", delta: 100, balance: 178, }, { id: "pts_4", at: new Date(Date.now() - 1000 * 60 * 60 * 24 * 2).toISOString(), label: "Order reward", delta: 242, balance: 420, }, ]; export const useAuthStore = create()( persist( (set, get) => ({ user: { ...DEMO_USER, email: DEMO_USER.email, referralCode: "GISHEN-KIRU", activeVoucher: null, }, hasOnboarded: true, ledger: seedLedger, setHasOnboarded: (v) => set({ hasOnboarded: v }), signIn: ({ phone, name, email, isGuest, avatarUri, authProvider }) => set({ user: { id: `u_${Date.now()}`, name, phone, email, points: isGuest ? 0 : 50, tier: "bronze", isGuest: !!isGuest, biometricEnabled: false, avatarUri: avatarUri ?? null, referralCode: `GISHEN-${name.slice(0, 4).toUpperCase() || "USER"}`, activeVoucher: null, authProvider: authProvider ?? (isGuest ? "guest" : "phone"), }, hasOnboarded: true, ledger: isGuest ? [] : [ { id: `pts_${Date.now()}`, at: new Date().toISOString(), label: "Welcome bonus", delta: 50, balance: 50, }, ], }), signOut: () => set({ user: null }), setBiometric: (enabled) => { const user = get().user; if (!user) return; set({ user: { ...user, biometricEnabled: enabled } }); }, setAvatar: (uri) => { const user = get().user; if (!user) return; set({ user: { ...user, avatarUri: uri } }); }, updateProfile: (patch) => { const user = get().user; if (!user) return; set({ user: { ...user, ...patch } }); }, addPoints: (pts, label = "Order reward") => { const user = get().user; if (!user || user.isGuest || pts === 0) return; const points = user.points + pts; const entry: PointsEntry = { id: `pts_${Date.now()}`, at: new Date().toISOString(), label, delta: pts, balance: points, }; set({ user: { ...user, points, tier: tierFor(points) }, ledger: [entry, ...get().ledger], }); }, redeemPoints: (pts) => { const user = get().user; if (!user || user.isGuest || user.points < pts) return false; const points = user.points - pts; const entry: PointsEntry = { id: `pts_${Date.now()}`, at: new Date().toISOString(), label: `Redeemed for voucher`, delta: -pts, balance: points, }; set({ user: { ...user, points, tier: tierFor(points), activeVoucher: "GISHEN10", }, ledger: [entry, ...get().ledger], }); return true; }, setActiveVoucher: (code) => { const user = get().user; if (!user) return; set({ user: { ...user, activeVoucher: code } }); }, ensureDemoUser: () => { if (!get().user) { set({ user: { ...DEMO_USER, referralCode: "GISHEN-KIRU", activeVoucher: null, }, hasOnboarded: true, ledger: seedLedger, }); } }, }), { name: "gishen-auth", storage: createJSONStorage(() => AsyncStorage), version: 4, migrate: (persisted: unknown) => { const state = (persisted ?? {}) as Partial; if (!state.user) { return { ...state, user: { ...DEMO_USER, referralCode: "GISHEN-KIRU", activeVoucher: null, authProvider: "phone" as const, }, hasOnboarded: true, ledger: seedLedger, }; } return { ...state, user: { ...DEMO_USER, ...state.user, avatarUri: state.user.avatarUri ?? null, referralCode: state.user.referralCode ?? "GISHEN-KIRU", activeVoucher: state.user.activeVoucher ?? null, authProvider: state.user.authProvider ?? (state.user.isGuest ? ("guest" as const) : ("phone" as const)), }, ledger: state.ledger?.length ? state.ledger : seedLedger, }; }, } ) );