import { createAsyncThunk } from '@reduxjs/toolkit'; import { apiService, LoginRequest, RegisterRequest } from '../../services/api'; import { setLoading, setError, loginSuccess, logout, setTokens } from './authSlice'; export const loginUser = createAsyncThunk( 'auth/login', async (credentials: LoginRequest, { dispatch }) => { try { dispatch(setLoading(true)); dispatch(setError(null)); const response = await apiService.login(credentials); if (response.success && response.data) { // Store tokens in localStorage localStorage.setItem('accessToken', response.data.accessToken); localStorage.setItem('refreshToken', response.data.refreshToken); localStorage.setItem('sessionId', response.data.sessionId); // Dispatch login success dispatch(loginSuccess({ user: response.data.user, token: response.data.accessToken, refreshToken: response.data.refreshToken, sessionId: response.data.sessionId, })); return response.data; } else { throw new Error(response.message || 'Login failed'); } } catch (error: any) { const errorMessage = error.message || 'Login failed. Please try again.'; dispatch(setError(errorMessage)); throw error; } finally { dispatch(setLoading(false)); } } ); export const registerUser = createAsyncThunk( 'auth/register', async (userData: RegisterRequest, { dispatch }) => { try { dispatch(setLoading(true)); dispatch(setError(null)); const response = await apiService.register(userData); if (response.success) { return response; } else { throw new Error(response.message || 'Registration failed'); } } catch (error: any) { const errorMessage = error.message || 'Registration failed. Please try again.'; dispatch(setError(errorMessage)); throw error; } finally { dispatch(setLoading(false)); } } ); export const verifyEmail = createAsyncThunk( 'auth/verifyEmail', async ({ email, otp }: { email: string; otp: string }, { dispatch }) => { try { dispatch(setLoading(true)); dispatch(setError(null)); const response = await apiService.verifyEmail(email, otp); if (response.success) { return response; } else { throw new Error(response.message || 'Email verification failed'); } } catch (error: any) { const errorMessage = error.message || 'Email verification failed. Please try again.'; dispatch(setError(errorMessage)); throw error; } finally { dispatch(setLoading(false)); } } ); export const resendVerificationEmail = createAsyncThunk( 'auth/resendVerification', async (email: string, { dispatch }) => { try { dispatch(setLoading(true)); dispatch(setError(null)); const response = await apiService.resendVerificationEmail(email); if (response.success) { return response; } else { throw new Error(response.message || 'Failed to resend verification email'); } } catch (error: any) { const errorMessage = error.message || 'Failed to resend verification email. Please try again.'; dispatch(setError(errorMessage)); throw error; } finally { dispatch(setLoading(false)); } } ); export const logoutUser = createAsyncThunk( 'auth/logout', async (_, { dispatch, getState }) => { try { const state = getState() as any; const sessionId = state.auth.sessionId; if (sessionId) { await apiService.logout(sessionId); } // Clear localStorage localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); localStorage.removeItem('sessionId'); // Dispatch logout dispatch(logout()); } catch (error) { console.error('Logout error:', error); // Still logout locally even if API call fails localStorage.removeItem('accessToken'); localStorage.removeItem('refreshToken'); localStorage.removeItem('sessionId'); dispatch(logout()); } } ); export const getCurrentUser = createAsyncThunk( 'auth/getCurrentUser', async (_, { dispatch }) => { try { dispatch(setLoading(true)); dispatch(setError(null)); const response = await apiService.getCurrentUser(); if (response.success) { return response.data; } else { throw new Error('Failed to get current user'); } } catch (error: any) { const errorMessage = error.message || 'Failed to get current user'; dispatch(setError(errorMessage)); throw error; } finally { dispatch(setLoading(false)); } } ); export const refreshUserToken = createAsyncThunk( 'auth/refreshToken', async (_, { dispatch, getState }) => { try { const state = getState() as any; const refreshToken = state.auth.refreshToken; if (!refreshToken) { throw new Error('No refresh token available'); } const response = await apiService.refreshToken(refreshToken); if (response.success && response.data) { // Update tokens in localStorage localStorage.setItem('accessToken', response.data.accessToken); localStorage.setItem('refreshToken', response.data.refreshToken); localStorage.setItem('sessionId', response.data.sessionId); // Update tokens in store dispatch(setTokens({ token: response.data.accessToken, refreshToken: response.data.refreshToken, sessionId: response.data.sessionId, })); return response.data; } else { throw new Error(response.message || 'Token refresh failed'); } } catch (error: any) { console.error('Token refresh failed:', error); // If refresh fails, logout the user dispatch(logoutUser()); throw error; } } );