import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"
import { User } from "../../models/User"
import { AuthResponse } from "../../models/response/AuthResponse";
import AuthService from "../../services/AuthService";
import { ServerError } from "../../models/response/ServerError";
import { AxiosError } from 'axios';
import { API_URL } from "../../http";
import axios from "axios";



export interface UserState {
    user: User;
    isAuth: boolean;
    isLoading: boolean;
}



const initialState: UserState = {
    user: {
        _id: '',
        email: '',
        name: '',
        sname: ''
    },
    isAuth: false,
    isLoading: true
}

export const registration = createAsyncThunk<User, {email: string, name: string, sname: string, password: string}>(
    'userSlice/registration',
    async (user, {rejectWithValue}) => {
        try {
            const {email, name, sname, password} = user;
            const response = await AuthService.registration(email, name, sname, password);
            localStorage.setItem('token', response.data.accessToken);
            return response.data.user;
        } catch (error) {
            const err = error as AxiosError;
            const e = err.response?.data as ServerError
            return rejectWithValue(e.error);
        }
        
    }
)

export const login = createAsyncThunk<User, {email: string, password: string}>(
    'userSlice/login',
    async (user, {rejectWithValue}) => {
        try {
            const {email, password} = user;
            const response = await AuthService.login(email, password);
            localStorage.setItem('token', response.data.accessToken);
            return response.data.user;
        } catch ( error ) {
            const err = error as AxiosError;
            const e = err.response?.data as ServerError
            return rejectWithValue(e.error);
        }
    }
)

export const checkAuth = createAsyncThunk<User>(
    'userSlice/checkAuth',
    async (_, {rejectWithValue}) => {
        try {
            const response = await axios.get<AuthResponse>(`${API_URL}/auth/refresh`, {withCredentials: true});
            localStorage.setItem('token', response.data.accessToken);
            return response.data.user;
        } catch (error) {
            const err = error as AxiosError;
            const e = err.response?.data as ServerError
            return rejectWithValue(e.error);
        }
    }
)

export const logout = createAsyncThunk<boolean>(
    'userSlice/logout',
    async (_, {rejectWithValue}) => {
        try {
            await AuthService.logout();
            localStorage.removeItem('token');
            return true;
        } catch (error) {
            const err = error as AxiosError;
            const e = err.response?.data as ServerError
            return rejectWithValue(e.error);
        }
    }
)

export const userSlice = createSlice({
    name: 'userSlice',
    initialState,
    reducers: {
        storeLoad(state) {
            state.isLoading = false;
        }
    },
    extraReducers: (builder) => {
        builder
            .addCase(registration.fulfilled, (state, { payload }) => {
                state.isAuth = true;
                state.user = payload;
            })
            .addCase(registration.rejected, (_, { payload }) => {
                console.log(payload);
            })
            .addCase(login.fulfilled, (state, { payload }) => {
                state.isAuth = true;
                state.user = payload;
            })
            .addCase(login.rejected, (_, { payload }) => {
                console.log(payload);
            })
            .addCase(checkAuth.pending, (state) => {
                state.isLoading = true;
            })
            .addCase(checkAuth.fulfilled, (state, action) => {
                state.user = action.payload;
                state.isAuth = true;
                state.isLoading = false;
            })
            .addCase(checkAuth.rejected, (state, { payload }) => {
                state.isLoading = false;
                console.log(payload);
            })
            .addCase(logout.fulfilled, (state) => {
                state.isAuth = false;
                state.user = {} as User;
            })
            .addCase(logout.rejected, (_, { payload }) => {
                console.log(payload);
            })
    }
})

export default userSlice.reducer;