"use client"

import { Command } from "cmdk"
import { useEffect, useRef, useState } from "react"
import { useRouter } from "next/navigation"
import { useUserInterfaceStore } from "@/lib/stores/user-interface-store"
import { useSubscriptions } from "@/lib/queries/use-subscriptions"

export function CommandPalette() {
  const isOpen = useUserInterfaceStore((state) => state.isCommandPaletteOpen)
  const setOpen = useUserInterfaceStore((state) => state.setCommandPaletteOpen)
  const toggleSidebar = useUserInterfaceStore((state) => state.toggleSidebar)
  const setEntryListViewMode = useUserInterfaceStore(
    (state) => state.setEntryListViewMode
  )
  const setAddFeedDialogOpen = useUserInterfaceStore(
    (state) => state.setAddFeedDialogOpen
  )
  const router = useRouter()
  const { data: subscriptionsData } = useSubscriptions()
  const listReference = useRef<HTMLDivElement>(null)
  const [inputValue, setInputValue] = useState("")

  useEffect(() => {
    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
        event.preventDefault()
        setOpen(!isOpen)
      }
    }

    document.addEventListener("keydown", handleKeyDown)

    return () => document.removeEventListener("keydown", handleKeyDown)
  }, [isOpen, setOpen])

  useEffect(() => {
    if (!isOpen) return

    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") {
        setOpen(false)
        return
      }

      if (event.key === "ArrowDown" || event.key === "ArrowUp") {
        setTimeout(() => {
          const list = listReference.current
          if (!list) return
          const selected = list.querySelector('[aria-selected="true"]') as HTMLElement
          if (!selected) return
          const listRect = list.getBoundingClientRect()
          const selectedRect = selected.getBoundingClientRect()
          if (selectedRect.bottom > listRect.bottom) {
            list.scrollTop += selectedRect.bottom - listRect.bottom
          } else if (selectedRect.top < listRect.top) {
            list.scrollTop -= listRect.top - selectedRect.top
          }
        }, 0)
      }
    }

    document.addEventListener("keydown", handleKeyDown)
    return () => document.removeEventListener("keydown", handleKeyDown)
  }, [isOpen, setOpen])

  if (!isOpen) return null

  function handleInputKeyDown(event: React.KeyboardEvent) {
    if (event.key === "Backspace" && inputValue === "") {
      event.preventDefault()
      setOpen(false)
    }
  }

  function navigateAndClose(path: string) {
    router.push(path)
    setOpen(false)
  }

  function actionAndClose(action: () => void) {
    action()
    setOpen(false)
  }

  return (
    <div className="fixed inset-0 z-50 flex items-start justify-center pt-[20vh]">
      <div
        className="fixed inset-0 bg-background-primary/80"
        onClick={() => setOpen(false)}
      />
      <Command className="relative w-full max-w-lg border border-border bg-background-secondary">
        <Command.Input
          placeholder="type a command..."
          className="w-full border-b border-border bg-transparent px-4 py-3 text-text-primary outline-none placeholder:text-text-dim"
          autoFocus
          value={inputValue}
          onValueChange={setInputValue}
          onKeyDown={handleInputKeyDown}
        />
        <Command.List ref={listReference} className="max-h-80 overflow-auto p-2">
          <Command.Empty className="p-4 text-center text-text-dim">
            no results found
          </Command.Empty>

          <Command.Group
            heading="navigation"
            className="mb-2 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1 [&_[cmdk-group-heading]]:text-text-dim"
          >
            <Command.Item
              onSelect={() => navigateAndClose("/reader")}
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              go to all entries
            </Command.Item>
            <Command.Item
              onSelect={() => navigateAndClose("/reader/saved")}
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              go to saved
            </Command.Item>
            <Command.Item
              onSelect={() => navigateAndClose("/reader/settings")}
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              go to settings
            </Command.Item>
          </Command.Group>

          {subscriptionsData &&
            subscriptionsData.subscriptions.length > 0 && (
              <Command.Group
                heading="feeds"
                className="mb-2 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1 [&_[cmdk-group-heading]]:text-text-dim"
              >
                {subscriptionsData.subscriptions.map((subscription) => (
                  <Command.Item
                    key={subscription.subscriptionIdentifier}
                    value={`feed-${subscription.subscriptionIdentifier}-${subscription.customTitle ?? subscription.feedTitle}`}
                    onSelect={() =>
                      navigateAndClose(
                        `/reader?feed=${subscription.feedIdentifier}`
                      )
                    }
                    className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
                  >
                    {subscription.customTitle ?? subscription.feedTitle}
                  </Command.Item>
                ))}
              </Command.Group>
            )}

          <Command.Group
            heading="actions"
            className="mb-2 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1 [&_[cmdk-group-heading]]:text-text-dim"
          >
            <Command.Item
              onSelect={() =>
                actionAndClose(() => setAddFeedDialogOpen(true))
              }
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              add feed
            </Command.Item>
            <Command.Item
              onSelect={() => actionAndClose(toggleSidebar)}
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              toggle sidebar
            </Command.Item>
            <Command.Item
              onSelect={() =>
                actionAndClose(() => setEntryListViewMode("compact"))
              }
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              compact view
            </Command.Item>
            <Command.Item
              onSelect={() =>
                actionAndClose(() => setEntryListViewMode("comfortable"))
              }
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              comfortable view
            </Command.Item>
            <Command.Item
              onSelect={() =>
                actionAndClose(() => setEntryListViewMode("expanded"))
              }
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              expanded view
            </Command.Item>
            <Command.Item
              onSelect={() =>
                actionAndClose(() => {
                  const store = useUserInterfaceStore.getState()
                  store.resetSidebarLayout?.()
                  store.resetDetailLayout?.()
                })
              }
              className="cursor-pointer px-2 py-1 text-text-secondary aria-selected:bg-background-tertiary aria-selected:text-text-primary"
            >
              reset panel sizes
            </Command.Item>
          </Command.Group>
        </Command.List>
      </Command>
    </div>
  )
}
