import type { ChangeEvent, FocusEvent } from 'react'
import {
  useEffect,
  useCallback,
} from 'react'

import trim from 'lodash/trim'

import { isValidEmail } from 'helpers/isValidEmail'
import { isValidPhone } from 'helpers/isValidPhone'
import { formatPhoneCode } from 'helpers/formatPhoneCode'

import type { SelectedCountry } from 'hooks/useCountries'
import { useCountries } from 'hooks/useCountries'
import { useCities } from 'hooks/useCities'

import { formIds } from 'config/form'

import { useForm } from 'features/FormStore'
import { useSubmitHandler } from 'features/Register/components/RegistrationStep/hooks/useSubmitHandler'
import { useLexicsStore } from 'features/LexicsStore'

type Name = 'name_rus' | 'name_eng'

export const useRegistrationForm = () => {
  const {
    readFormError,
    readFormValue,
    updateFormError,
    updateFormValue,
  } = useForm()

  const {
    countries,
    selectedCountry,
    setSelectedCountry,
  } = useCountries()

  const {
    cities,
    getCities,
    onCitySelect,
    resetCities,
    resetSelectedCity,
    selectedCity,
  } = useCities()

  const handleSubmit = useSubmitHandler({
    selectedCity,
    selectedCountry,
  })
  const { suffix } = useLexicsStore()

  const onEmailBlur = useCallback(({ target }: FocusEvent<HTMLInputElement>) => {
    const email = trim(target.value)
    if (email && !isValidEmail(email)) {
      updateFormError(formIds.email, 'error_invalid_email_format')
    }
  }, [updateFormError])

  const onPhoneBlur = useCallback(({ target }: ChangeEvent<HTMLInputElement>) => {
    const phone = target.value
    if (phone && !isValidPhone(phone)) {
      updateFormError(formIds.phone, 'error_invalid_phone_format')
    }
  }, [updateFormError])

  const onCountrySelect = useCallback((
    country: SelectedCountry,
    updatePhoneCode: boolean = true,
  ) => {
    setSelectedCountry(country)
    const countryName = country ? country[`name_${suffix}` as Name] : ''
    updateFormValue(formIds.country)(countryName)

    updateFormValue(formIds.cityId)('')
    updateFormValue(formIds.countryId)(`${country?.id}`)
    resetCities()
    resetSelectedCity()

    if (updatePhoneCode) {
      const code = country?.phone_code
        ? formatPhoneCode(country.phone_code)
        : ''
      updateFormValue(formIds.phone)(code)
    }
  }, [
    resetCities,
    resetSelectedCity,
    setSelectedCountry,
    updateFormValue,
    suffix,
  ])

  const onRegionOrCityChange = useCallback((fieldName: string) => (
    ({ target }: ChangeEvent<HTMLInputElement>) => {
      if (selectedCountry) {
        updateFormValue(fieldName)(target.value)
      } else {
        updateFormError(formIds.country, 'error_select_country_first')
      }
    }
  ), [
    selectedCountry,
    updateFormError,
    updateFormValue,
  ])

  const trimmedCity = trim(readFormValue(formIds.city))
  useEffect(() => {
    if (trimmedCity && selectedCountry?.id) {
      getCities(trimmedCity, selectedCountry.id)
    }
  }, [
    trimmedCity,
    selectedCountry,
    getCities,
  ])

  return {
    cities,
    countries,
    getCities,
    handleSubmit,
    onCitySelect,
    onCountrySelect,
    onEmailBlur,
    onPhoneBlur,
    onRegionOrCityChange,
    readFormError,
    readFormValue,
    resetCities,
    resetSelectedCity,
    selectedCity,
    updateFormError,
    updateFormValue,
  }
}
