import { connect } from 'react-redux'
import { bindActionCreators, Dispatch } from 'redux'

import { StoreState } from '@agiliza/redux'
import * as entProposal from '@agiliza/redux/entities/proposalData/proposal'
import * as ucAuthentication from '@agiliza/redux/useCases/authentication'
import * as ucProposalDataBD from '@agiliza/redux/useCases/proposalData/businessData'
import * as ucProposalDataContext from '@agiliza/redux/useCases/proposalData/context'
import * as ucProposalDataCD from '@agiliza/redux/useCases/proposalData/customerData'
import * as ucSimulation from '@agiliza/redux/useCases/simulation'
import { createSelector } from '@reduxjs/toolkit'

export interface ConnectedProps {
  fetching: boolean
  proposalId: string
  personId: string
  reset: () => void
  fetchContext: typeof ucProposalDataContext.actions.fetchContext
  getContextAddress: typeof ucAuthentication.actions.getContext
  addIndentification: typeof ucProposalDataCD.actions.addIndentification
  updatePersonalData: typeof ucProposalDataCD.actions.updatePersonalData
  updateCDAddress: typeof ucProposalDataCD.actions.updateAddress
  updateSourceIncome: typeof ucProposalDataCD.actions.updateSourceIncome
  updateSpouseData: typeof ucProposalDataCD.actions.updateSpouseData
  updateHome: typeof ucProposalDataCD.actions.updateHome
  updateIdentification: typeof ucProposalDataBD.actions.updateIdentification
  updateBDAddress: typeof ucProposalDataBD.actions.updateAddress
  updateStockSalesCosts: typeof ucProposalDataBD.actions.updateStockSalesCosts
  sendProposal: typeof ucSimulation.actions.sendProposal
}

type StateProps = Pick<ConnectedProps, 'fetching' | 'proposalId' | 'personId'>
type DispatchProps = Pick<
  ConnectedProps,
  | 'reset'
  | 'addIndentification'
  | 'fetchContext'
  | 'updatePersonalData'
  | 'updateCDAddress'
  | 'getContextAddress'
  | 'updateSourceIncome'
  | 'updateSpouseData'
  | 'updateHome'
  | 'updateIdentification'
  | 'updateBDAddress'
  | 'updateStockSalesCosts'
  | 'sendProposal'
>

const isFetching = createSelector(
  (state: StoreState) => ucProposalDataContext.selectors.isFetching(state.ui.login),
  (state: StoreState) => ucAuthentication.selectors.isFetching(state.useCases.authentication),
  (state: StoreState) => ucProposalDataCD.selectors.isFetching(state.useCases.proposalData.customerData),
  (state: StoreState) => ucProposalDataBD.selectors.isFetching(state.useCases.proposalData.businessData),
  (state: StoreState) => ucSimulation.selectors.isSendingProposal(state.useCases.simulation),
  (...conditions) => conditions.some((c) => c)
)

const mapStateToProps = (state: StoreState): StateProps => ({
  fetching: isFetching(state),
  proposalId: entProposal.selectors.getProposalId(state.entities.proposalData.proposal),
  personId: entProposal.selectors.getPersonlId(state.entities.proposalData.proposal),
})

const mapDispatchToProps = (dispatch: Dispatch): DispatchProps =>
  bindActionCreators(
    {
      reset: () => ({ type: 'RESET_STORE' }),
      addIndentification: ucProposalDataCD.actions.addIndentification,
      fetchContext: ucProposalDataContext.actions.fetchContext,
      updatePersonalData: ucProposalDataCD.actions.updatePersonalData,
      updateCDAddress: ucProposalDataCD.actions.updateAddress,
      getContextAddress: ucAuthentication.actions.getContext,
      updateSourceIncome: ucProposalDataCD.actions.updateSourceIncome,
      updateSpouseData: ucProposalDataCD.actions.updateSpouseData,
      updateHome: ucProposalDataCD.actions.updateHome,
      updateBDAddress: ucProposalDataBD.actions.updateAddress,
      updateIdentification: ucProposalDataBD.actions.updateIdentification,
      updateStockSalesCosts: ucProposalDataBD.actions.updateStockSalesCosts,
      sendProposal: ucSimulation.actions.sendProposal,
    },
    dispatch
  )

export const connected = connect(mapStateToProps, mapDispatchToProps)
