import Button from '@/components/ui/Button'
import Dialog from '@/components/ui/Dialog'
import { GLOBAL_SEARCH } from '@/constants/permission.constant'
import withHeaderItem from '@/utils/hoc/withHeaderItem'
import useThemeClass from '@/utils/hooks/useThemeClass'
import classNames from 'classnames'
import { useEffect, useRef, useState } from 'react'
import Highlighter from 'react-highlight-words'
import { HiChevronRight, HiOutlineSearch } from 'react-icons/hi'
import { Link } from 'react-router-dom'
import { PermissionCheck } from '../shared'
import { Badge, Checkbox, Pagination } from '../ui'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { getSearch, getSystems } from '@/services/global-search.service'

type SearchData = {
  title: string
  url: string
  icon?: string
  category?: string
  categoryTitle?: string
}

type SearchResult = {
  title: string
  badge?: string
  data: SearchData[]
}

const ListItem = (props: {
  icon?: string
  label: string
  url: string
  isLast?: boolean
  keyWord: string
  onNavigate: () => void
}) => {
  const { icon, label, url = '', isLast, keyWord, onNavigate } = props

  const { textTheme } = useThemeClass()

  return (
    <Link to={url} onClick={onNavigate}>
      <div
        className={classNames(
          'flex items-center justify-between rounded-lg p-3.5 cursor-pointer user-select',
          'bg-gray-50 dark:bg-gray-700/60 hover:bg-gray-100 dark:hover:bg-gray-700/90',
          !isLast && 'mb-3',
        )}
      >
        <div className="flex items-center">
          {/* <div
            className={classNames(
              'mr-4 rounded-md ring-1 ring-slate-900/5 shadow-sm text-xl group-hover:shadow h-6 w-6 flex items-center justify-center bg-white dark:bg-gray-700',
              textTheme,
              'dark:text-gray-100',
            )}
          >
            {icon && navigationIcon[icon]}
          </div> */}
          <div className="text-gray-900 dark:text-gray-300">
            <Highlighter
              autoEscape
              highlightClassName={classNames(
                textTheme,
                'underline bg-transparent font-semibold dark:text-white',
              )}
              searchWords={[keyWord]}
              textToHighlight={label}
            />
          </div>
        </div>
        <HiChevronRight className="text-lg" />
      </div>
    </Link>
  )
}

const _Search = ({ className }: { className?: string }) => {
  const [searchDialogOpen, setSearchDialogOpen] = useState(false)
  const [searchResult, setSearchResult] = useState<SearchResult[]>([])
  const [systems, setSystems] = useState<string[]>([])
  const [noResult, setNoResult] = useState(false)
  const [totalCount, setTotalCount] = useState(0)
  const [currentPage, setCurrentPage] = useState(1)
  const [currentSystems, setCurrentSystems] = useState<string[]>([])

  const { translate } = useLocalization()
  const inputRef = useRef<HTMLInputElement>(null)

  const handleReset = () => {
    setNoResult(false)
    setCurrentPage(1)
    setTotalCount(0)
    setSearchResult([])
  }

  const handleSearchOpen = async () => {
    const result = await getSystems()
    if (result?.data) {
      setSystems(result.data)
      setCurrentSystems(result.data)
    }
    setSearchDialogOpen(true)
  }

  const handleSearchClose = () => {
    setSearchDialogOpen(false)
    if (noResult) {
      setTimeout(() => {
        handleReset()
      }, 300)
    }
  }

  const handleSearch = async () => {
    const q = inputRef.current?.value
    if (!q || q.length < 3) return

    const result = await getSearch({ query: q, system: currentSystems, page: currentPage })

    if (!result.data?.totalCount || !result.data.items?.length) {
      setNoResult(true)
      setTotalCount(0)
      setSearchResult([])
      return
    }

    setTotalCount(result.data.totalCount)

    const results = result.data.items.reduce((acc, curr) => {
      const a = acc.find((item) => item.title === curr.group && item.badge === curr.system)
      if (a) {
        a.data.push({
          title: curr.term,
          url: curr.url,
        })
      } else {
        acc.push({
          title: curr.group,
          badge: curr.system,
          data: [
            {
              title: curr.term,
              url: curr.url,
            },
          ],
        })
      }

      return acc
    }, [] as SearchResult[])

    setSearchResult(results)
  }

  useEffect(() => {
    handleSearch()
  }, [currentPage])

  useEffect(() => {
    if (searchDialogOpen) {
      const timeout = setTimeout(() => inputRef.current?.focus(), 100)
      return () => {
        clearTimeout(timeout)
      }
    }
  }, [searchDialogOpen])

  const handleNavigate = () => {
    handleSearchClose()
  }

  return (
    <PermissionCheck permissions={[GLOBAL_SEARCH]}>
      <div className={classNames(className, 'text-2xl')} onClick={handleSearchOpen}>
        <HiOutlineSearch />
      </div>
      <Dialog
        contentClassName="p-0"
        isOpen={searchDialogOpen}
        closable={false}
        onRequestClose={handleSearchClose}
      >
        <div>
          <div className="px-4 flex items-center border-b border-gray-200 dark:border-gray-600">
            <div className="flex items-center flex-1">
              <HiOutlineSearch className="text-xl" />
              <input
                ref={inputRef}
                className="ring-0 outline-none block w-full p-4 text-base bg-transparent text-gray-900 dark:text-gray-100"
                placeholder={translate('::App.Search')}
                onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
              />
            </div>
            <Button size="xs" onClick={handleSearch}>
              <HiOutlineSearch />
            </Button>
          </div>
          <div>
            <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-600">
              <div className="flex items-center space-x-2">
                <span className="text-sm">{translate('::App.SearchIn')}</span>
                <Checkbox.Group
                  value={currentSystems}
                  onChange={(value) => setCurrentSystems(value as string[])}
                >
                  {systems.map((system) => (
                    <Checkbox key={system} value={system}>
                      {system}
                    </Checkbox>
                  ))}
                </Checkbox.Group>
              </div>
            </div>
          </div>
          <div className="py-6 px-5 max-h-[550px] overflow-y-auto">
            {searchResult.map((result) => (
              <div key={`${result.title}-${result.badge}`} className="mb-6">
                <div className="flex items-center justify-between mb-1">
                  <h6 className="mb-3">{result.title}</h6>
                  <Badge content={result.badge} />
                </div>

                {result.data.map((data, index) => (
                  <ListItem
                    key={data.title + index}
                    icon={data.icon}
                    label={data.title}
                    url={data.url}
                    keyWord={inputRef.current?.value || ''}
                    onNavigate={handleNavigate}
                  />
                ))}
              </div>
            ))}
            {searchResult.length === 0 && noResult && (
              <div className="my-10 text-center text-lg">
                <span>{translate('::App.NoResults')}</span>
                <div className="heading-text">'{inputRef.current?.value}'</div>
              </div>
            )}
            <Pagination
              className="float-right"
              total={totalCount}
              currentPage={currentPage}
              pageSize={10}
              onChange={setCurrentPage}
            />
          </div>
        </div>
      </Dialog>
    </PermissionCheck>
  )
}

const Search = withHeaderItem(_Search)

export default Search
