import {
  useEffect,
  useState,
  useMemo,
} from 'react'
import { useHistory } from 'react-router'

import includes from 'lodash/includes'
import filter from 'lodash/filter'
import isEmpty from 'lodash/isEmpty'

import { PAGES } from 'config'

import { useAuthStore } from 'features/AuthStore'
import { Tabs } from 'features/MatchSidePlaylists/config'
import { initialCircleAnimation } from 'features/CircleAnimationBar'
import type { TCircleAnimation } from 'features/CircleAnimationBar'
import { StatsType } from 'features/MatchSidePlaylists/components/TabStats/config'
import { PlaylistTypes } from 'features/MatchPage/types'
import { FULL_GAME_KEY } from 'features/MatchPage/helpers/buildPlaylists'

import type { MatchInfo } from 'requests/getMatchInfo'
import { getMatchInfo } from 'requests/getMatchInfo'
import { getViewMatchDuration } from 'requests/getViewMatchDuration'
import { getLandingStatus } from 'requests/getLandingStatus'

import { usePageParams, useToggle } from 'hooks'

import { redirectToUrl } from 'helpers/redirectToUrl'
import { parseDate } from 'helpers/parseDate'

import { useAds } from 'components/Ads/hooks'

import { useTournamentData } from './useTournamentData'
import { useMatchData } from './useMatchData'
import { useFiltersPopup } from './useFitersPopup'
import { useTabEvents } from './useTabEvents'
import { useTeamsStats } from './useTeamsStats'
import { useStatsTab } from './useStatsTab'
import { usePlayersStats } from './usePlayersStats'
import { useLexicsStore } from '../../../LexicsStore'

type PlayingData = {
  player: {
    id: number | null,
    paramId: number | null,
  },
  team: {
    id: number | null,
    paramId: number | null,
  },
}

type EpisodeInfo = {
  episodesCount?: number,
  paramName?: string,
  playerOrTeamName?: string,
}

const initPlayingData: PlayingData = {
  player: {
    id: null,
    paramId: null,
  },
  team: {
    id: null,
    paramId: null,
  },
}

const ACCESS_TIME = 60

