import { SessionRepositoryImplFactory } from '@agiliza/api/useCases/session'
import { appPlatform } from '@agiliza/constants/platform'
import {
  createAsyncReducers,
  getTypesThunkActions,
  values,
  WithSuccess
} from '@agiliza/utils/method'
import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit'

const prefix = 'ui/login'

export interface State {
  fetching: boolean
}

export const initialState: State = {
  fetching: false,
}

interface Login {
  username: string
  password: string
}

export const actions = {
  login: createAsyncThunk(`${prefix}/login`, async (args: WithSuccess<{ username: string; password: string }>, thunkApi) => {
    const useCase = SessionRepositoryImplFactory.create(appPlatform)
    try {
      const { username, password, onSuccess } = args
      const customer = await useCase.login(username, password)
      onSuccess && onSuccess()
      return customer
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  logout: createAsyncThunk(`${prefix}/logout`, (_, thunkApi) => {
    const useCase = SessionRepositoryImplFactory.create(appPlatform)
    useCase.logout()
    thunkApi.dispatch({ type: 'RESET_STORE' })
    return
  }),
  connect: createAsyncThunk(`${prefix}/connect`, (_, thunkApi) => {
    const useCase = SessionRepositoryImplFactory.create(appPlatform)
    try {
      useCase.connect()
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
} as const
export const types = getTypesThunkActions(actions)

const login = createSlice({
  name: prefix,
  initialState,
  reducers: {
    login(state, action: PayloadAction<Login>) {
      state.fetching = true
    },
    loginSuccess(state) {
      state.fetching = false
    },
    loginError(state, action: PayloadAction<string>) {
      state.fetching = false
    },
  },
  extraReducers: {
    ...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
  },
})

export default login
