import { GetProjects, SubmitProjects } from '@agiliza/api/domain'
import { ProjectRepositoryImplFactory } from '@agiliza/api/useCases'
import { appPlatform } from '@agiliza/constants/platform'
import {
  createAsyncReducers,
  getTypesThunkActions,
  values,
  WithSuccess
} from '@agiliza/utils/method'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'

const prefix = 'useCases/authentication'

export interface State {
  fetching: boolean
  searching: boolean
  submitting: boolean
}

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

export const actions = {
  getContext: createAsyncThunk(`${prefix}/getContext`, async (_, thunkApi) => {
    const useCase = ProjectRepositoryImplFactory.create(appPlatform)
    try {
      return await useCase.getContext()
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  getProjects: createAsyncThunk(`${prefix}/getProjects`, async (input: GetProjects['Input'], thunkApi) => {
    const useCase = ProjectRepositoryImplFactory.create(appPlatform)
    try {
      return await useCase.getProjects(input)
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  submitProjects: createAsyncThunk(`${prefix}/submitProjects`, async (input: WithSuccess<SubmitProjects['Input']>, thunkApi) => {
    const useCase = ProjectRepositoryImplFactory.create(appPlatform)
    try {
      const broker = await useCase.submitProjects(input)
      input.onSuccess && input.onSuccess()
      return broker
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
} as const
export const types = getTypesThunkActions(actions)

const slice = createSlice({
  name: prefix,
  initialState,
  reducers: {},
  extraReducers: {
    ...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
    ...createAsyncReducers(types.getProjects, 'searching'),
    ...createAsyncReducers(types.submitProjects, 'submitting'),
  },
})

export default slice
