import { useEffect, useRef, useState } from "react";
import { useCategories, useCreateCategory } from "../hooks/useCategories";
import { LucideIcon } from "../lib/iconData";
import { IconPicker } from "./IconPicker";

interface CategoryPickerProps {
	value: number;
	onChange: (categoryId: number) => void;
}

export function CategoryPicker({ value, onChange }: CategoryPickerProps) {
	const { data: categories = [] } = useCategories();
	const createCategory = useCreateCategory();
	const [inputValue, setInputValue] = useState("");
	const [isOpen, setIsOpen] = useState(false);
	const [highlightIndex, setHighlightIndex] = useState(-1);
	const [isCreating, setIsCreating] = useState(false);
	const [newCategoryIcon, setNewCategoryIcon] = useState("package");
	const containerRef = useRef<HTMLDivElement>(null);
	const inputRef = useRef<HTMLInputElement>(null);
	const listRef = useRef<HTMLUListElement>(null);

	// Sync display value when value prop changes
	const selectedCategory = categories.find((c) => c.id === value);

	const filtered = categories.filter((c) =>
		c.name.toLowerCase().includes(inputValue.toLowerCase()),
	);

	const showCreateOption =
		inputValue.trim() !== "" &&
		!categories.some(
			(c) => c.name.toLowerCase() === inputValue.trim().toLowerCase(),
		);

	const totalOptions = filtered.length + (showCreateOption ? 1 : 0);

	useEffect(() => {
		function handleClickOutside(e: MouseEvent) {
			const target = e.target as Node;
			if (
				containerRef.current &&
				!containerRef.current.contains(target) &&
				!(target instanceof Element && target.closest("[data-icon-picker]"))
			) {
				setIsOpen(false);
				setIsCreating(false);
				setNewCategoryIcon("package");
				// Reset input to selected category name
				if (selectedCategory) {
					setInputValue("");
				}
			}
		}
		document.addEventListener("mousedown", handleClickOutside);
		return () => document.removeEventListener("mousedown", handleClickOutside);
	}, [selectedCategory]);

	function handleSelect(categoryId: number) {
		onChange(categoryId);
		setInputValue("");
		setIsOpen(false);
		setHighlightIndex(-1);
	}

	function handleStartCreate() {
		setIsCreating(true);
	}

	async function handleConfirmCreate() {
		const name = inputValue.trim();
		if (!name) return;
		createCategory.mutate(
			{ name, icon: newCategoryIcon },
			{
				onSuccess: (newCat) => {
					setIsCreating(false);
					setNewCategoryIcon("package");
					handleSelect(newCat.id);
				},
			},
		);
	}

	function handleKeyDown(e: React.KeyboardEvent) {
		if (!isOpen) {
			if (e.key === "ArrowDown" || e.key === "Enter") {
				setIsOpen(true);
				e.preventDefault();
			}
			return;
		}

		switch (e.key) {
			case "ArrowDown":
				e.preventDefault();
				setHighlightIndex((i) => Math.min(i + 1, totalOptions - 1));
				break;
			case "ArrowUp":
				e.preventDefault();
				setHighlightIndex((i) => Math.max(i - 1, 0));
				break;
			case "Enter":
				e.preventDefault();
				if (isCreating) {
					handleConfirmCreate();
				} else if (highlightIndex >= 0 && highlightIndex < filtered.length) {
					handleSelect(filtered[highlightIndex].id);
				} else if (showCreateOption && highlightIndex === filtered.length) {
					handleStartCreate();
				}
				break;
			case "Escape":
				if (isCreating) {
					setIsCreating(false);
					setNewCategoryIcon("package");
				} else {
					setIsOpen(false);
					setHighlightIndex(-1);
					setInputValue("");
				}
				break;
		}
	}

	// Scroll highlighted option into view
	useEffect(() => {
		if (highlightIndex >= 0 && listRef.current) {
			const option = listRef.current.children[highlightIndex] as HTMLElement;
			option?.scrollIntoView({ block: "nearest" });
		}
	}, [highlightIndex]);

	return (
		<div ref={containerRef} className="relative">
			<div className="relative">
				{!isOpen && selectedCategory && (
					<div className="absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none">
						<LucideIcon
							name={selectedCategory.icon}
							size={16}
							className="text-gray-500"
						/>
					</div>
				)}
				<input
					ref={inputRef}
					type="text"
					role="combobox"
					aria-expanded={isOpen}
					aria-autocomplete="list"
					aria-controls="category-listbox"
					aria-activedescendant={
						highlightIndex >= 0
							? `category-option-${highlightIndex}`
							: undefined
					}
					value={
						isOpen ? inputValue : selectedCategory ? selectedCategory.name : ""
					}
					placeholder="Search or create category..."
					onChange={(e) => {
						setInputValue(e.target.value);
						setIsOpen(true);
						setHighlightIndex(-1);
					}}
					onFocus={() => {
						setIsOpen(true);
						setInputValue("");
					}}
					onKeyDown={handleKeyDown}
					className={`w-full py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent ${
						!isOpen && selectedCategory ? "pl-8 pr-3" : "px-3"
					}`}
				/>
			</div>
			{isOpen && (
				<ul
					ref={listRef}
					id="category-listbox"
					className="absolute z-20 mt-1 w-full max-h-48 overflow-auto bg-white border border-gray-200 rounded-lg shadow-lg"
				>
					{filtered.map((cat, i) => (
						<li
							key={cat.id}
							id={`category-option-${i}`}
							aria-selected={cat.id === value}
							className={`px-3 py-2 text-sm cursor-pointer flex items-center gap-1.5 ${
								i === highlightIndex
									? "bg-gray-100 text-gray-900"
									: "hover:bg-gray-50"
							} ${cat.id === value ? "font-medium" : ""}`}
							onClick={() => handleSelect(cat.id)}
							onMouseEnter={() => setHighlightIndex(i)}
						>
							<LucideIcon
								name={cat.icon}
								size={16}
								className="text-gray-500 shrink-0"
							/>
							{cat.name}
						</li>
					))}
					{showCreateOption && !isCreating && (
						<li
							id={`category-option-${filtered.length}`}
							aria-selected={false}
							className={`px-3 py-2 text-sm cursor-pointer border-t border-gray-100 ${
								highlightIndex === filtered.length
									? "bg-gray-100 text-gray-900"
									: "hover:bg-gray-50 text-gray-600"
							}`}
							onClick={handleStartCreate}
							onMouseEnter={() => setHighlightIndex(filtered.length)}
						>
							+ Create "{inputValue.trim()}"
						</li>
					)}
					{isCreating && (
						<li className="px-3 py-2 border-t border-gray-100">
							<div className="flex items-center gap-2">
								<IconPicker
									value={newCategoryIcon}
									onChange={setNewCategoryIcon}
									size="sm"
								/>
								<span className="text-sm text-gray-700 truncate flex-1">
									{inputValue.trim()}
								</span>
								<button
									type="button"
									onClick={handleConfirmCreate}
									disabled={createCategory.isPending}
									className="text-xs font-medium text-gray-600 hover:text-gray-800 disabled:opacity-50"
								>
									{createCategory.isPending ? "..." : "Create"}
								</button>
							</div>
						</li>
					)}
					{filtered.length === 0 && !showCreateOption && (
						<li className="px-3 py-2 text-sm text-gray-400">
							No categories found
						</li>
					)}
				</ul>
			)}
		</div>
	);
}
