import type { CurrentUserResponse, EmailRequest, NotificationListResponse, OkResponse, OtpRequestResponse, RegisterCitizenRequest, RegisterCitizenResponse, RewardsResponse, TokenResponse, VerifyOtpRequest, UpdateProfileRequest } from "~/types/api"; export const useAuth = () => { const nuxtApp = useNuxtApp() const token = useCookie('auth_token', { maxAge: 60 * 60 * 12, sameSite: 'lax', path: '/', watch: true }) const tokenState = useState('auth_token_state', () => token.value ?? null) type UserContext = CurrentUserResponse['user'] const user = useState('auth_user', () => null) const isSyncingUser = useState('auth_syncing', () => false) const isAuthenticated = computed(() => !!(tokenState.value || token.value)) const isAuthStatusError = (error: any) => { const status = error?.statusCode || error?.status || error?.response?.status return status === 401 || status === 403 } watch(() => token.value, (newVal) => { tokenState.value = newVal || null }) const syncUser = async (options: { redirectOnSuccess?: boolean; currentPath?: string } = {}) => { const { redirectOnSuccess = false, currentPath } = options const tokenVal = tokenState.value || token.value if (!tokenVal || isSyncingUser.value) return isSyncingUser.value = true try { const res = await fetchCurrentUser() if (res.ok) { user.value = res.user const path = currentPath ?? useNuxtApp().$router.currentRoute.value.path if (redirectOnSuccess && path.startsWith('/auth')) { await nuxtApp.runWithContext(() => navigateTo('/dashboard')) } } } catch (error) { if (isAuthStatusError(error)) { console.error('[Auth] Sync failed with authentication error, keeping session state:', error) return } console.error('[Auth] Sync failed, logging out:', error) logout() } finally { isSyncingUser.value = false } } const handleLoginSuccess = async (jwtToken: string) => { token.value = jwtToken tokenState.value = jwtToken await syncUser({ redirectOnSuccess: true }) } const logout = () => { token.value = null tokenState.value = null user.value = null nuxtApp.runWithContext(() => navigateTo('/auth/login')) } const register = (body: RegisterCitizenRequest) => useApiFetch('/api/v1/auth/register', { method: 'POST', body }) const requestOtp = (body: EmailRequest) => useApiFetch('/api/v1/auth/otp/request', { method: 'POST', body }) const verifyOtp = (body: VerifyOtpRequest) => useApiFetch('/api/v1/auth/otp/verify', { method: 'POST', body }) const updateProfile = (body: UpdateProfileRequest) => useApiFetch('/api/v1/me', { method: 'PATCH', body }) const fetchCurrentUser = () => useApiFetch('/api/v1/me', { method: 'GET' }) const fetchRewards = (query?: { page?: number; per_page?: number }) => useApiFetch('/api/v1/me/rewards', { method: 'GET', query }) const fetchNotifications = (query?: { page?: number; per_page?: number }) => useApiFetch('/api/v1/notifications', { method: 'GET', query }) const markNotificationRead = (id: number) => useApiFetch(`/api/v1/notifications/${id}/read`, { method: 'PATCH' }) return { user, token, tokenState, isSyncingUser, isAuthenticated, handleLoginSuccess, syncUser, logout, register, requestOtp, verifyOtp, updateProfile, fetchCurrentUser, fetchRewards, fetchNotifications, markNotificationRead, } }