'use client'; import {Dispatch, SetStateAction, useContext, useEffect, useState} from 'react'; import {AppRouterInstance, useRouter} from '@/lib/navigation'; import {useTranslations} from '@/lib/i18n'; import {AlertContext, AlertContextProps} from '@/context/AlertContext'; import {LangContext, LangContextProps} from '@/context/LangContext'; import OfflineContext, {OfflineMode} from '@/context/OfflineContext'; import {SessionProps} from '@/lib/types/session'; import {UserProps} from '@/lib/types/user'; import {apiGet} from '@/lib/api/client'; import {isDesktop} from '@/lib/configs'; import * as tauri from '@/lib/tauri'; import {getCookie} from '@/lib/utils/cookies'; interface UseAuthenticationReturn { session: SessionProps; setSession: Dispatch>; isLoading: boolean; currentCredits: number; setCurrentCredits: Dispatch>; amountSpent: number; setAmountSpent: Dispatch>; showPinSetup: boolean; setShowPinSetup: Dispatch>; showPinVerify: boolean; setShowPinVerify: Dispatch>; handlePinVerifySuccess: (userId: string) => Promise; } export default function useAuthentication(): UseAuthenticationReturn { const t = useTranslations(); const {lang: locale}: LangContextProps = useContext(LangContext); const {errorMessage}: AlertContextProps = useContext(AlertContext); const {initializeDatabase, setOfflineMode} = useContext(OfflineContext); const router: AppRouterInstance = useRouter(); const [session, setSession] = useState({user: null, accessToken: '', isConnected: false}); const [currentCredits, setCurrentCredits] = useState(0); const [amountSpent, setAmountSpent] = useState(session.user?.aiUsage || 0); const [isLoading, setIsLoading] = useState(true); const [sessionAttempts, setSessionAttempts] = useState(0); const [showPinSetup, setShowPinSetup] = useState(false); const [showPinVerify, setShowPinVerify] = useState(false); useEffect((): void => { checkAuthentification().then(); }, []); useEffect((): void => { if (session.isConnected) { setIsLoading(false); } else { if (sessionAttempts > 2) { router.push('/'); } } setSessionAttempts(sessionAttempts + 1); }, [session]); async function checkAuthentification(): Promise { const token: string | null = isDesktop ? await tauri.getToken() : getCookie('token'); if (token) { try { const user: UserProps = await apiGet('user/infos', token, locale); if (!user) { errorMessage(t('homePage.errors.userNotFound')); if (isDesktop) { await tauri.removeToken(); await tauri.logout(); } return; } if (isDesktop && user.id) { try { const initResult = await tauri.initUser(user.id); if (!initResult.success) { errorMessage(initResult.error || t('homePage.errors.offlineInitError')); return; } try { const offlineStatus = await tauri.offlineModeGet(); if (!offlineStatus.hasPin && user.termsAccepted) { setTimeout((): void => { setShowPinSetup(true); }, 2000); } } catch (error) { errorMessage(t('homePage.errors.offlineModeError')); } } catch (error) { errorMessage(t('homePage.errors.offlineInitError')); } try { const dbInitialized: boolean = await initializeDatabase(user.id); if (dbInitialized) { try { await tauri.syncUser({ userId: user.id, username: user.username || '', email: user.email || '' }); } catch (syncError) { errorMessage(t('homePage.errors.syncError')); } } } catch (error) { errorMessage(t('homePage.errors.syncError')); } } setSession({ isConnected: true, user: user, accessToken: token, }); setCurrentCredits(user.creditsBalance); setAmountSpent(user.aiUsage); } catch (e: unknown) { if (isDesktop) { try { const offlineStatus = await tauri.offlineModeGet(); if (offlineStatus.hasPin && offlineStatus.lastUserId) { setOfflineMode((prev: OfflineMode): OfflineMode => ({ ...prev, isOffline: true, isNetworkOnline: false })); setShowPinVerify(true); setIsLoading(false); return; } else { await tauri.removeToken(); await tauri.logout(); } } catch (offlineError) { errorMessage(t('homePage.errors.offlineError')); } } else { window.location.href = 'https://eritors.com/login'; } if (e instanceof Error) { errorMessage(e.message); } else { errorMessage(t('homePage.errors.authenticationError')); } } } else { if (isDesktop) { try { const offlineStatus = await tauri.offlineModeGet(); if (offlineStatus.hasPin && offlineStatus.lastUserId) { setOfflineMode((prev: OfflineMode): OfflineMode => ({ ...prev, isOffline: true, isNetworkOnline: false })); setShowPinVerify(true); setIsLoading(false); return; } } catch (error) { errorMessage(t('homePage.errors.authenticationError')); } await tauri.openLoginWindow(); } else { window.location.href = 'https://eritors.com/login'; } } } async function handlePinVerifySuccess(userId: string): Promise { try { const storedToken: string | null = await tauri.getToken(); const encryptionKey: string | null = await tauri.getUserEncryptionKey(userId); if (encryptionKey) { await tauri.dbInitialize(userId, encryptionKey); setOfflineMode((prev: OfflineMode): OfflineMode => ({ ...prev, isDatabaseInitialized: true })); const localUser: UserProps = await tauri.getUserInfo(); if (localUser && localUser.id) { setSession({ isConnected: true, user: localUser, accessToken: storedToken || '', }); setShowPinVerify(false); setCurrentCredits(localUser.creditsBalance || 0); setAmountSpent(localUser.aiUsage || 0); } else { errorMessage(t('homePage.errors.localDataError')); } } else { errorMessage(t('homePage.errors.encryptionKeyError')); } } catch (error) { errorMessage(t('homePage.errors.offlineModeError')); } } return { session, setSession, isLoading, currentCredits, setCurrentCredits, amountSpent, setAmountSpent, showPinSetup, setShowPinSetup, showPinVerify, setShowPinVerify, handlePinVerifySuccess, }; }