import { createFileRoute, Link } from "@tanstack/react-router";
import { ArrowLeft, LayoutGrid, LayoutList, X } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import { z } from "zod";
import { GearImage } from "../../components/GearImage";
import { GlobalItemCard } from "../../components/GlobalItemCard";
import { useFormatters } from "../../hooks/useFormatters";
import { useGlobalItems } from "../../hooks/useGlobalItems";
import { useTags } from "../../hooks/useTags";

export const Route = createFileRoute("/global-items/")({
	component: GlobalItemsCatalog,
	validateSearch: z.object({
		q: z.string().optional().catch(undefined),
	}),
});

type ViewMode = "grid" | "list";

function GlobalItemsCatalog() {
	const { q } = Route.useSearch();

	const [searchInput, setSearchInput] = useState(q ?? "");
	const [debouncedQuery, setDebouncedQuery] = useState(q ?? "");
	const [selectedTags, setSelectedTags] = useState<string[]>([]);
	const [viewMode, setViewMode] = useState<ViewMode>("grid");

	// Range filters (client-side)
	const [weightMin, setWeightMin] = useState(0);
	const [weightMax, setWeightMax] = useState(5000);
	const [priceMin, setPriceMin] = useState(0);
	const [priceMax, setPriceMax] = useState(100000);

	// Popover states
	const [tagFilterOpen, setTagFilterOpen] = useState(false);
	const [weightFilterOpen, setWeightFilterOpen] = useState(false);
	const [priceFilterOpen, setPriceFilterOpen] = useState(false);

	const tagRef = useRef<HTMLDivElement>(null);
	const weightRef = useRef<HTMLDivElement>(null);
	const priceRef = useRef<HTMLDivElement>(null);

	const { weight, price } = useFormatters();
	const { data: tags } = useTags();
	const { data: rawItems, isLoading } = useGlobalItems(
		debouncedQuery || undefined,
		selectedTags.length > 0 ? selectedTags : undefined,
	);

	// Client-side range filtering
	const hasRangeFilters =
		weightMin > 0 || weightMax < 5000 || priceMin > 0 || priceMax < 100000;

	const items = useMemo(() => {
		if (!rawItems || !hasRangeFilters) return rawItems;
		return rawItems.filter((item) => {
			if (item.weightGrams != null) {
				if (item.weightGrams < weightMin || item.weightGrams > weightMax)
					return false;
			}
			if (item.priceCents != null) {
				if (item.priceCents < priceMin || item.priceCents > priceMax)
					return false;
			}
			return true;
		});
	}, [rawItems, weightMin, weightMax, priceMin, priceMax, hasRangeFilters]);

	// Debounce search input
	useEffect(() => {
		const timer = setTimeout(() => {
			setDebouncedQuery(searchInput);
		}, 300);
		return () => clearTimeout(timer);
	}, [searchInput]);

	// Close popovers on outside click
	useEffect(() => {
		function handleClick(e: MouseEvent) {
			if (tagRef.current && !tagRef.current.contains(e.target as Node)) {
				setTagFilterOpen(false);
			}
			if (weightRef.current && !weightRef.current.contains(e.target as Node)) {
				setWeightFilterOpen(false);
			}
			if (priceRef.current && !priceRef.current.contains(e.target as Node)) {
				setPriceFilterOpen(false);
			}
		}
		document.addEventListener("mousedown", handleClick);
		return () => document.removeEventListener("mousedown", handleClick);
	}, []);

	function toggleTag(tagName: string) {
		setSelectedTags((prev) =>
			prev.includes(tagName)
				? prev.filter((t) => t !== tagName)
				: [...prev, tagName],
		);
	}

	function removeTag(tagName: string) {
		setSelectedTags((prev) => prev.filter((t) => t !== tagName));
	}

	function clearAllFilters() {
		setSelectedTags([]);
		setWeightMin(0);
		setWeightMax(5000);
		setPriceMin(0);
		setPriceMax(100000);
	}

	const hasAnyFilter = selectedTags.length > 0 || hasRangeFilters;

	const showRow2 = (tags && tags.length > 0) || hasAnyFilter;

	return (
		<div className="min-h-screen bg-gray-50">
			{/* Sticky toolbar */}
			<div className="sticky top-14 z-[5] bg-white border-b border-gray-100">
				{/* Row 1: Back link, search, view toggle */}
				<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2">
					<div className="flex items-center gap-3">
						{/* Back link */}
						<Link
							to="/"
							className="inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-gray-700 transition-colors shrink-0"
						>
							<ArrowLeft className="w-3.5 h-3.5" />
							<span className="hidden sm:inline">Discover</span>
						</Link>

						{/* Search input */}
						<div className="relative flex-1 max-w-lg mx-auto">
							<input
								type="text"
								value={searchInput}
								onChange={(e) => setSearchInput(e.target.value)}
								placeholder="Search the catalog..."
								className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm text-gray-900 placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent transition-colors"
							/>
							{searchInput && (
								<button
									type="button"
									onClick={() => setSearchInput("")}
									className="absolute right-2.5 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors"
								>
									<X className="w-3.5 h-3.5" />
								</button>
							)}
						</div>

						{/* View toggle */}
						<div className="flex items-center gap-1 bg-gray-100 rounded-lg p-0.5 shrink-0">
							<button
								type="button"
								onClick={() => setViewMode("list")}
								className={`p-1.5 rounded-md transition-colors ${
									viewMode === "list"
										? "bg-white text-gray-900 shadow-sm"
										: "text-gray-400 hover:text-gray-600"
								}`}
								title="List view"
							>
								<LayoutList className="w-4 h-4" />
							</button>
							<button
								type="button"
								onClick={() => setViewMode("grid")}
								className={`p-1.5 rounded-md transition-colors ${
									viewMode === "grid"
										? "bg-white text-gray-900 shadow-sm"
										: "text-gray-400 hover:text-gray-600"
								}`}
								title="Grid view"
							>
								<LayoutGrid className="w-4 h-4" />
							</button>
						</div>
					</div>
				</div>

				{/* Row 2: Filter pills + active pills */}
				{showRow2 && (
					<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-1.5">
						<div className="flex flex-wrap items-center gap-1.5">
							{/* Tags filter pill */}
							{tags && tags.length > 0 && (
								<div className="relative" ref={tagRef}>
									<button
										type="button"
										onClick={() => {
											setTagFilterOpen((prev) => !prev);
											setWeightFilterOpen(false);
											setPriceFilterOpen(false);
										}}
										className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium border transition-colors ${
											selectedTags.length > 0
												? "bg-blue-50 text-blue-700 border-blue-200"
												: "bg-white text-gray-600 border-gray-200 hover:border-gray-300"
										}`}
									>
										Tags
										{selectedTags.length > 0 && (
											<span className="ml-0.5 inline-flex items-center justify-center w-4 h-4 rounded-full bg-blue-500 text-white text-[10px] font-bold">
												{selectedTags.length}
											</span>
										)}
									</button>

									{tagFilterOpen && (
										<div className="absolute left-0 top-full mt-1 z-20 bg-white border border-gray-200 rounded-lg shadow-lg min-w-[160px] max-h-48 overflow-y-auto">
											<div className="p-1.5 space-y-0.5">
												{tags.map((tag) => {
													const isActive = selectedTags.includes(tag.name);
													return (
														<button
															key={tag.id}
															type="button"
															onClick={() => toggleTag(tag.name)}
															className={`w-full text-left px-2.5 py-1.5 rounded-md text-sm transition-colors ${
																isActive
																	? "bg-blue-50 text-blue-700 font-medium"
																	: "text-gray-600 hover:bg-gray-50"
															}`}
														>
															{tag.name}
														</button>
													);
												})}
											</div>
										</div>
									)}
								</div>
							)}

							{/* Weight filter pill */}
							<div className="relative" ref={weightRef}>
								<button
									type="button"
									onClick={() => {
										setWeightFilterOpen((prev) => !prev);
										setTagFilterOpen(false);
										setPriceFilterOpen(false);
									}}
									className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium border transition-colors ${
										weightMin > 0 || weightMax < 5000
											? "bg-blue-50 text-blue-700 border-blue-200"
											: "bg-white text-gray-600 border-gray-200 hover:border-gray-300"
									}`}
								>
									Weight
									{(weightMin > 0 || weightMax < 5000) && (
										<span className="ml-0.5 text-blue-500">
											{weightMin > 0 && weightMax < 5000
												? `${weight(weightMin)}–${weight(weightMax)}`
												: weightMin > 0
													? `≥${weight(weightMin)}`
													: `≤${weight(weightMax)}`}
										</span>
									)}
								</button>

								{weightFilterOpen && (
									<div className="absolute left-0 top-full mt-1 z-20 bg-white border border-gray-200 rounded-lg shadow-lg p-4 w-56">
										<h3 className="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-3">
											Weight range
										</h3>
										<div className="space-y-2">
											<div>
												<label className="text-xs text-gray-500 mb-1 block">
													Min: {weight(weightMin)}
												</label>
												<input
													type="range"
													min={0}
													max={5000}
													step={50}
													value={weightMin}
													onChange={(e) =>
														setWeightMin(
															Math.min(Number(e.target.value), weightMax - 50),
														)
													}
													className="w-full h-1.5 bg-gray-200 rounded-full appearance-none accent-blue-500"
												/>
											</div>
											<div>
												<label className="text-xs text-gray-500 mb-1 block">
													Max: {weight(weightMax)}
												</label>
												<input
													type="range"
													min={0}
													max={5000}
													step={50}
													value={weightMax}
													onChange={(e) =>
														setWeightMax(
															Math.max(Number(e.target.value), weightMin + 50),
														)
													}
													className="w-full h-1.5 bg-gray-200 rounded-full appearance-none accent-blue-500"
												/>
											</div>
											<div className="flex justify-between text-xs text-gray-400 pt-1">
												<span>{weight(weightMin)}</span>
												<span>{weight(weightMax)}</span>
											</div>
										</div>
										{(weightMin > 0 || weightMax < 5000) && (
											<button
												type="button"
												onClick={() => {
													setWeightMin(0);
													setWeightMax(5000);
												}}
												className="mt-2 text-xs text-gray-400 hover:text-gray-600"
											>
												Reset
											</button>
										)}
									</div>
								)}
							</div>

							{/* Price filter pill */}
							<div className="relative" ref={priceRef}>
								<button
									type="button"
									onClick={() => {
										setPriceFilterOpen((prev) => !prev);
										setTagFilterOpen(false);
										setWeightFilterOpen(false);
									}}
									className={`inline-flex items-center gap-1 px-2.5 py-1 rounded-full text-xs font-medium border transition-colors ${
										priceMin > 0 || priceMax < 100000
											? "bg-green-50 text-green-700 border-green-200"
											: "bg-white text-gray-600 border-gray-200 hover:border-gray-300"
									}`}
								>
									Price
									{(priceMin > 0 || priceMax < 100000) && (
										<span className="ml-0.5 text-green-600">
											{priceMin > 0 && priceMax < 100000
												? `${price(priceMin)}–${price(priceMax)}`
												: priceMin > 0
													? `≥${price(priceMin)}`
													: `≤${price(priceMax)}`}
										</span>
									)}
								</button>

								{priceFilterOpen && (
									<div className="absolute left-0 top-full mt-1 z-20 bg-white border border-gray-200 rounded-lg shadow-lg p-4 w-56">
										<h3 className="text-xs font-semibold text-gray-400 uppercase tracking-wide mb-3">
											Price range
										</h3>
										<div className="space-y-2">
											<div>
												<label className="text-xs text-gray-500 mb-1 block">
													Min: {price(priceMin)}
												</label>
												<input
													type="range"
													min={0}
													max={100000}
													step={500}
													value={priceMin}
													onChange={(e) =>
														setPriceMin(
															Math.min(Number(e.target.value), priceMax - 500),
														)
													}
													className="w-full h-1.5 bg-gray-200 rounded-full appearance-none accent-green-500"
												/>
											</div>
											<div>
												<label className="text-xs text-gray-500 mb-1 block">
													Max: {price(priceMax)}
												</label>
												<input
													type="range"
													min={0}
													max={100000}
													step={500}
													value={priceMax}
													onChange={(e) =>
														setPriceMax(
															Math.max(Number(e.target.value), priceMin + 500),
														)
													}
													className="w-full h-1.5 bg-gray-200 rounded-full appearance-none accent-green-500"
												/>
											</div>
											<div className="flex justify-between text-xs text-gray-400 pt-1">
												<span>{price(priceMin)}</span>
												<span>{price(priceMax)}</span>
											</div>
										</div>
										{(priceMin > 0 || priceMax < 100000) && (
											<button
												type="button"
												onClick={() => {
													setPriceMin(0);
													setPriceMax(100000);
												}}
												className="mt-2 text-xs text-gray-400 hover:text-gray-600"
											>
												Reset
											</button>
										)}
									</div>
								)}
							</div>

							{/* Active filter pills */}
							{selectedTags.map((tag) => (
								<button
									key={tag}
									type="button"
									onClick={() => removeTag(tag)}
									className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-700 hover:bg-blue-200 transition-colors"
								>
									{tag}
									<X className="w-3 h-3" />
								</button>
							))}

							{weightMin > 0 && (
								<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-500">
									≥{weight(weightMin)}
									<button type="button" onClick={() => setWeightMin(0)}>
										<X className="w-3 h-3" />
									</button>
								</span>
							)}
							{weightMax < 5000 && (
								<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-500">
									≤{weight(weightMax)}
									<button type="button" onClick={() => setWeightMax(5000)}>
										<X className="w-3 h-3" />
									</button>
								</span>
							)}
							{priceMin > 0 && (
								<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-600">
									≥{price(priceMin)}
									<button type="button" onClick={() => setPriceMin(0)}>
										<X className="w-3 h-3" />
									</button>
								</span>
							)}
							{priceMax < 100000 && (
								<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-600">
									≤{price(priceMax)}
									<button type="button" onClick={() => setPriceMax(100000)}>
										<X className="w-3 h-3" />
									</button>
								</span>
							)}

							{hasAnyFilter && (
								<button
									type="button"
									onClick={clearAllFilters}
									className="text-xs text-gray-400 hover:text-gray-600 px-1 transition-colors"
								>
									Clear all
								</button>
							)}
						</div>
					</div>
				)}
			</div>

			{/* Results */}
			<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
				{isLoading ? (
					viewMode === "grid" ? (
						<SkeletonGrid />
					) : (
						<SkeletonList />
					)
				) : items && items.length > 0 ? (
					viewMode === "grid" ? (
						<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
							{items.map((item) => (
								<GlobalItemCard key={item.id} {...item} />
							))}
						</div>
					) : (
						<div className="space-y-2">
							{items.map((item) => (
								<GlobalItemListRow
									key={item.id}
									item={item}
									weight={weight}
									price={price}
								/>
							))}
						</div>
					)
				) : (
					<EmptyState
						hasQuery={
							!!debouncedQuery || selectedTags.length > 0 || hasRangeFilters
						}
					/>
				)}
			</div>
		</div>
	);
}

// ── List Row ───────────────────────────────────────────────────────────

interface ListRowProps {
	item: {
		id: number;
		brand: string;
		model: string;
		category: string | null;
		weightGrams: number | null;
		priceCents: number | null;
		imageUrl: string | null;
	};
	weight: (g: number | null) => string;
	price: (cents: number | null) => string;
}

function GlobalItemListRow({ item, weight, price }: ListRowProps) {
	return (
		<Link
			to="/global-items/$globalItemId"
			params={{ globalItemId: String(item.id) }}
			className="bg-white rounded-xl border border-gray-100 flex items-center gap-4 px-4 py-3 hover:border-gray-200 hover:shadow-sm transition-all block"
		>
			{/* Thumbnail */}
			<div
				className="w-12 h-12 rounded-lg shrink-0 overflow-hidden"
				style={{
					backgroundColor: item.imageUrl
						? (item.dominantColor as string) || "#f3f4f6"
						: undefined,
				}}
			>
				{item.imageUrl ? (
					<GearImage src={item.imageUrl} alt={`${item.brand} ${item.model}`} />
				) : (
					<div className="w-full h-full bg-gray-50 flex items-center justify-center">
						<svg
							className="w-5 h-5 text-gray-300"
							fill="none"
							stroke="currentColor"
							viewBox="0 0 24 24"
						>
							<path
								strokeLinecap="round"
								strokeLinejoin="round"
								strokeWidth={1.5}
								d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"
							/>
						</svg>
					</div>
				)}
			</div>

			{/* Info */}
			<div className="flex-1 min-w-0">
				<p className="text-sm font-semibold text-gray-900 truncate">
					{item.brand} {item.model}
				</p>
				<div className="flex flex-wrap gap-1.5 mt-1">
					{item.weightGrams != null && (
						<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-blue-50 text-blue-400">
							{weight(item.weightGrams)}
						</span>
					)}
					{item.priceCents != null && (
						<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-green-50 text-green-500">
							{price(item.priceCents)}
						</span>
					)}
					{item.category && (
						<span className="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-50 text-gray-600">
							{item.category}
						</span>
					)}
				</div>
			</div>
		</Link>
	);
}

// ── Skeletons ──────────────────────────────────────────────────────────

function SkeletonGrid() {
	return (
		<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
			{[1, 2, 3, 4, 5, 6].map((id) => (
				<div
					key={id}
					className="bg-white rounded-xl border border-gray-100 overflow-hidden animate-pulse"
				>
					<div className="aspect-[4/3] bg-gray-100" />
					<div className="p-4 space-y-2">
						<div className="h-3 bg-gray-100 rounded w-16" />
						<div className="h-4 bg-gray-100 rounded w-32" />
						<div className="flex gap-1.5">
							<div className="h-5 bg-gray-100 rounded-full w-14" />
							<div className="h-5 bg-gray-100 rounded-full w-14" />
						</div>
					</div>
				</div>
			))}
		</div>
	);
}

function SkeletonList() {
	return (
		<div className="space-y-2">
			{[1, 2, 3, 4, 5, 6].map((id) => (
				<div
					key={id}
					className="bg-white rounded-xl border border-gray-100 flex items-center gap-4 px-4 py-3 animate-pulse"
				>
					<div className="w-12 h-12 rounded-lg bg-gray-100 shrink-0" />
					<div className="flex-1 space-y-2">
						<div className="h-4 bg-gray-100 rounded w-48" />
						<div className="flex gap-1.5">
							<div className="h-5 bg-gray-100 rounded-full w-14" />
							<div className="h-5 bg-gray-100 rounded-full w-14" />
						</div>
					</div>
				</div>
			))}
		</div>
	);
}

// ── Empty State ────────────────────────────────────────────────────────

function EmptyState({ hasQuery }: { hasQuery: boolean }) {
	return (
		<div className="flex flex-col items-center justify-center py-20 px-4">
			<svg
				className="w-12 h-12 text-gray-300 mb-4"
				fill="none"
				stroke="currentColor"
				viewBox="0 0 24 24"
			>
				<path
					strokeLinecap="round"
					strokeLinejoin="round"
					strokeWidth={1.5}
					d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"
				/>
			</svg>
			<p className="text-sm text-gray-500 text-center">
				{hasQuery
					? "No items found matching your search"
					: "No items in the global catalog yet"}
			</p>
		</div>
	);
}
