import {
  autoUpdate,
  FloatingFocusManager,
  FloatingPortal,
  flip,
  size,
  useDismiss,
  useFloating,
  useInteractions,
  useListNavigation,
  useRole,
} from '@floating-ui/react'
import Fuse from 'fuse.js'
import { useAtom, useAtomValue } from 'jotai'
import { forwardRef, useId, useMemo, useRef, useState } from 'react'
import { charactersAtom, selectedCharacterAtom, selectedTargetInventoryAtom } from '@/state/atoms'

interface AccountInventorySelectorItemProps {
  children: React.ReactNode
  active: boolean
}

const AccountInventorySelectorItem = forwardRef<
  HTMLDivElement,
  AccountInventorySelectorItemProps & React.HTMLProps<HTMLDivElement>
>(({ children, active, ...rest }, ref) => {
  const id = useId()
  const isDisabled = rest['aria-disabled']
  return (
    <div
      ref={ref}
      // biome-ignore lint/a11y/useSemanticElements: Custom autocomplete component needs role="option"
      role="option"
      id={id}
      aria-selected={active}
      aria-disabled={isDisabled}
      tabIndex={-1}
      {...rest}
      style={{
        background: active && !isDisabled ? 'lightblue' : 'none',
        padding: 4,
        cursor: isDisabled ? 'not-allowed' : 'default',
        opacity: isDisabled ? 0.5 : 1,
        ...rest.style,
      }}
    >
      {children}
    </div>
  )
})
export const InventoryTargetSelector = () => {
  const [open, setOpen] = useState(false)
  const [inputValue, setInputValue] = useState('')
  const [activeIndex, setActiveIndex] = useState<number | null>(null)

  const listRef = useRef<Array<HTMLElement | null>>([])

  const { refs, floatingStyles, context } = useFloating<HTMLInputElement>({
    whileElementsMounted: autoUpdate,
    open,
    onOpenChange: setOpen,
    middleware: [
      flip({ padding: 10 }),
      size({
        apply({ rects, availableHeight, elements }) {
          Object.assign(elements.floating.style, {
            width: `${Math.max(rects.reference.width * 2, 400)}px`,
            maxHeight: `${availableHeight}px`,
          })
        },
        padding: 10,
      }),
    ],
  })

  const role = useRole(context, { role: 'listbox' })
  const dismiss = useDismiss(context)
  const listNav = useListNavigation(context, {
    listRef,
    activeIndex,
    onNavigate: setActiveIndex,
    virtual: true,
    loop: true,
  })

  const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
    role,
    dismiss,
    listNav,
  ])

  function onChange(event: React.ChangeEvent<HTMLInputElement>) {
    const value = event.target.value
    setInputValue(value)
    setSelectedTargetInventory(undefined)

    if (value) {
      setOpen(true)
      setActiveIndex(0)
    } else {
      setOpen(false)
    }
  }
  const { data: subaccounts } = useAtomValue(charactersAtom)
  const selectedCharacter = useAtomValue(selectedCharacterAtom)

  const [selectedTargetInventory, setSelectedTargetInventory] = useAtom(selectedTargetInventoryAtom)

  const searcher = useMemo(() => {
    const allInventories = subaccounts?.flatMap(x => [x.bank, x.character]) || []
    // Don't filter out current character, we'll disable it in the UI
    return new Fuse(allInventories, {
      keys: ['path', 'name'],
      findAllMatches: true,
      threshold: 0.8,
      useExtendedSearch: true,
    })
  }, [subaccounts])

  const items = inputValue
    ? searcher.search(inputValue, { limit: 10 }).map(x => x.item)
    : subaccounts?.flatMap(x => [x.bank, x.character]).slice(0, 10) || []
  return (
    <>
      <input
        className={`border border-black-1 placeholder-gray-600 ${
          selectedTargetInventory ? 'bg-green-100' : inputValue ? 'bg-yellow-200' : 'bg-gray-300'
        }`}
        {...getReferenceProps({
          ref: refs.setReference,
          onChange,
          value:
            selectedTargetInventory !== undefined
              ? !selectedTargetInventory.path.includes('/')
                ? `[Bank] ${selectedTargetInventory.account_name}`
                : selectedTargetInventory.name
              : inputValue,
          placeholder: 'Target Inventory',
          'aria-autocomplete': 'list',
          onFocus() {
            setOpen(true)
          },
          onKeyDown(event) {
            if (event.key === 'Enter' && activeIndex != null && items[activeIndex]) {
              setSelectedTargetInventory(items[activeIndex])
              setInputValue('')
              setActiveIndex(null)
              setOpen(false)
            }
          },
        })}
      />
      {open && (
        <FloatingPortal>
          <FloatingFocusManager context={context} initialFocus={-1} visuallyHiddenDismiss>
            <div
              {...getFloatingProps({
                ref: refs.setFloating,
                style: {
                  ...floatingStyles,
                  background: '#eee',
                  color: 'black',
                  overflowY: 'auto',
                },
              })}
            >
              <div style={{ display: 'flex', flexDirection: 'row', gap: '10px', padding: '5px' }}>
                <div style={{ flex: 1 }}>
                  {items
                    .filter(item => item.path.includes('/'))
                    .map(item => {
                      const actualIndex = items.indexOf(item)
                      const isDisabled = item.path === selectedCharacter?.path
                      return (
                        <AccountInventorySelectorItem
                          key={item.path}
                          {...getItemProps({
                            ref(node) {
                              listRef.current[actualIndex] = node
                            },
                            onClick() {
                              if (!isDisabled) {
                                setInputValue('')
                                setSelectedTargetInventory(item)
                                setOpen(false)
                                refs.domReference.current?.focus()
                              }
                            },
                          })}
                          active={activeIndex === actualIndex}
                          aria-disabled={isDisabled}
                        >
                          {item.name}
                        </AccountInventorySelectorItem>
                      )
                    })}
                </div>
                <div style={{ flex: 1 }}>
                  {items
                    .filter(item => !item.path.includes('/'))
                    .map(item => {
                      const actualIndex = items.indexOf(item)
                      const isDisabled = item.path === selectedCharacter?.path
                      return (
                        <AccountInventorySelectorItem
                          key={item.path}
                          {...getItemProps({
                            ref(node) {
                              listRef.current[actualIndex] = node
                            },
                            onClick() {
                              if (!isDisabled) {
                                setInputValue('')
                                setSelectedTargetInventory(item)
                                setOpen(false)
                                refs.domReference.current?.focus()
                              }
                            },
                          })}
                          active={activeIndex === actualIndex}
                          aria-disabled={isDisabled}
                        >
                          [Bank] {item.account_name}
                        </AccountInventorySelectorItem>
                      )
                    })}
                </div>
              </div>
            </div>
          </FloatingFocusManager>
        </FloatingPortal>
      )}
    </>
  )
}
