import {
  useState,
  useEffect,
  useCallback,
} from 'react'

import find from 'lodash/find'
import reduce from 'lodash/reduce'
import isNull from 'lodash/isNull'
import isNumber from 'lodash/isNumber'
import isString from 'lodash/isString'
import isObject from 'lodash/isObject'

import { formIds } from 'config/form'

import type { UserInfo, SaveUserInfo } from 'requests'
import {
  getUserInfo,
  getCountryCities,
  saveUserInfo,
} from 'requests'

import type { FormState } from 'features/FormStore/hooks/useFormState'
import { useLexicsStore } from 'features/LexicsStore'

const transformToFormState = async (userInfo: UserInfo, lang: string) => {
  const cities = userInfo.country?.id
    ? await getCountryCities('', userInfo.country.id)
    : []
  return reduce(
    formIds,
    (
      acc: FormState,
      field,
    ) => {
      const key = field as keyof UserInfo
      const value = userInfo[key]
      if (key === formIds.cityId && value) {
        const city = find(cities, { id: Number(value) }) || { id: '', name: acc[formIds.city]?.value }
        acc[formIds.cityId] = { value: String(city.id) }
        acc[formIds.city] = { value: city.name }
      } else if (key === formIds.country && isObject(value) && value.id) {
        const formValue = { value: String(value.id) }
        acc[formIds.initialCountryId] = formValue
        acc[formIds.countryId] = formValue
      } else if (key === formIds.language && isObject(value)) {
        acc[formIds.language] = { value: userInfo.language?.iso ?? lang }
      } else if (isNumber(value) || isString(value)) {
        acc[key] = { value: String(value) }
      } else if (isNull(value)) {
        acc[key] = { value: '' }
      }
      return acc
    },
    {},
  )
}

export const useUserInfo = () => {
  const {
    changeLang,
    lang,
    languageList,
  } = useLexicsStore()
  const [userInfo, setUserInfo] = useState<FormState | null>(null)
  const [loader, setLoader] = useState<boolean>(false)

  const fetchUserInfo = useCallback(async () => {
    const userInfoFetched = await getUserInfo()
    const userInfoFormState = await transformToFormState(userInfoFetched, lang)
    setUserInfo(userInfoFormState)
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  const onSubmit = useCallback((data: SaveUserInfo) => {
    setLoader(true)
    saveUserInfo(data).then(() => {
      fetchUserInfo()

      const lang_iso = find(languageList,
        (language) => language.id === data.language_id)?.iso_639_1

      if (lang_iso) {
        changeLang(lang_iso)
      }
    }).finally(() => setLoader(false))
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fetchUserInfo])

  useEffect(() => {
    fetchUserInfo()
  }, [fetchUserInfo])

  return {
    loader,
    onSubmit,
    userInfo,
  }
}
