import {
  ChangeEvent,
  useEffect,
  useRef,
  useState,
  useMemo,
} from 'react'

import debounce from 'lodash/debounce'

import {
  useRecoilState,
  useSetRecoilState,
  useRecoilValue,
} from 'recoil'

import { useUserFavoritesStore } from 'features/UserFavorites/store'

import type { Match } from 'requests/getMatches/types'

import { getSportList } from 'requests/getSportList'
import { getSounds } from 'requests/getSounds'
import {
  getSportTeams,
  Team,
  SportTeamsType,
} from 'requests/getSportTeams'
import { getPlayerMatches } from 'requests/getMatches/getPlayerMatches'
import { getTeamPlayers, Player } from 'requests/getTeamPlayers'
import { getSearchItems, PlayerTypeFromSearch } from 'requests'

import {
  checkedMatches,
  playerMatchesState,
  dataForPayHighlights,
  fetchingMatches,
} from '../../storeHighlightsAtoms'

export type SportType = {
  id: number,
  lexic: number,
  name_eng: string,
  name_rus: string,
}

type SportTypeName = SportType & {
  disabled?: boolean,
  name: string,
}

type PlayerType = {
  firstname_eng: string,
  firstname_rus: string,
  id: number,
  lastname_eng: string,
  lastname_rus: string,
  name: string,
  sport?: number,
  sport_id?: number,
  team?: {
    id: number,
    name_eng: string,
    name_rus: string,
  },
}

type TeamType = {
  id: number,
  name: string,
  name_eng: string,
  name_rus: string,
  short_name_eng?: string,
  short_name_rus?: string,
}

type Sound = {
  asset?: string | null,
  id: number,
  name: string,
}

type StatsType = {
  id: number,
  name: string,
}

type FormType = {
  duration: string,
  playerValue: string,
  players: Array<string>,
  selectedPlayer: PlayerType | null,
  selectedSound: Sound | null,
  selectedTeam: TeamType | null,
  sport: SportTypeName | null,
  stats: StatsType,
  teamValue: string,
}

const summaryStats = [
  {
    id: 0,
    name: 'No',
  },
  {
    id: 1,
    name: 'Yes',
  },
]

const defaultValues = {
  duration: '2',
  playerValue: '',
  players: [],
  selectedPlayer: null,
  selectedSound: null,
  selectedTeam: null,
  sport: null,
  stats: summaryStats[0],
  teamValue: '',
}

