import type {
  SyntheticEvent,
  Dispatch,
  SetStateAction,
} from 'react'
import {
  useRef,
  useState,
  useEffect,
  useMemo,
} from 'react'

import size from 'lodash/size'
import isNil from 'lodash/isNil'
import reduce from 'lodash/reduce'
import forEach from 'lodash/forEach'
import values from 'lodash/values'
import round from 'lodash/round'
import map from 'lodash/map'

import { isMobileDevice } from 'config'

import type { PlayerParam, PlayersStats } from 'requests'

import { useToggle } from 'hooks'

import { useMatchPageStore } from 'features/MatchPage/store'
import { useLexicsConfig } from 'features/LexicsStore'

import type { SortCondition } from '../types'
import {
  PARAM_COLUMN_WIDTH,
  DISPLAYED_PARAMS_COLUMNS,
  FIRST_COLUMN_WIDTH_DEFAULT,
  SCROLLBAR_WIDTH,
} from '../config'

type UseTableArgs = {
  setSortCondition: Dispatch<SetStateAction<SortCondition>>,
  teamId: number,
}

type HeaderParam = Pick<PlayerParam, 'id' | 'lexica_short' | 'lexic'>

export const useTable = ({
  setSortCondition,
  teamId,
}: UseTableArgs) => {
  const containerRef = useRef<HTMLDivElement>(null)
  const tableWrapperRef = useRef<HTMLDivElement>(null)

  const [showLeftArrow, setShowLeftArrow] = useState(false)
  const [showRightArrow, setShowRightArrow] = useState(false)

  const { isOpen: isExpanded, toggle: toggleIsExpanded } = useToggle()
  const { playersStats } = useMatchPageStore()

  const params = useMemo(() => (
    reduce<PlayersStats, Record<string, HeaderParam>>(
      playersStats[teamId],
      (acc, curr) => {
        forEach(values(curr), ({
          id,
          lexic,
          lexica_short,
        }) => {
          acc[id] = acc[id] || {
            id,
            lexic,
            lexica_short,
          }
        })

        return acc
      },
      {},
    )
  ), [playersStats, teamId])

  const lexics = useMemo(() => (
    reduce<HeaderParam, Array<number>>(
      values(params),
      (acc, { lexic, lexica_short }) => {
        if (lexic) acc.push(lexic)
        if (lexica_short) acc.push(lexica_short)

        return acc
      },
      [],
    )
  // eslint-disable-next-line react-hooks/exhaustive-deps
  ), [map(params, 'id').sort().join('')])

  useLexicsConfig(lexics)

  const paramsCount = size(params)

  const getParamColumnWidth = () => {
    const rest = (
      (containerRef.current?.clientWidth || 0) - FIRST_COLUMN_WIDTH_DEFAULT - SCROLLBAR_WIDTH
    )
    const desktopWith = PARAM_COLUMN_WIDTH
    const mobileWidth = paramsCount < DISPLAYED_PARAMS_COLUMNS ? 0 : rest / DISPLAYED_PARAMS_COLUMNS

    return isMobileDevice ? mobileWidth : desktopWith
  }

  const getFirstColumnWidth = () => {
    if (isExpanded) return 0

    return paramsCount < DISPLAYED_PARAMS_COLUMNS ? 0 : FIRST_COLUMN_WIDTH_DEFAULT
  }

  const paramColumnWidth = getParamColumnWidth()
  const firstColumnWidth = getFirstColumnWidth()

  const slideLeft = () => tableWrapperRef.current?.scrollBy(-paramColumnWidth, 0)
  const slideRight = () => tableWrapperRef.current?.scrollBy(paramColumnWidth, 0)

  const getDisplayedValue = ({ val }: PlayerParam) => (isNil(val) ? '-' : round(val, 2))

  const handleScroll = (e: SyntheticEvent<HTMLDivElement>) => {
    const {
      clientWidth,
      scrollLeft,
      scrollWidth,
    } = e.currentTarget

    const scrollRight = scrollWidth - (scrollLeft + clientWidth)

    setShowLeftArrow(scrollLeft > 0)
    setShowRightArrow(scrollRight > 0)
  }

  const handleSortClick = (paramId: number) => () => {
    setSortCondition((curr) => ({
      dir: curr.dir === 'asc' || curr.paramId !== paramId ? 'desc' : 'asc',
      paramId,
    }))
  }

  useEffect(() => {
    const {
      clientWidth = 0,
      scrollLeft = 0,
      scrollWidth = 0,
    } = tableWrapperRef.current || {}

    const scrollRight = scrollWidth - (scrollLeft + clientWidth)

    setShowRightArrow(scrollRight > 0)
  }, [isExpanded])

  return {
    containerRef,
    firstColumnWidth,
    getDisplayedValue,
    handleScroll,
    handleSortClick,
    isExpanded,
    paramColumnWidth,
    params,
    showExpandButton: !isMobileDevice && paramsCount > DISPLAYED_PARAMS_COLUMNS,
    showLeftArrow,
    showRightArrow,
    slideLeft,
    slideRight,
    tableWrapperRef,
    toggleIsExpanded,
  }
}
