import {
  AddCDIdentification,
  AddCDReference,
  AddCDVehicle,
  CreateProposal,
  GetCDReferences,
  GetCDVehicles,
  UpdateCDAddress,
  UpdateCDHome,
  UpdateCDPersonalData,
  UpdateCDReference,
  UpdateCDSourceIncome,
  UpdateCDSpouseData,
  UpdateCDVehicle
} from '@agiliza/api/domain'
import {
  PDCustomerDataRepositoryImplFactory
} from '@agiliza/api/useCases/proposalData/customerData'
import { appPlatform } from '@agiliza/constants/platform'
import {
  createAsyncReducers,
  getTypesThunkActions,
  values,
  WithSuccess
} from '@agiliza/utils/method'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'

const prefix = 'useCases/customerData'

export interface State {
  fetching: boolean
}

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

export const actions = {
  createProposal: createAsyncThunk(`${prefix}/createProposal`, async (input: WithSuccess<CreateProposal['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.createProposal(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  addIndentification: createAsyncThunk(`${prefix}/addIndentification`, async (input: WithSuccess<AddCDIdentification['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const proposal = await useCase.addIdentification(input)
      input.onSuccess && input.onSuccess()
      return proposal
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updatePersonalData: createAsyncThunk(`${prefix}/updatePersonalData`, async (input: WithSuccess<UpdateCDPersonalData['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updatePersonalData(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateAddress: createAsyncThunk(`${prefix}/updateAddress`, async (input: WithSuccess<UpdateCDAddress['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateAddress(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateSourceIncome: createAsyncThunk(`${prefix}/updateSourceIncome`, async (input: WithSuccess<UpdateCDSourceIncome['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateSourceIncome(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateSpouseData: createAsyncThunk(`${prefix}/updateSpouseData`, async (input: WithSuccess<UpdateCDSpouseData['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateSpouseData(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  getReferences: createAsyncThunk(`${prefix}/getReferences`, async (input: WithSuccess<GetCDReferences['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.getReferences(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  addReference: createAsyncThunk(`${prefix}/addReference`, async (input: WithSuccess<AddCDReference['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.addReference(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateReference: createAsyncThunk(`${prefix}/updateReference`, async (input: WithSuccess<UpdateCDReference['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateReference(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateHome: createAsyncThunk(`${prefix}/updateHome`, async (input: WithSuccess<UpdateCDHome['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateHome(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  getVehicles: createAsyncThunk(`${prefix}/getVehicles`, async (input: WithSuccess<GetCDVehicles['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.getVehicles(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  addVehicle: createAsyncThunk(`${prefix}/addVehicle`, async (input: WithSuccess<AddCDVehicle['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.addVehicle(input)
      input.onSuccess && input.onSuccess()
      return response
    } catch (e) {
      return thunkApi.rejectWithValue(e)
    }
  }),
  updateVehicle: createAsyncThunk(`${prefix}/updateVehicle`, async (input: WithSuccess<UpdateCDVehicle['Input']>, thunkApi) => {
    const useCase = PDCustomerDataRepositoryImplFactory.create(appPlatform)
    try {
      const response = await useCase.updateVehicle(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) }), {}),
  },
})

export default login