export const useMatchPage = () => {
  const [matchProfile, setMatchProfile] = useState<MatchInfo>(null)
  const [watchAllEpisodesTimer, setWatchAllEpisodesTimer] = useState(false)
  const [isFullscreen, setIsFullScreen] = useState(false)
  const [access, setAccess] = useState(true)
  const [playingProgress, setPlayingProgress] = useState(0)
  const [playingData, setPlayingData] = useState<PlayingData>(initPlayingData)
  const [playingOrder, setPlaingOrder] = useState(0)
  const [isPlayFilterEpisodes, setIsPlayingFiltersEpisodes] = useState(false)
  const [selectedTab, setSelectedTab] = useState<Tabs>(Tabs.WATCH)
  const [circleAnimation, setCircleAnimation] = useState<TCircleAnimation>(initialCircleAnimation)
  const [episodeInfo, setEpisodeInfo] = useState<EpisodeInfo>({
    episodesCount: 0,
    paramName: '',
    playerOrTeamName: '',
  })
  const { suffix } = useLexicsStore()

  const { profileId: matchId, sportType } = usePageParams()

  const { ads } = useAds({
    matchId,
    sportType,
    tournamentId: matchProfile?.tournament?.id,
  })

  useEffect(() => {
    sessionStorage.removeItem('isFromLanding')
  }, [])

  const {
    isFromLanding,
    landingUrlFrom,
    setIsFromLanding,
    setLandingUrlFrom,
    user,
    userInfo,
  } = useAuthStore()
  const history = useHistory()

  const {
    close: hideProfileCard,
    isOpen: profileCardShown,
    open: showProfileCard,
  } = useToggle(true)

  const {
    events,
    handlePlaylistClick,
    matchPlaylists,
    selectedPlaylist,
    setFullMatchPlaylistDuration,
  } = useMatchData({ matchProfile, selectedTab })

  const profile = matchProfile

  const isPlayingEpisode = selectedPlaylist.id !== FULL_GAME_KEY

  const isStatsPlaylist = selectedPlaylist.tab === Tabs.STATS

  const {
    activeEvents,
    activeFirstTeamPlayers,
    activeSecondTeamPlayers,
    allActionsToggle,
    allPlayersToggle,
    applyFilters,
    close: closePopup,
    countOfFilters,
    filters,
    isAllActionsChecked,
    isEmptyFilters,
    isFirstTeamPlayersChecked,
    isOpen: isOpenFiltersPopup,
    isSecondTeamPlayersChecked,
    toggle: togglePopup,
    toggleActiveEvents,
    toggleActivePlayers,
    uniqEvents,
  } = useFiltersPopup({
    events,
    matchPlaylists,
  })

  const getMatchViewDuration = (id: number) => (getViewMatchDuration({
    matchId,
    sportType,
    userId: id,
  }).then(({
    duration,
    error,
  }) => {
    if (error || (duration && Number(duration) > ACCESS_TIME)) {
      setAccess(false)
    }
  }))

  useEffect(() => {
    if (user || isFromLanding || history.length > 1) return
    setLandingUrlFrom(window.location.pathname)
    getLandingStatus({ matchId, sportType })
      .then((data) => {
        sessionStorage.setItem(
          'landingData',
          JSON.stringify({ ...data, defaultLanding: false }),
        )
        setIsFromLanding(false)
        if (data.landing_id) redirectToUrl(`${PAGES.landing}/${data.landing_id}`)
      })
      .catch(() => {
        getMatchInfo(sportType, matchId).then((data) => {
          sessionStorage.setItem('landingData', JSON.stringify({
            defaultLanding: true,
            sportType,
            tournamentId: data?.tournament.id,
          }))
          redirectToUrl(`
            ${PAGES.landing}/default
              ?season=${data?.season.name}
              &tournament=${data?.tournament[`name_${suffix}`]}`)
        })
      })
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    setLandingUrlFrom,
    isFromLanding,
    landingUrlFrom,
    matchId,
    setIsFromLanding,
    sportType,
    user,
  ])

  useEffect(() => {
    getMatchInfo(sportType, matchId).then(
      (info) => (info?.sport
      // проверяем именно какой-то ключ в объекте,
      // потому что, когда матча не существует, приходит - []
        ? setMatchProfile(info) : window.location.replace(PAGES.home)),
    )
  }, [sportType, matchId])

  useEffect(() => {
    let getIntervalMatch: ReturnType<typeof setInterval>
    if (matchProfile?.live && !matchProfile.youtube_link) {
      getIntervalMatch = setInterval(
        () => getMatchInfo(sportType, matchId).then(setMatchProfile),
        1000 * 60 * 3,
      )
    }
    return () => clearInterval(getIntervalMatch)
  }, [
    matchProfile,
    sportType,
    matchId,
  ])

  useEffect(() => {
    if (user || !userInfo?.email) return

    const counter = setInterval(
      () => getMatchViewDuration(Number(userInfo?.email)),
      1000 * 30,
    )
    // eslint-disable-next-line
    return () => clearInterval(counter)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    sportType,
    matchId,
    userInfo,
  ])

  const disablePlayingStatsEpisodes = () => {
    setStatsIsPlayinFiltersEpisodes(false)
    setStatsWatchAllEpisodesTimer(false)
    setStatsCircleAnimation(initialCircleAnimation)
    setStatsPlaingOrder(0)
  }

  const disablePlayingPlaysEpisodes = () => {
    setIsPlayingFiltersEpisodes(false)
    setWatchAllEpisodesTimer(false)
    setCircleAnimation(initialCircleAnimation)
    setPlaingOrder(0)
  }

  const disablePlayingEpisodes = () => {
    isStatsPlaylist ? disablePlayingStatsEpisodes() : disablePlayingPlaysEpisodes()
  }

  useEffect(() => {
    if (selectedPlaylist.type !== PlaylistTypes.EVENT) {
      disablePlayingStatsEpisodes()
      disablePlayingPlaysEpisodes()
    } else {
      !isStatsPlaylist ? disablePlayingStatsEpisodes() : disablePlayingPlaysEpisodes()
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [selectedPlaylist])

  const {
    circleAnimation: statsCircleAnimation,
    filteredEvents: statsFilteredEvents,
    isExpanded,
    isPlayersStatsFetching,
    isPlayFilterEpisodes: isStatsPlayFilterEpisodes,
    isTeamsStatsFetching,
    playEpisodes: playStatsEpisodes,
    playingOrder: statsPlaingOrder,
    playNextEpisode: playStatsNextEpisode,
    reduceTable,
    selectedStatsTable,
    setCircleAnimation: setStatsCircleAnimation,
    setIsPlayersStatsFetching,
    setIsPlayingFiltersEpisodes: setStatsIsPlayinFiltersEpisodes,
    setIsTeamsStatsFetching,
    setPlaingOrder: setStatsPlaingOrder,
    setSelectedStatsTable,
    setStatsType,
    setWatchAllEpisodesTimer: setStatsWatchAllEpisodesTimer,
    statsType,
    toggleIsExpanded,
    toggleStatsType,
    watchAllEpisodesTimer: statsWatchAllEpisodesTimer,
  } = useStatsTab({
    disablePlayingEpisodes,
    handlePlaylistClick,
    matchProfile,
    selectedPlaylist,
  })

  const {
    beforeCloseTourCallback: beforeCloseTourCallbackTeams,
    getFirstClickableParam,
    isClickable,
    teamsStats,
  } = useTeamsStats({
    matchProfile,
    playingProgress,
    selectedStatsTable,
    selectedTab,
    setIsTeamsStatsFetching,
    statsType,
  })

  const {
    beforeCloseTourCallback: beforeCloseTourCallbackPlayers,
    getParams,
    playersData,
    playersStats,
  } = usePlayersStats({
    matchProfile,
    playingProgress,
    selectedStatsTable,
    selectedTab,
    setIsPlayersStatsFetching,
    statsType,
  })

  const beforeCloseTourCallback = () => {
    beforeCloseTourCallbackPlayers()
    beforeCloseTourCallbackTeams()

    setStatsType(profile?.live ? StatsType.CURRENT_STATS : StatsType.FINAL_STATS)
    isExpanded && toggleIsExpanded()
  }

  const isStarted = useMemo(() => (
    profile?.date
      ? parseDate(profile.date) < new Date()
      : true
  ), [profile?.date])

  const { tournamentData } = useTournamentData(matchProfile)

  const filteredEvents = useMemo(() => {
    switch (true) {
      case (!isEmpty(filters.events) && !isEmpty(filters.players)):
        return filter(events, (event) => includes(filters.players, event.p)
          && includes(filters.events, event.l))
      case (!isEmpty(filters.players)):
        return filter(events, (event) => includes(filters.players, event.p))
      case (!isEmpty(filters.events)):
        return filter(events, (event) => includes(filters.events, event.l))
      default: return events
    }
  }, [events, filters])

  const {
    activeStatus,
    episodesToPlay,
    isLiveMatch,
    likeImage,
    likeToggle,
    reversedGroupEvents,
    setReversed,
    setUnreversed,
  } = useTabEvents({ events: filteredEvents, profile })

  const playNextEpisode = (order?: number) => {
    const isLastEpisode = playingOrder === episodesToPlay.length

    const currentOrder = order === 0 ? order : playingOrder

    if (isLastEpisode || !episodesToPlay[currentOrder]) {
      setIsPlayingFiltersEpisodes(false)
      setPlaingOrder(0)

      return
    }

    handlePlaylistClick({
      playlist: episodesToPlay[currentOrder],
      tab: Tabs.EVENTS,
    })

    setPlaingOrder(currentOrder + 1)
  }

  const playEpisodes = () => {
    setPlayingData(initPlayingData)
    setStatsWatchAllEpisodesTimer(true)
    setStatsIsPlayinFiltersEpisodes(false)
    setStatsCircleAnimation(initialCircleAnimation)

    if (!watchAllEpisodesTimer) {
      setWatchAllEpisodesTimer(true)
    }

    setIsPlayingFiltersEpisodes(true)
    playNextEpisode(0)
  }

  return {
    access,
    activeEvents,
    activeFirstTeamPlayers,
    activeSecondTeamPlayers,
    activeStatus,
    ads,
    allActionsToggle,
    allPlayersToggle,
    applyFilters,
    beforeCloseTourCallback,
    circleAnimation: isStatsPlaylist ? statsCircleAnimation : circleAnimation,
    closePopup,
    countOfFilters,
    disablePlayingEpisodes,
    episodeInfo,
    events,
    filteredEvents: isStatsPlaylist ? statsFilteredEvents : filteredEvents,
    getFirstClickableParam,
    getParams,
    handlePlaylistClick,
    hideProfileCard,
    isAllActionsChecked,
    isClickable,
    isEmptyFilters,
    isExpanded,
    isFirstTeamPlayersChecked,
    isFullscreen,
    isLiveMatch,
    isOpenFiltersPopup,
    isPlayFilterEpisodes: isStatsPlaylist ? isStatsPlayFilterEpisodes : isPlayFilterEpisodes,
    isPlayersStatsFetching,
    isPlayingEpisode,
    isSecondTeamPlayersChecked,
    isStarted,
    isTeamsStatsFetching,
    likeImage,
    likeToggle,
    matchPlaylists,
    playEpisodes,
    playNextEpisode: isStatsPlaylist ? playStatsNextEpisode : playNextEpisode,
    playStatsEpisodes,
    playersData,
    playersStats,
    playingData,
    playingOrder: isStatsPlaylist ? statsPlaingOrder : playingOrder,
    playingProgress,
    profile,
    profileCardShown,
    reduceTable,
    reversedGroupEvents,
    selectedPlaylist,
    selectedStatsTable,
    selectedTab,
    setCircleAnimation: isStatsPlaylist ? setStatsCircleAnimation : setCircleAnimation,
    setEpisodeInfo,
    setFullMatchPlaylistDuration,
    setIsFullScreen,
    setIsPlayingFiltersEpisodes: isStatsPlaylist
      ? setStatsIsPlayinFiltersEpisodes
      : setIsPlayersStatsFetching,
    setMatchProfile,
    setPlaingOrder: isStatsPlaylist ? setStatsPlaingOrder : setPlaingOrder,
    setPlayingData,
    setPlayingProgress,
    setReversed,
    setSelectedStatsTable,
    setSelectedTab,
    setStatsType,
    setUnreversed,
    setWatchAllEpisodesTimer: isStatsPlaylist
      ? setStatsWatchAllEpisodesTimer
      : setWatchAllEpisodesTimer,
    showProfileCard,
    statsType,
    teamsStats,
    toggleActiveEvents,
    toggleActivePlayers,
    toggleIsExpanded,
    togglePopup,
    toggleStatsType,
    tournamentData,
    uniqEvents,
    user,
    watchAllEpisodesTimer: isStatsPlaylist ? statsWatchAllEpisodesTimer : watchAllEpisodesTimer,
  }
}
