import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useState } from "react";
import { toast } from "sonner";
import { useCategories } from "../hooks/useCategories";
import { useGlobalItem } from "../hooks/useGlobalItems";
import { useCreateThread, useThreads } from "../hooks/useThreads";
import { apiPost } from "../lib/api";
import { useUIStore } from "../stores/uiStore";

export function AddToThreadModal() {
	const { open, globalItemId, globalItemName } = useUIStore(
		(s) => s.addToThreadModal,
	);
	const closeAddToThread = useUIStore((s) => s.closeAddToThread);
	const catalogSessionThreadId = useUIStore((s) => s.catalogSessionThreadId);
	const setCatalogSessionThreadId = useUIStore(
		(s) => s.setCatalogSessionThreadId,
	);

	const { data: threads } = useThreads();
	const { data: categories } = useCategories();
	const { data: globalItem } = useGlobalItem(globalItemId);
	const createThread = useCreateThread();
	const queryClient = useQueryClient();

	const [mode, setMode] = useState<"pick" | "create">("pick");
	const [selectedThreadId, setSelectedThreadId] = useState<number | null>(null);
	const [newThreadName, setNewThreadName] = useState("");
	const [newThreadCategoryId, setNewThreadCategoryId] = useState<number | null>(
		null,
	);
	const [isSubmitting, setIsSubmitting] = useState(false);
	const [error, setError] = useState<string | null>(null);

	const activeThreads = threads?.filter((t) => t.status === "active") ?? [];

	// Pre-select category for new thread creation
	useEffect(() => {
		if (categories && categories.length > 0 && newThreadCategoryId === null) {
			setNewThreadCategoryId(categories[0].id);
		}
	}, [categories, newThreadCategoryId]);

	// Initialize selection when modal opens
	useEffect(() => {
		if (open) {
			if (activeThreads.length === 0) {
				setMode("create");
			} else {
				setMode("pick");
				if (
					catalogSessionThreadId &&
					activeThreads.some((t) => t.id === catalogSessionThreadId)
				) {
					setSelectedThreadId(catalogSessionThreadId);
				} else if (activeThreads.length > 0) {
					setSelectedThreadId(activeThreads[0].id);
				}
			}
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [
		open,
		activeThreads.length,
		activeThreads.some,
		activeThreads[0]?.id,
		catalogSessionThreadId,
	]);

	// Reset form state when modal closes
	useEffect(() => {
		if (!open) {
			setMode("pick");
			setSelectedThreadId(null);
			setNewThreadName("");
			setNewThreadCategoryId(categories?.[0]?.id ?? null);
			setError(null);
			setIsSubmitting(false);
		}
	}, [open, categories]);

	if (!open || !globalItemId) return null;

	function handleClose() {
		closeAddToThread();
	}

	function handleSelectChange(value: string) {
		if (value === "new") {
			setMode("create");
		} else {
			setSelectedThreadId(Number(value));
		}
	}

	async function handleAddToExistingThread() {
		if (!selectedThreadId || !globalItemId) return;
		setIsSubmitting(true);
		setError(null);
		try {
			const thread = activeThreads.find((t) => t.id === selectedThreadId);
			await apiPost(`/api/threads/${selectedThreadId}/candidates`, {
				name: globalItemName ?? "Unknown Item",
				globalItemId,
				categoryId: thread?.categoryId ?? categories?.[0]?.id ?? 1,
				weightGrams: globalItem?.weightGrams ?? undefined,
				priceCents: globalItem?.priceCents ?? undefined,
			});
			queryClient.invalidateQueries({ queryKey: ["threads"] });
			queryClient.invalidateQueries({
				queryKey: ["threads", selectedThreadId],
			});
			setCatalogSessionThreadId(selectedThreadId);
			toast.success(`Added to "${thread?.name ?? "thread"}"`);
			closeAddToThread();
		} catch (err) {
			setError(err instanceof Error ? err.message : "Failed to add candidate");
		} finally {
			setIsSubmitting(false);
		}
	}

	async function handleCreateThreadAndAdd() {
		const trimmedName = newThreadName.trim();
		if (!trimmedName || !newThreadCategoryId || !globalItemId) return;
		setIsSubmitting(true);
		setError(null);
		try {
			const thread = await createThread.mutateAsync({
				name: trimmedName,
				categoryId: newThreadCategoryId,
			});
			await apiPost(`/api/threads/${thread.id}/candidates`, {
				name: globalItemName ?? "Unknown Item",
				globalItemId,
				categoryId: newThreadCategoryId,
				weightGrams: globalItem?.weightGrams ?? undefined,
				priceCents: globalItem?.priceCents ?? undefined,
			});
			queryClient.invalidateQueries({ queryKey: ["threads"] });
			setCatalogSessionThreadId(thread.id);
			toast.success(`Created "${trimmedName}" with first candidate`);
			closeAddToThread();
		} catch (err) {
			setError(err instanceof Error ? err.message : "Failed to create thread");
		} finally {
			setIsSubmitting(false);
		}
	}

	function handleSubmit(e: React.FormEvent) {
		e.preventDefault();
		if (mode === "pick") {
			handleAddToExistingThread();
		} else {
			handleCreateThreadAndAdd();
		}
	}

	return (
		<div
			role="dialog"
			className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
			onClick={handleClose}
			onKeyDown={(e) => {
				if (e.key === "Escape") handleClose();
			}}
		>
			<div
				role="document"
				className="w-full max-w-md bg-white rounded-xl shadow-xl p-6"
				onClick={(e) => e.stopPropagation()}
				onKeyDown={() => {}}
			>
				<h2 className="text-lg font-semibold text-gray-900 mb-1">
					{mode === "pick" ? "Add to Thread" : "New Thread + Candidate"}
				</h2>
				<p className="text-sm text-gray-500 mb-4">{globalItemName}</p>

				<form onSubmit={handleSubmit} className="space-y-4">
					{mode === "pick" ? (
						<div>
							<label
								htmlFor="thread-select"
								className="block text-sm font-medium text-gray-700 mb-1"
							>
								Thread
							</label>
							<select
								id="thread-select"
								value={selectedThreadId ?? ""}
								onChange={(e) => handleSelectChange(e.target.value)}
								className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent bg-white"
							>
								{activeThreads.map((t) => (
									<option key={t.id} value={t.id}>
										{t.name} ({t.categoryName})
									</option>
								))}
								<option value="new">+ New Thread...</option>
							</select>
						</div>
					) : (
						<>
							<div>
								<label
									htmlFor="new-thread-name"
									className="block text-sm font-medium text-gray-700 mb-1"
								>
									Thread name
								</label>
								<input
									id="new-thread-name"
									type="text"
									value={newThreadName}
									onChange={(e) => setNewThreadName(e.target.value)}
									placeholder="e.g. Lightweight sleeping bag"
									className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent"
								/>
							</div>

							<div>
								<label
									htmlFor="new-thread-category"
									className="block text-sm font-medium text-gray-700 mb-1"
								>
									Category
								</label>
								<select
									id="new-thread-category"
									value={newThreadCategoryId ?? ""}
									onChange={(e) =>
										setNewThreadCategoryId(Number(e.target.value))
									}
									className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent bg-white"
								>
									{categories?.map((cat) => (
										<option key={cat.id} value={cat.id}>
											{cat.name}
										</option>
									))}
								</select>
							</div>

							{activeThreads.length > 0 && (
								<button
									type="button"
									onClick={() => setMode("pick")}
									className="text-sm text-gray-500 hover:text-gray-700 underline"
								>
									Back to thread picker
								</button>
							)}
						</>
					)}

					{error && <p className="text-sm text-red-600">{error}</p>}

					<div className="flex justify-end gap-2 pt-2">
						<button
							type="button"
							onClick={
								mode === "create" && activeThreads.length > 0
									? () => setMode("pick")
									: handleClose
							}
							className="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors"
						>
							Cancel
						</button>
						<button
							type="submit"
							disabled={isSubmitting}
							className="px-4 py-2 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 disabled:opacity-50 rounded-lg transition-colors"
						>
							{isSubmitting
								? "Adding..."
								: mode === "pick"
									? "Add as Candidate"
									: "Create & Add"}
						</button>
					</div>
				</form>
			</div>
		</div>
	);
}
