import type { ChangeEvent } from 'react'
import { useCallback, useState } from 'react'

import isObject from 'lodash/isObject'

import { isFormStateEqual } from '../helpers'

type FieldState = {
  error?: string | null,
  value: string,
}

export type FormState = {[formId: string]: FieldState}

export const useFormState = (initialState: FormState = {}) => {
  const [formState, setFormState] = useState<FormState>(initialState)

  const readFormValue = useCallback(
    (fieldName: string) => formState[fieldName]?.value ?? '',
    [formState],
  )
  const readFormError = useCallback(
    (fieldName: string) => formState[fieldName]?.error ?? null,
    [formState],
  )
  const updateFormValue = useCallback(
    (fieldName: string) => (
      (event: ChangeEvent<HTMLInputElement> | string) => {
        const value = isObject(event) ? event.target.value : event
        setFormState(((state) => {
          const newState = {
            ...state,
            [fieldName]: {
              error: null,
              value: value ?? '',
            },
          }
          return newState
        }))
      }
    ),
    [],
  )

  const updateFormError = useCallback(
    (fieldName: string, error: string) => {
      setFormState(((state) => {
        const newState = {
          ...state,
          [fieldName]: {
            error,
            value: state[fieldName]?.value,
          },
        }
        return newState
      }))
    },
    [],
  )

  const hasChanges = useCallback(
    () => !isFormStateEqual(formState, initialState),
    [formState, initialState],
  )

  return {
    hasChanges,
    readFormError,
    readFormValue,
    updateFormError,
    updateFormValue,
  }
}
