"use client" import { create } from "zustand" import { persist } from "zustand/middleware" import { debouncedPersistJSONStorage } from "@/lib/stores/debounced-json-storage" import { useSessionGuardStore } from "@/lib/auth/session-guard-store" import type { PlatformUser } from "@/lib/auth/jwt-claims" const AUTH_STORAGE_KEY = "ulti-auth" const LEGACY_AUTH_KEYS = ["ultimail-auth", "ultidrive-auth"] as const export { AUTH_STORAGE_KEY, LEGACY_AUTH_KEYS } function migrateLegacyAuthStorage() { if (typeof window === "undefined") return try { if (localStorage.getItem(AUTH_STORAGE_KEY)) return for (const legacy of LEGACY_AUTH_KEYS) { const raw = localStorage.getItem(legacy) if (raw) { localStorage.setItem(AUTH_STORAGE_KEY, raw) return } } } catch { /* private mode / quota */ } } migrateLegacyAuthStorage() interface AuthState { accessToken: string | null refreshToken: string | null expiresAt: number | null user: PlatformUser | null login: ( accessToken: string, refreshToken: string, expiresAt: number, user?: PlatformUser | null ) => void logout: () => void isAuthenticated: () => boolean } export const useAuthStore = create()( persist( (set, get) => ({ accessToken: null, refreshToken: null, expiresAt: null, user: null, login: (accessToken, refreshToken, expiresAt, user = null) => { set({ accessToken, refreshToken, expiresAt, user }) useSessionGuardStore.getState().clear() }, logout: () => { set({ accessToken: null, refreshToken: null, expiresAt: null, user: null, }) if (typeof window !== "undefined") { try { localStorage.removeItem(AUTH_STORAGE_KEY) for (const legacy of LEGACY_AUTH_KEYS) { localStorage.removeItem(legacy) } } catch { /* private mode / quota */ } } }, isAuthenticated: () => { const { accessToken, expiresAt, refreshToken } = get() if (!accessToken) return false if (expiresAt && Date.now() < expiresAt) return true // Access token expired — session may still be renewed via refresh token. return Boolean(refreshToken) }, }), { name: AUTH_STORAGE_KEY, storage: debouncedPersistJSONStorage, version: 1, migrate: (persisted) => { const state = (persisted as { state?: AuthState }).state if (state) { state.accessToken = null state.refreshToken = null state.expiresAt = null } return persisted as { state: AuthState; version: number } }, // Tokens stay in httpOnly cookies + in-memory store (via /api/auth/session). partialize: (state) => ({ user: state.user, }), } ) )