import merge from 'deepmerge'
import { useMemo, useReducer } from 'react'

import { CaseReducerActions, createSlice, PayloadAction } from '@reduxjs/toolkit'

import { entries } from '../method'
import bindActionCreators from './bindActionCreators'

export type Formatter = (txt: string) => string

export type FormatterState<S> = { [k in keyof S]?: Formatter | Formatter[] }

export type UpdatePayload<S> = {
  [k in keyof S]: Partial<S[k]>
}

type FormState<S> = {
  [k in keyof S]: S extends Record<string, any> ? S[k] : string | boolean | number
}

export type ActionType<State> = CaseReducerActions<{
  update: (
    state: State,
    action: {
      payload: Partial<UpdatePayload<State>>
      type: string
    }
  ) => void
}>

export const useFormState = <S extends FormState<S>>(
  name: string,
  initialState: S
  // formatters: FormatterState<S> = {}
) => {
  const slice = useMemo(
    () =>
      createSlice({
        name,
        initialState,
        reducers: {
          update: (state, action: PayloadAction<Partial<UpdatePayload<S>>>) => {
            const { payload } = action
            entries(payload).forEach(([k, v]) => {
              if (!(v instanceof Date) && v instanceof Object) state[k] = merge.all([state[k], v]) as any
              else state[k] = v
              // let aux = state
              // const splitedPath = k.split('.')
              // if (splitedPath.length > 1) {
              //   const lastKey = splitedPath.pop()
              //   splitedPath.forEach((k) => (aux = aux[k]))
              //   if (lastKey && !(aux[lastKey] instanceof Object)) aux[lastKey] = v
              // } else {
              // }
              // setValueFromPath(state[k], k, v)
              // state[k] = v
              // const formatter = getValueFromPath(formatters, k)
              // if (formatter) {
              //   if (formatter instanceof Array) {
              //     let formatted = v
              //     formatter.forEach((fmtr) => (formatted = fmtr(formatted)))
              //     setValueFromPath(state[k], k, formatted)
              //   }
              //   if (formatter instanceof Function) {
              //     const formatted = formatter(v)
              //     setValueFromPath(state[k], k, formatted)
              //   }
              // }
            })
          },
        },
      }),
    [initialState]
  )

  const [state, dispatch] = useReducer(slice.reducer, initialState)

  const actions = bindActionCreators(slice.actions, dispatch) as typeof slice.actions

  return { state, actions }
}
