import { Database, Search, Trash2 } from "lucide-react";
import {
	useCallback,
	useEffect,
	useMemo,
	useOptimistic,
	useState,
} from "react";
import type { CachedSourceInfo } from "../adapters/bestiary-cache.js";
import * as bestiaryCache from "../adapters/bestiary-cache.js";
import { useBestiaryContext } from "../contexts/bestiary-context.js";
import { Button } from "./ui/button.js";
import { Input } from "./ui/input.js";

export function SourceManager() {
	const { refreshCache } = useBestiaryContext();
	const [sources, setSources] = useState<CachedSourceInfo[]>([]);
	const [filter, setFilter] = useState("");
	const [optimisticSources, applyOptimistic] = useOptimistic(
		sources,
		(
			state,
			action: { type: "remove"; sourceCode: string } | { type: "clear" },
		) =>
			action.type === "clear"
				? []
				: state.filter((s) => s.sourceCode !== action.sourceCode),
	);

	const loadSources = useCallback(async () => {
		const cached = await bestiaryCache.getCachedSources();
		setSources(cached);
	}, []);

	useEffect(() => {
		void loadSources();
	}, [loadSources]);

	const handleClearSource = async (sourceCode: string) => {
		applyOptimistic({ type: "remove", sourceCode });
		await bestiaryCache.clearSource(sourceCode);
		await loadSources();
		void refreshCache();
	};

	const handleClearAll = async () => {
		applyOptimistic({ type: "clear" });
		await bestiaryCache.clearAll();
		await loadSources();
		void refreshCache();
	};

	const filteredSources = useMemo(() => {
		const term = filter.toLowerCase();
		return term
			? optimisticSources.filter((s) =>
					s.displayName.toLowerCase().includes(term),
				)
			: optimisticSources;
	}, [optimisticSources, filter]);

	if (optimisticSources.length === 0) {
		return (
			<div className="flex flex-col items-center gap-2 py-8 text-center">
				<Database className="h-8 w-8 text-muted-foreground" />
				<p className="text-muted-foreground text-sm">No cached sources</p>
			</div>
		);
	}

	return (
		<div className="flex flex-col gap-3">
			<div className="flex items-center justify-between">
				<span className="font-semibold text-foreground text-sm">
					Cached Sources
				</span>
				<Button
					variant="outline"
					className="hover:border-hover-destructive hover:text-hover-destructive"
					onClick={handleClearAll}
				>
					<Trash2 className="mr-1 h-3 w-3" />
					Clear All
				</Button>
			</div>
			<div className="relative">
				<Search className="pointer-events-none absolute top-1/2 left-3 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
				<Input
					placeholder="Filter sources…"
					value={filter}
					onChange={(e) => setFilter(e.target.value)}
					className="pl-8"
				/>
			</div>
			<ul className="flex flex-col gap-1">
				{filteredSources.map((source) => (
					<li
						key={source.sourceCode}
						className="flex items-center justify-between rounded-md border border-border px-3 py-2"
					>
						<div>
							<span className="text-foreground text-sm">
								{source.displayName}
							</span>
							<span className="ml-2 text-muted-foreground text-xs">
								{source.creatureCount} creatures
							</span>
						</div>
						<button
							type="button"
							onClick={() => handleClearSource(source.sourceCode)}
							className="rounded-md p-1 text-muted-foreground transition-colors hover:bg-hover-destructive-bg hover:text-hover-destructive"
							aria-label={`Remove ${source.displayName}`}
						>
							<Trash2 className="h-3.5 w-3.5" />
						</button>
					</li>
				))}
			</ul>
		</div>
	);
}
