import React, { useEffect, useRef, useState } from 'react'
import { type useVirtualizer } from '@tanstack/react-virtual'

import Button from '../../Button/Button'
import EmptyState from '../../EmptyState/EmptyState'
import Icon from '../../Icons/Icon'
import isClient from '../../../services/isClient'
import Popover from '../../Popover/Popover'
import SearchBar from '../../SearchBar/SearchBar'
import { useIsMobileView } from '../../../hooks/useIsMobileView/useIsMobileView'
import styles from './_pagination-ellipsis.module.scss'
import { SelectDisplayRow } from '../../Selects/SelectDisplay/SelectDisplay'
import { Virtual } from '../../Virtual/Virtual'
import ScrollingContainer from '../../ScrollingContainer/ScrollingContainer'
import { c } from '../../../translations/LibraryTranslationService'

type PaginationEllipsisProps = {
  activePage: number
  position: 'start' | 'end'
  lastPage: number
  updatePage: (page: number) => void
  pageOptions: { name: string; label: string }[]
}

const PaginationEllipsis = ({
  activePage,
  position,
  lastPage,
  updatePage,
  pageOptions,
}: PaginationEllipsisProps): React.JSX.Element => {
  const [showPopover, setShowPopover] = useState(false)
  const [searchValue, setSearchValue] = useState('')
  const [options, setOptions] = useState(pageOptions)
  const [filteredOptions, setFilteredOptions] = useState<
    {
      name: string
      label: string
    }[]
  >([])
  const searchBarRef = useRef<HTMLInputElement>(null)
  const searchBarTimeout = useRef<ReturnType<typeof setTimeout>>(undefined)
  const optionTimeout = useRef<ReturnType<typeof setTimeout>>(undefined)
  const scrollTimeout = useRef<ReturnType<typeof setTimeout>>(undefined)
  const isMobileView = useIsMobileView()

  useEffect(() => {
    if (showPopover && searchBarRef.current) {
      searchBarTimeout.current = setTimeout(() => {
        searchBarRef.current?.focus()
      }, 250)
    }
    return () => {
      clearTimeout(searchBarTimeout.current)
    }
  }, [showPopover])

  useEffect(() => {
    return () => {
      clearTimeout(optionTimeout.current)
      clearTimeout(scrollTimeout.current)
    }
  }, [])

  const updateSearch = (searchValue: string) => {
    setSearchValue(searchValue)

    const filteredOptions = searchValue
      ? options.filter((option) =>
          option.name
            .toLowerCase()
            .includes(searchValue.replace(/,/g, '').toLowerCase()),
        )
      : options

    setFilteredOptions(filteredOptions)
  }

  useEffect(() => {
    const createPagesArray = (): { name: string; label: string }[] => {
      let startPage: number
      let endPage: number

      if (isMobileView) {
        // For mobile, use the full range
        startPage = 1
        endPage = lastPage + 1
      } else {
        if (position === 'start') {
          startPage = 2
          endPage = activePage + 4 > lastPage ? lastPage - 4 : activePage - 1
        } else {
          startPage = activePage > 3 ? activePage + 3 : 6
          endPage = lastPage
        }
      }

      return Array.from({ length: endPage - startPage + 1 }, (_, i) => ({
        name: (i + startPage).toString(),
        label: (i + startPage).toLocaleString(),
      }))
    }

    const newOptions = createPagesArray()
    setOptions(newOptions)
    setFilteredOptions(newOptions)
  }, [activePage, lastPage, position, isMobileView])

  const renderContent = (
    virtualizer: ReturnType<typeof useVirtualizer>,
    virtualizedParentRef: React.RefObject<HTMLDivElement>,
    setVisible?: (visible: boolean) => void,
  ) => (
    <div className={styles.popoverContainer}>
      <div className={styles.searchBarContainer}>
        <SearchBar
          value={searchValue}
          onChange={updateSearch}
          minWidth={100}
          placeholder={c('pageNumbers')}
          ref={searchBarRef}
        />
      </div>
      {filteredOptions.length === 0 ? (
        <EmptyState
          primaryText={c('noPagesFound')}
          secondaryText={c('updateSearchField')}
        />
      ) : (
        <ScrollingContainer ref={virtualizedParentRef}>
          <Virtual.List virtualizer={virtualizer}>
            {({ index }) => (
              <SelectDisplayRow
                callout={(option) => {
                  setSearchValue('')
                  setShowPopover(false)
                  setVisible && setVisible(false)
                  optionTimeout.current = setTimeout(() => {
                    updatePage(Number(option.name) - 1)
                    virtualizer.scrollToIndex(0)
                  }, 200)
                }}
                option={filteredOptions[index]}
              />
            )}
          </Virtual.List>
        </ScrollingContainer>
      )}
    </div>
  )

  return (
    <Virtual count={filteredOptions.length}>
      {({ virtualizer, virtualizedParentRef }) => (
        <Popover
          position='top'
          {...(isClient ? { appendTo: document.body } : {})}
          onClickOutside={() => {
            setShowPopover(false)
            scrollTimeout.current = setTimeout(() => {
              virtualizer.scrollToIndex(0)
            }, 200)
          }}
          noPadding
          popoverContent={({ setVisible }) =>
            renderContent(
              virtualizer,
              virtualizedParentRef as unknown as React.RefObject<HTMLDivElement>,
              setVisible,
            )
          }
        >
          {({ setVisible }) => (
            <div>
              {isMobileView ? (
                <Button
                  onClick={() => {
                    setVisible(!showPopover)
                    setTimeout(() => setShowPopover(!showPopover), 250) // To ensure Popover is rendered after the animation, so virtualizedParentRef and searchBarRef are set correctly
                  }}
                  className={styles.currentPageButton}
                >
                  <div className={styles.iconContainer}>
                    {activePage + 1}
                    <Icon icon='carat' iconSize='8px' />
                  </div>
                </Button>
              ) : (
                <Button
                  className={styles.ellipsis}
                  onClick={() => {
                    setTimeout(() => setShowPopover(!showPopover), 250)
                    setVisible(!showPopover)
                  }}
                >
                  <Icon icon='options' color='dark-purple' iconSize='12px' />
                </Button>
              )}
            </div>
          )}
        </Popover>
      )}
    </Virtual>
  )
}

export default PaginationEllipsis
