"use client"

import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"
import { useMediaQuery } from "@/hooks/use-media-query"
import { formatIconName, fuzzySearch } from "@/lib/utils"
import { useRouter } from "next/navigation"
import { useCallback, useEffect, useState } from "react"

interface CommandMenuProps {
	icons: {
		name: string
		data: {
			categories: string[]
			aliases: string[]
			[key: string]: unknown
		}
	}[]
	triggerButtonId?: string
	open?: boolean
	onOpenChange?: (open: boolean) => void
}

export function CommandMenu({ icons, open: externalOpen, onOpenChange: externalOnOpenChange }: CommandMenuProps) {
	const router = useRouter()
	const [internalOpen, setInternalOpen] = useState(false)
	const [query, setQuery] = useState("")
	const isDesktop = useMediaQuery("(min-width: 768px)")

	// Use either external or internal state for controlling open state
	const isOpen = externalOpen !== undefined ? externalOpen : internalOpen

	// Wrap setIsOpen in useCallback to fix dependency issue
	const setIsOpen = useCallback(
		(value: boolean) => {
			if (externalOnOpenChange) {
				externalOnOpenChange(value)
			} else {
				setInternalOpen(value)
			}
		},
		[externalOnOpenChange],
	)

	const filteredIcons = getFilteredIcons(icons, query)

	useEffect(() => {
		const handleKeyDown = (e: KeyboardEvent) => {
			if (
				(e.key === "k" && (e.metaKey || e.ctrlKey)) ||
				(e.key === "/" && document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA")
			) {
				e.preventDefault()
				setIsOpen(!isOpen)
			}
		}

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

	function getFilteredIcons(iconList: CommandMenuProps["icons"], query: string) {
		if (!query) {
			// Return a limited number of icons when no query is provided
			return iconList.slice(0, 8)
		}

		// Calculate scores for each icon
		const scoredIcons = iconList.map((icon) => {
			// Calculate scores for different fields
			const nameScore = fuzzySearch(icon.name, query) * 2.0 // Give more weight to name matches

			// Get max score from aliases
			const aliasScore =
				icon.data.aliases && icon.data.aliases.length > 0
					? Math.max(...icon.data.aliases.map((alias) => fuzzySearch(alias, query))) * 1.8 // Increased weight for aliases
					: 0

			// Get max score from categories
			const categoryScore =
				icon.data.categories && icon.data.categories.length > 0
					? Math.max(...icon.data.categories.map((category) => fuzzySearch(category, query)))
					: 0

			// Use the highest score
			const score = Math.max(nameScore, aliasScore, categoryScore)

			return { icon, score, matchedField: score === nameScore ? "name" : score === aliasScore ? "alias" : "category" }
		})

		// Filter icons with a minimum score and sort by highest score
		return scoredIcons
			.filter((item) => item.score > 0.3) // Higher threshold for more accurate results
			.sort((a, b) => b.score - a.score)
			.slice(0, 20) // Limit the number of results
			.map((item) => item.icon)
	}

	const handleSelect = (name: string) => {
		setIsOpen(false)
		router.push(`/icons/${name}`)
	}

	return (
		<CommandDialog open={isOpen} onOpenChange={setIsOpen}>
			<CommandInput placeholder="Search for icons by name, category, or purpose..." value={query} onValueChange={setQuery} />
			<CommandList>
				<CommandEmpty>No matching icons found. Try a different search term or browse all icons.</CommandEmpty>
				<CommandGroup heading="Icons">
					{filteredIcons.map(({ name, data }) => {
						// Find matched alias for display if available
						const matchedAlias =
							query && data.aliases && data.aliases.length > 0
								? data.aliases.find((alias) => alias.toLowerCase().includes(query.toLowerCase()))
								: null
						const formatedIconName = formatIconName(name)

						return (
							<CommandItem key={name} value={name} onSelect={() => handleSelect(name)} className="flex items-center gap-2 cursor-pointer">
								<div className="flex-shrink-0 h-5 w-5 relative">
									<div className="h-5 w-5 bg-rose-100 dark:bg-rose-900/30 rounded-md flex items-center justify-center">
										<span className="text-[10px] font-medium text-rose-800 dark:text-rose-300">{name.substring(0, 2).toUpperCase()}</span>
									</div>
								</div>
								<span className="flex-grow capitalize">{formatedIconName}</span>
								{matchedAlias && <span className="text-xs text-primary-500 truncate max-w-[100px]">alias: {matchedAlias}</span>}
								{!matchedAlias && data.categories && data.categories.length > 0 && (
									<span className="text-xs text-muted-foreground truncate max-w-[100px]">
										{data.categories[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())}
									</span>
								)}
							</CommandItem>
						)
					})}
				</CommandGroup>
			</CommandList>
		</CommandDialog>
	)
}