import { GetSubProducts, SendProposal } from '@agiliza/api/domain'
import { SimulationContextRepositoryImplFactory } from '@agiliza/api/useCases'
import { SimulationRepositoryImplFactory } from '@agiliza/api/useCases/simulation/simulation'
import { appPlatform } from '@agiliza/constants/platform'
import {
  createAsyncReducers,
  getTypesThunkActions,
  values,
  WithSuccess
} from '@agiliza/utils/method'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'

const prefix = 'useCases/simulation'

export interface State {
  fetching: boolean
  sendingProposal: boolean
}

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

export const actions = {
  fetchSimulationCategories: createAsyncThunk(`${prefix}/fetchSimulationCategories`, async (_, thunkApi) => {
    const useCase = SimulationContextRepositoryImplFactory.create(appPlatform)
    try {
      return await useCase.fetchSimulationCategories()
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  getSubproducts: createAsyncThunk(
    `${prefix}/getSubproducts`,
    async (input: WithSuccess<GetSubProducts['Input'], GetSubProducts['Output']>, thunkApi) => {
      const useCase = SimulationRepositoryImplFactory.create(appPlatform)
      try {
        const response = await useCase.getSubproducts(input)
        input.onSuccess && input.onSuccess(response)
        return response
      } catch (e) {
        return thunkApi.rejectWithValue(e)
      }
    }
  ),
  sendProposal: createAsyncThunk(`${prefix}/sendProposal`, async (input: WithSuccess<SendProposal['Input']>, thunkApi) => {
    const useCase = SimulationRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.sendProposal(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
} as const
export const types = getTypesThunkActions(actions)

const login = createSlice({
  name: prefix,
  initialState,
  reducers: {},
  extraReducers: {
    ...values(types).reduce((reducers, type) => ({ ...reducers, ...createAsyncReducers(type) }), {}),
    ...createAsyncReducers(types.sendProposal, 'sendingProposal'),
  },
})

export default login
