import { css, cx } from "@emotion/css"
import styled from "@emotion/styled"
import { useEffect, useMemo, useRef, useState } from "react"
import { menuClassName } from "~/options/hooks/useDropdownMenu"
import { token } from "~/options/theme"
import { useEvent } from "@aet/hooks"

export interface Pos {
  x: number
  y: number
}

export function SuggestionMenu({
  onAddTag,
  onClose,
  inputPos: pos,
  suggestions = [],
  inputValue,
  currentValues: values,
}: {
  onAddTag: (tag: string) => void
  onClose: () => void
  inputPos: Pos | null
  suggestions?: string[]
  inputValue: string
  currentValues: string[]
}) {
  const open = pos != null
  const menuRef = useRef<HTMLUListElement>(null)
  const [maxHeight, setMaxHeight] = useState("200px")

  const searchTerm = useMemo(() => inputValue.toUpperCase(), [inputValue])
  const filteredSuggestions = useMemo(
    () =>
      searchTerm
        ? suggestions.filter(s => s.toUpperCase().includes(searchTerm))
        : suggestions,
    [suggestions, searchTerm],
  )

  useEffect(() => {
    if (open && menuRef.current) {
      const { top } = menuRef.current.getBoundingClientRect()
      setMaxHeight(`calc(100vh - ${top}px - 20px)`)
    }
  }, [open])

  if (!pos || !filteredSuggestions.length) {
    return null
  }

  return (
    <Suggestions style={{ position: "fixed", top: pos.y, left: pos.x }}>
      <div className={menuClassName}>
        <ul
          role="menu"
          aria-label="Menu"
          ref={menuRef}
          style={{ maxHeight }}
          className={cx(
            "szh-menu",
            open && "szh-menu--state-open",
            css`
              overflow-y: auto;
            `,
          )}
        >
          {filteredSuggestions
            .filter(suggestion => !values.includes(suggestion))
            .map(suggestion => (
              <Suggestion
                key={suggestion}
                suggestion={suggestion}
                onAddTag={onAddTag}
                onClose={onClose}
              />
            ))}
        </ul>
      </div>
    </Suggestions>
  )
}

function Suggestion({
  suggestion,
  onAddTag,
  onClose,
}: {
  suggestion: string
  onAddTag: (tag: string) => void
  onClose: () => void
}) {
  const add = useEvent(() => {
    onAddTag(suggestion)
    onClose()
  })

  return (
    <li
      role="menuitem"
      className={cx(
        "szh-menu__item",
        css`
          &:focus {
            outline: 1px solid ${token.border.default};
          }
        `,
      )}
      key={suggestion}
      tabIndex={0}
      onClick={add}
      onKeyDown={e => {
        if (e.key === "Enter") {
          add()
        } else if (e.key === "Escape") {
          onClose()
        }
      }}
    >
      {suggestion}
    </li>
  )
}

const Suggestions = styled.div`
  position: fixed;
`
