import { createReduxStore, register } from '@wordpress/data'
import { validationDispatch, ValidationState } from '../data/redux/validation.redux'
import { Debit, Plaid, Ribbit } from '@greenpay/models'

const DEFAULT_STATE: ValidationState = {
	errors: {
		plaid: '',
		routing: '',
		account: '',
	},
	touched: {
		plaid: false,
		routing: false,
		account: false,
	},
	status: {
		tan: false,
		plaid: false,
	},
	errorMessage: '',
	snackbar: {
		open: false,
		message: '',
	},
}

const storeConfig = {
	reducer(state: ValidationState = DEFAULT_STATE, action: any): ValidationState {
		switch (action.type) {
			case 'SET_ERROR_MESSAGE':
				return { ...state, errorMessage: action.payload.errorMessage }
			case 'SET_PLAID_ERROR':
				return {
					...state,
					errors: { ...state.errors, plaid: action.payload },
				}
			case 'SET_ROUTING_ERROR':
				return {
					...state,
					errors: { ...state.errors, routing: action.payload },
				}
			case 'SET_ACCOUNT_ERROR':
				return {
					...state,
					errors: { ...state.errors, account: action.payload },
				}
			case 'SET_PLAID_TOUCHED':
				return {
					...state,
					touched: { ...state.touched, plaid: action.payload },
				}
			case 'SET_ROUTING_TOUCHED':
				return {
					...state,
					touched: { ...state.touched, routing: action.payload },
				}
			case 'SET_ACCOUNT_TOUCHED':
				return {
					...state,
					touched: { ...state.touched, account: action.payload },
				}
			case 'SET_DEBIT_TOUCHED':
				return {
					...state,
					touched: { ...state.touched, routing: action.payload, account: action.payload },
				}
			case 'SET_TAN_STATUS':
				return {
					...state,
					status: { ...state.status, tan: action.payload },
				}
			case 'SET_PLAID_OPEN':
				return {
					...state,
					status: { ...state.status, plaid: action.payload },
				}
			case 'SHOW_SNACKBAR':
				return {
					...state,
					snackbar: { open: true, message: action.payload },
				}
			case 'HIDE_SNACKBAR':
				return {
					...state,
					snackbar: { ...state.snackbar, open: false },
				}
			default:
				return state
		}
	},
	actions: {
		setErrorMessage(errorMessage: string) {
			return { type: 'SET_ERROR_MESSAGE', payload: { errorMessage } }
		},
		setPlaidError(message: string) {
			return { type: 'SET_PLAID_ERROR', payload: message }
		},
		setRoutingError(message: string) {
			return { type: 'SET_ROUTING_ERROR', payload: message }
		},
		setAccountError(message: string) {
			return { type: 'SET_ACCOUNT_ERROR', payload: message }
		},
		setPlaidTouched(touched: boolean) {
			return { type: 'SET_PLAID_TOUCHED', payload: touched }
		},
		setRoutingTouched(touched: boolean) {
			return { type: 'SET_ROUTING_TOUCHED', payload: touched }
		},
		setAccountTouched(touched: boolean) {
			return { type: 'SET_ACCOUNT_TOUCHED', payload: touched }
		},
		setDebitTouched(touched: boolean) {
			return { type: 'SET_DEBIT_TOUCHED', payload: touched }
		},
		setTanStatus(status: boolean) {
			return { type: 'SET_TAN_STATUS', payload: status }
		},
		setPlaidOpen(status: boolean) {
			return { type: 'SET_PLAID_OPEN', payload: status }
		},
		showSnackbar(message: string) {
			return { type: 'SHOW_SNACKBAR', payload: message }
		},
		hideSnackbar() {
			return { type: 'HIDE_SNACKBAR' }
		},
		validatePlaid(data: Plaid | null) {
			return () => {
				const { setPlaidError, setPlaidTouched } = validationDispatch()

				setPlaidTouched(true)
				if (!data || !data.success) {
					setPlaidError('Please use the bank login to register your payment.')
					return false
				} else if (!data.token || !data.institution) {
					setPlaidError('Bank login was unsuccessful, please try again.')
					return false
				} else if (data.isTAN && data.isTAN === true) {
					setPlaidError('Please verify your bank account information.')
					return false
				} else {
					setPlaidError('')
					return true
				}
			}
		},
		validateRibbit(data: Ribbit | null) {
			return () => {
				const { setPlaidError, setPlaidTouched } = validationDispatch()

				setPlaidTouched(true)
				if (!data || !data.success) {
					setPlaidError('Please use the bank login to register your payment.')
					return false
				}
				if (data.isTAN && data.isTAN === true) {
					setPlaidError('Please verify your bank account information.')
					return false
				}
				if (!data.customerToken || !data.accountToken || !data.institutionName) {
					setPlaidError('Bank login was unsuccessful, please try again.')
					return false
				}

				setPlaidError('')
				return true
			}
		},
		validateDebit(data: Debit | null) {
			return () => {
				const { validateRouting, validateAccount, setAccountError, setDebitTouched } = validationDispatch()

				if (!data) {
					setAccountError('Please enter your bank information.')
					setDebitTouched(true)
					return false
				}

				return validateRouting(data.routingNumber) && validateAccount(data.accountNumber)
			}
		},
		validateRouting(routing?: string) {
			return () => {
				const { setRoutingError, setRoutingTouched } = validationDispatch()
				setRoutingTouched(true)
				if (!routing || routing.length !== 9) {
					setRoutingError('Please enter a valid 9-digit routing number.')
					return false
				}

				setRoutingError('')
				return true
			}
		},
		validateAccount(account?: string) {
			return () => {
				const { setAccountError, setAccountTouched } = validationDispatch()
				setAccountTouched(true)
				if (!account || account.length < 5 || account.length > 17) {
					setAccountError('Please enter a valid account number. (must be between 5 and 17 digits)')
					return false
				}

				setAccountError('')
				return true
			}
		},
	},
	selectors: {
		getErrorMessage(state: ValidationState) {
			return state.errorMessage
		},
		getPlaidError(state: ValidationState) {
			return state.errors.plaid
		},
		getPlaidTouched(state: ValidationState) {
			return state.touched.plaid
		},
		getRoutingTouched(state: ValidationState) {
			return state.touched.routing
		},
		getAccountTouched(state: ValidationState) {
			return state.touched.account
		},
		getDebitError(state: ValidationState) {
			return `${state.errors.routing} ${state.errors.account}`.trim()
		},
		getRoutingError(state: ValidationState) {
			return state.errors.routing
		},
		getAccountError(state: ValidationState) {
			return state.errors.account
		},
		getTanStatus(state: ValidationState) {
			return state.status.tan
		},
		getPlaidOpen(state: ValidationState) {
			return state.status.plaid
		},
		getSnackbarOpen(state: ValidationState) {
			return state.snackbar.open
		},
		getSnackbarMessage(state: ValidationState) {
			return state.snackbar.message
		},
	},
}

const validationStore = createReduxStore('green-pay/validation', storeConfig)
export const validationActions = storeConfig.actions

register(validationStore)