export const useHighlightsForm = () => {
  const { playerHighlight } = useUserFavoritesStore()

  const [sports, setSports] = useState<Array<SportTypeName>>([])
  const [sounds, setSounds] = useState<Array<Sound>>([])
  const [isFetchingTeams, setIsFetchingTeams] = useState(false)
  const [teams, setTeams] = useState<Array<TeamType>>([])
  const [playersData, setPlayersData] = useState<Array<PlayerType>>([])
  const [players, setPlayers] = useState<Array<PlayerType>>([])
  const [formState, setFormState] = useState<FormType>(defaultValues)
  const [playerMatches, setPlayerMatches] = useRecoilState(playerMatchesState)
  const {
    checkedMatchesLength,
  } = useRecoilValue(checkedMatches)
  const setDatahighlights = useSetRecoilState(dataForPayHighlights)
  const setIsFetching = useSetRecoilState(fetchingMatches)

  const formRef = useRef<HTMLFormElement>(null)

  const onSportSelect = (selectedSport: SportTypeName | null) => {
    if (selectedSport) {
      setFormState((state) => ({
        ...state,
        playerValue: '',
        selectedPlayer: null,
        selectedTeam: null,
        sport: selectedSport,
        teamValue: '',
      }))
      setTeams([])
      setPlayers([])
      setPlayerMatches([])
    }
  }

  const onTeamSelect = (selectedTeam: TeamType | null) => {
    if (selectedTeam) {
      setFormState((state) => ({
        ...state,
        duration: '2',
        selectedTeam,
      }))
    }
  }

  const onPlayerSelect = (selectedPlayer: PlayerType | null) => {
    if (!selectedPlayer) return
    setFormState((state: FormType) => ({
      ...state,
      duration: '2',
      playerValue: '',
      selectedPlayer,
      teamValue: '',
    }))

    if (selectedPlayer.team && !formState.selectedTeam) {
      setFormState((state: FormType) => ({
        ...state,
        selectedTeam: {
          id: selectedPlayer?.team?.id || 0,
          name: selectedPlayer?.team?.name_eng || '',
          name_eng: selectedPlayer?.team?.name_eng || '',
          name_rus: selectedPlayer?.team?.name_rus || '',
        },
      }))
    }
  }

  const onSoundSelect = (selectedSound: Sound | null) => {
    if (!selectedSound) return
    setFormState((state) => ({
      ...state,
      selectedSound,
    }))
  }

  const onStatsSelect = (stats: StatsType | null) => {
    if (!stats) return
    setFormState((state) => ({
      ...state,
      stats,
    }))
  }

  const onChangeMaxDuration = (e: ChangeEvent<HTMLInputElement>) => {
    if ((Number(e.target.value) > 0 && Number(e.target.value) <= 100) || e.target.value === '') {
      setFormState((state) => ({
        ...state,
        duration: e.target.value,
      }))
    }
  }

  const onChangeTeam = (e: ChangeEvent<HTMLInputElement>) => {
    if (!e.target.value) {
      setTeams([])
    }

    setFormState((state: FormType) => ({
      ...state,
      playerValue: '',
      selectedPlayer: null,
      selectedTeam: null,
      teamValue: e?.target?.value,
    }))
    setPlayers([])
    setPlayerMatches([])
  }

  const onChangePlayer = (e: ChangeEvent<HTMLInputElement>) => {
    if (!/[A-Za-z\s]/g.test(e.target.value) && e.target.value.length) return

    if (!formState.selectedTeam) {
      e.target?.value?.length > 3
        && getSearchItems(formState.playerValue)
          .then((state) => {
            setPlayersData(state?.players?.map((player: PlayerTypeFromSearch) => ({
              ...player,
              name: `${player?.firstname_eng} ${player?.lastname_eng}`,
            })) || [])
            setPlayers(state?.players?.map((player: PlayerTypeFromSearch) => ({
              ...player,
              name: `${player?.firstname_eng} ${player?.lastname_eng}`,
            })) || [])
          })
    }
    setPlayerMatches([])
    setFormState((state: FormType) => ({
      ...state,
      playerValue: e?.target?.value,
      selectedPlayer: null,
      selectedTeam: state.selectedTeam ?? null,
    }))
    setPlayers(
      playersData?.filter(
        (player: PlayerType) => player
        && player?.name
          ?.toLowerCase()
          .indexOf(e?.target?.value.toLowerCase()) >= 0,
      ),
    )
  }

  useEffect(() => {
    getSportList()
      .then((res) => setSports(
        res
          ?.filter(({ id }: SportType) => id === 3 || id === 1)
          .map((sport: SportType) => ({
            ...sport,
            name: sport?.name_eng,
          })),
      ))

    getSounds()
      .then((state) => {
        setSounds([{
          asset: null,
          id: 100,
          name: 'No',
        },
        ...state,
        ])
        setFormState((prev) => ({
          ...prev,
          duration: '2',
          selectedSound: {
            asset: null,
            id: 100,
            name: 'No',
          },
        }))
      })
  }, [])

  useEffect(() => {
    onSportSelect(sports[0])
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [sports])

  useEffect(() => {
    if (playerHighlight?.sportType && playerHighlight?.profile) {
      // TODO: исправить any
      // eslint-disable-next-line
      setFormState((state: any) => ({
        ...state,
        selectedPlayer: {
          ...playerHighlight.profile,
          name: `${playerHighlight.profile?.name_eng}`,
        },
        selectedTeam: playerHighlight?.profile?.additionalInfo,
        sport: sports?.find((sportType) => sportType.id === playerHighlight.sportType),
      }))
    }
  }, [sports, playerHighlight, teams])

  const fetchTeams = useMemo(
    () => debounce(() => {
      setIsFetchingTeams(true)
      // eslint-disable-next-line @typescript-eslint/no-unused-expressions
      formState?.sport?.id
      && getSportTeams(
        formState?.sport?.id,
        -1,
        formState.teamValue,
      )
        .then(({ data }: SportTeamsType) => {
          setTeams(
            data?.map((team: Team) => ({
              ...team,
              name: team.name_eng,
            })),
          )
        })
        .finally(() => setIsFetchingTeams(false))
    }, 1000),
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [formState.teamValue],
  )

  useEffect(() => {
    if (checkedMatchesLength * 2 >= 2) {
      setFormState((prev) => ({
        ...prev,
        duration: (checkedMatchesLength * 2).toString(),
      }))
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [checkedMatchesLength])

  useEffect(() => {
    if (formState?.teamValue?.length >= 3 && formState?.sport) {
      fetchTeams()
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState.teamValue, formState?.sport, playerHighlight])

  useEffect(() => {
    if (formState?.selectedPlayer?.id && formState?.sport) {
      setDatahighlights({
        data: {
          background_music: formState?.selectedSound?.asset || null,
          duration: Number(formState?.duration) * 60,
          lang: 'en',
          matches: playerMatches?.filter(({ isChecked }) => (isChecked)).map(({ id }) => id),
          player_id: formState?.selectedPlayer?.id,
          price: checkedMatchesLength * 25,
          sport_id: formState?.sport.id,
          stats: Boolean(formState?.stats?.id),
        },
        isDisabledButton: true,
        isOpenThanksPopup: false,
      })
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState, playerMatches])

  useEffect(() => {
    formState?.selectedTeam?.id
    && getTeamPlayers(
      formState?.sport?.id || playerHighlight.sportType, formState?.selectedTeam?.id
        || playerHighlight?.profile?.additionalInfo?.id,
    )
      .then((state) => {
        setPlayersData(state?.map((player: Player) => ({
          ...player,
          name: `${player?.firstname_eng} ${player?.lastname_eng}`,
        })))
        setPlayers(state?.map((player: Player) => ({
          ...player,
          name: `${player?.firstname_eng} ${player?.lastname_eng}`,
        })))
      })
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState?.selectedTeam, playerHighlight])

  useEffect(() => {
    if (!formState?.selectedPlayer || !formState?.sport) return

    setIsFetching(true)
    formState?.selectedPlayer
    && getPlayerMatches({
      limit: 1000,
      offset: 0,
      p_match_completed: true,
      playerId: formState?.selectedPlayer?.id,
      sportType: formState?.sport?.id,
      sub_only: true,
    })
      .then(({ broadcast }) => setPlayerMatches(
        broadcast.map((match: Match) => ({ ...match, isChecked: false })),
      ))
      .finally(() => setIsFetching(false))

    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [formState?.selectedPlayer, formState?.selectedTeam])

  return {
    checkedMatchesLength,
    formRef,
    formState,
    isFetchingTeams,
    onChangeMaxDuration,
    onChangePlayer,
    onChangeTeam,
    onPlayerSelect,
    onSoundSelect,
    onSportSelect,
    onStatsSelect,
    onTeamSelect,
    playerMatches,
    players,
    sounds,
    sports,
    summaryStats,
    teams,
  }
}
