import { createFileRoute, Link } from "@tanstack/react-router";
import { Reorder } from "framer-motion";
import { useEffect, useState } from "react";
import { CandidateCard } from "../../../components/CandidateCard";
import { CandidateListItem } from "../../../components/CandidateListItem";
import { CategoryPicker } from "../../../components/CategoryPicker";
import { ComparisonTable } from "../../../components/ComparisonTable";
import { ImageUpload } from "../../../components/ImageUpload";
import { SetupImpactSelector } from "../../../components/SetupImpactSelector";
import {
	useCreateCandidate,
	useReorderCandidates,
	useUpdateCandidate,
} from "../../../hooks/useCandidates";
import { useCurrency } from "../../../hooks/useCurrency";
import { useImpactDeltas } from "../../../hooks/useImpactDeltas";
import { useSetup } from "../../../hooks/useSetups";
import { useThread } from "../../../hooks/useThreads";
import { LucideIcon } from "../../../lib/iconData";
import { useUIStore } from "../../../stores/uiStore";

export const Route = createFileRoute("/threads/$threadId/")({
	component: ThreadDetailPage,
});

function ThreadDetailPage() {
	const { threadId: threadIdParam } = Route.useParams();
	const threadId = Number(threadIdParam);
	const { data: thread, isLoading, isError } = useThread(threadId);
	const candidateViewMode = useUIStore((s) => s.candidateViewMode);
	const setCandidateViewMode = useUIStore((s) => s.setCandidateViewMode);
	const selectedSetupId = useUIStore((s) => s.selectedSetupId);
	const updateCandidate = useUpdateCandidate(threadId);
	const reorderMutation = useReorderCandidates(threadId);
	const { data: setupData } = useSetup(selectedSetupId);
	const { deltas } = useImpactDeltas(
		thread?.candidates ?? [],
		setupData?.items,
		thread?.categoryId ?? 0,
	);

	const [addCandidateOpen, setAddCandidateOpen] = useState(false);

	const [tempItems, setTempItems] = useState<
		NonNullable<typeof thread>["candidates"] | null
	>(null);

	// Clear tempItems when server data changes
	// biome-ignore lint/correctness/useExhaustiveDependencies: thread?.candidates is the intended trigger
	useEffect(() => {
		setTempItems(null);
	}, [thread?.candidates]);

	if (isLoading) {
		return (
			<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
				<div className="animate-pulse space-y-6">
					<div className="h-6 bg-gray-200 rounded w-48" />
					<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
						{[1, 2, 3].map((i) => (
							<div key={i} className="h-40 bg-gray-200 rounded-xl" />
						))}
					</div>
				</div>
			</div>
		);
	}

	if (isError || !thread) {
		return (
			<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-16 text-center">
				<h2 className="text-xl font-semibold text-gray-900 mb-2">
					Thread not found
				</h2>
				<Link
					to="/"
					search={{ tab: "planning" }}
					className="text-sm text-gray-600 hover:text-gray-700"
				>
					Back to planning
				</Link>
			</div>
		);
	}

	const isActive = thread.status === "active";
	const winningCandidate = thread.resolvedCandidateId
		? thread.candidates.find((c) => c.id === thread.resolvedCandidateId)
		: null;

	const displayItems = tempItems ?? thread.candidates;

	function handleDragEnd() {
		if (!tempItems) return;
		reorderMutation.mutate({
			orderedIds: tempItems.map((c) => c.id),
		});
	}

	return (
		<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
			{/* Header */}
			<div className="mb-6">
				<Link
					to="/"
					search={{ tab: "planning" }}
					className="text-sm text-gray-500 hover:text-gray-700 mb-2 inline-block"
				>
					&larr; Back to planning
				</Link>
				<div className="flex items-center gap-3">
					<h1 className="text-xl font-semibold text-gray-900">{thread.name}</h1>
					<span
						className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${
							isActive
								? "bg-gray-100 text-gray-600"
								: "bg-gray-100 text-gray-500"
						}`}
					>
						{isActive ? "Active" : "Resolved"}
					</span>
				</div>
			</div>

			{/* Resolution banner */}
			{!isActive && winningCandidate && (
				<div className="mb-6 p-4 bg-amber-50 border border-amber-200 rounded-xl">
					<p className="text-sm text-amber-800">
						<span className="font-medium">{winningCandidate.name}</span> was
						picked as the winner and added to your collection.
					</p>
				</div>
			)}

			{/* Toolbar: Add candidate + view toggle */}
			<div className="mb-6 flex items-center gap-3 flex-wrap">
				{isActive && (
					<button
						type="button"
						onClick={() => setAddCandidateOpen(true)}
						className="inline-flex items-center gap-2 px-4 py-2 bg-gray-700 hover:bg-gray-800 text-white text-sm font-medium rounded-lg transition-colors"
					>
						<svg
							className="w-4 h-4"
							fill="none"
							stroke="currentColor"
							viewBox="0 0 24 24"
						>
							<path
								strokeLinecap="round"
								strokeLinejoin="round"
								strokeWidth={2}
								d="M12 4v16m8-8H4"
							/>
						</svg>
						Add Candidate
					</button>
				)}
				{thread.candidates.length > 0 && (
					<div className="flex items-center gap-1 bg-gray-100 rounded-lg p-0.5">
						<button
							type="button"
							onClick={() => setCandidateViewMode("list")}
							className={`p-1.5 rounded-md transition-colors ${
								candidateViewMode === "list"
									? "bg-gray-200 text-gray-900"
									: "text-gray-400 hover:text-gray-600"
							}`}
							title="List view"
						>
							<LucideIcon name="layout-list" size={16} />
						</button>
						<button
							type="button"
							onClick={() => setCandidateViewMode("grid")}
							className={`p-1.5 rounded-md transition-colors ${
								candidateViewMode === "grid"
									? "bg-gray-200 text-gray-900"
									: "text-gray-400 hover:text-gray-600"
							}`}
							title="Grid view"
						>
							<LucideIcon name="layout-grid" size={16} />
						</button>
						{thread.candidates.length >= 2 && (
							<button
								type="button"
								onClick={() => setCandidateViewMode("compare")}
								className={`p-1.5 rounded-md transition-colors ${
									candidateViewMode === "compare"
										? "bg-gray-200 text-gray-900"
										: "text-gray-400 hover:text-gray-600"
								}`}
								title="Compare view"
							>
								<LucideIcon name="columns-3" size={16} />
							</button>
						)}
					</div>
				)}
				<SetupImpactSelector threadStatus={thread.status} />
			</div>

			{/* Candidates */}
			{thread.candidates.length === 0 ? (
				<div className="py-12 text-center">
					<div className="mb-3">
						<LucideIcon
							name="tag"
							size={48}
							className="text-gray-400 mx-auto"
						/>
					</div>
					<h3 className="text-lg font-semibold text-gray-900 mb-1">
						No candidates yet
					</h3>
					<p className="text-sm text-gray-500">
						Add your first candidate to start comparing.
					</p>
				</div>
			) : candidateViewMode === "compare" ? (
				<ComparisonTable
					candidates={displayItems}
					resolvedCandidateId={thread.resolvedCandidateId}
					deltas={deltas}
				/>
			) : candidateViewMode === "list" ? (
				isActive ? (
					<Reorder.Group
						axis="y"
						values={displayItems}
						onReorder={setTempItems}
						className="flex flex-col"
					>
						{displayItems.map((candidate, index) => (
							<CandidateListItem
								key={candidate.id}
								candidate={candidate}
								rank={index + 1}
								isActive={isActive}
								onStatusChange={(newStatus) =>
									updateCandidate.mutate({
										candidateId: candidate.id,
										status: newStatus,
									})
								}
								delta={deltas[candidate.id]}
								onDragEnd={handleDragEnd}
							/>
						))}
					</Reorder.Group>
				) : (
					<div className="flex flex-col gap-2">
						{displayItems.map((candidate, index) => (
							<CandidateListItem
								key={candidate.id}
								candidate={candidate}
								rank={index + 1}
								isActive={isActive}
								onStatusChange={(newStatus) =>
									updateCandidate.mutate({
										candidateId: candidate.id,
										status: newStatus,
									})
								}
								delta={deltas[candidate.id]}
							/>
						))}
					</div>
				)
			) : (
				<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
					{thread.candidates.map((candidate, index) => (
						<CandidateCard
							key={candidate.id}
							id={candidate.id}
							name={candidate.name}
							weightGrams={candidate.weightGrams}
							priceCents={candidate.priceCents}
							categoryName={candidate.categoryName}
							categoryIcon={candidate.categoryIcon}
							imageFilename={candidate.imageFilename}
							imageUrl={candidate.imageUrl}
							productUrl={candidate.productUrl}
							threadId={threadId}
							isActive={isActive}
							status={candidate.status}
							onStatusChange={(newStatus) =>
								updateCandidate.mutate({
									candidateId: candidate.id,
									status: newStatus,
								})
							}
							pros={candidate.pros}
							cons={candidate.cons}
							rank={index + 1}
							delta={deltas[candidate.id]}
						/>
					))}
				</div>
			)}

			{addCandidateOpen && (
				<AddCandidateModal
					threadId={threadId}
					onClose={() => setAddCandidateOpen(false)}
				/>
			)}
		</div>
	);
}

interface AddCandidateModalProps {
	threadId: number;
	onClose: () => void;
}

interface ModalFormData {
	name: string;
	weightGrams: string;
	priceDollars: string;
	categoryId: number;
	notes: string;
	productUrl: string;
	imageFilename: string | null;
	pros: string;
	cons: string;
}

const INITIAL_MODAL_FORM: ModalFormData = {
	name: "",
	weightGrams: "",
	priceDollars: "",
	categoryId: 1,
	notes: "",
	productUrl: "",
	imageFilename: null,
	pros: "",
	cons: "",
};

function AddCandidateModal({ threadId, onClose }: AddCandidateModalProps) {
	const createCandidate = useCreateCandidate(threadId);
	const { currency } = useCurrency();
	const [form, setForm] = useState<ModalFormData>(INITIAL_MODAL_FORM);
	const [errors, setErrors] = useState<Record<string, string>>({});

	function validate(): boolean {
		const newErrors: Record<string, string> = {};
		if (!form.name.trim()) {
			newErrors.name = "Name is required";
		}
		if (
			form.weightGrams &&
			(Number.isNaN(Number(form.weightGrams)) || Number(form.weightGrams) < 0)
		) {
			newErrors.weightGrams = "Must be a positive number";
		}
		if (
			form.priceDollars &&
			(Number.isNaN(Number(form.priceDollars)) || Number(form.priceDollars) < 0)
		) {
			newErrors.priceDollars = "Must be a positive number";
		}
		if (
			form.productUrl &&
			form.productUrl.trim() !== "" &&
			!form.productUrl.match(/^https?:\/\//)
		) {
			newErrors.productUrl = "Must be a valid URL (https://...)";
		}
		setErrors(newErrors);
		return Object.keys(newErrors).length === 0;
	}

	function handleSubmit(e: React.FormEvent) {
		e.preventDefault();
		if (!validate()) return;

		createCandidate.mutate(
			{
				name: form.name.trim(),
				weightGrams: form.weightGrams ? Number(form.weightGrams) : undefined,
				priceCents: form.priceDollars
					? Math.round(Number(form.priceDollars) * 100)
					: undefined,
				categoryId: form.categoryId,
				notes: form.notes.trim() || undefined,
				productUrl: form.productUrl.trim() || undefined,
				imageFilename: form.imageFilename ?? undefined,
				pros: form.pros.trim() || undefined,
				cons: form.cons.trim() || undefined,
			},
			{
				onSuccess: () => {
					setForm(INITIAL_MODAL_FORM);
					onClose();
				},
			},
		);
	}

	return (
		<div
			className="fixed inset-0 z-50 flex items-center justify-center"
			onClick={onClose}
			onKeyDown={(e) => e.key === "Escape" && onClose()}
		>
			{/* Backdrop */}
			<div className="absolute inset-0 bg-black/40" />

			{/* Modal */}
			<div
				className="relative bg-white rounded-xl shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-y-auto"
				onClick={(e) => e.stopPropagation()}
				onKeyDown={(e) => e.stopPropagation()}
			>
				<div className="px-6 py-4 border-b border-gray-100 flex items-center justify-between">
					<h2 className="text-lg font-semibold text-gray-900">Add Candidate</h2>
					<button
						type="button"
						onClick={onClose}
						className="p-1 text-gray-400 hover:text-gray-600 rounded transition-colors"
					>
						<LucideIcon name="x" size={18} />
					</button>
				</div>

				<form onSubmit={handleSubmit} className="px-6 py-4 space-y-4">
					{/* Image */}
					<ImageUpload
						value={form.imageFilename}
						onChange={(filename) =>
							setForm((f) => ({ ...f, imageFilename: filename }))
						}
					/>

					{/* Name */}
					<div>
						<label
							htmlFor="modal-candidate-name"
							className="block text-sm font-medium text-gray-700 mb-1"
						>
							Name *
						</label>
						<input
							id="modal-candidate-name"
							type="text"
							value={form.name}
							onChange={(e) => setForm((f) => ({ ...f, name: 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"
							placeholder="e.g. Osprey Talon 22"
							autoFocus
						/>
						{errors.name && (
							<p className="mt-1 text-xs text-red-500">{errors.name}</p>
						)}
					</div>

					{/* Weight & Price row */}
					<div className="grid grid-cols-2 gap-4">
						<div>
							<label
								htmlFor="modal-candidate-weight"
								className="block text-sm font-medium text-gray-700 mb-1"
							>
								Weight (g)
							</label>
							<input
								id="modal-candidate-weight"
								type="number"
								min="0"
								step="any"
								value={form.weightGrams}
								onChange={(e) =>
									setForm((f) => ({
										...f,
										weightGrams: 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"
								placeholder="e.g. 680"
							/>
							{errors.weightGrams && (
								<p className="mt-1 text-xs text-red-500">
									{errors.weightGrams}
								</p>
							)}
						</div>
						<div>
							<label
								htmlFor="modal-candidate-price"
								className="block text-sm font-medium text-gray-700 mb-1"
							>
								{`Price (${currency})`}
							</label>
							<input
								id="modal-candidate-price"
								type="number"
								min="0"
								step="0.01"
								value={form.priceDollars}
								onChange={(e) =>
									setForm((f) => ({
										...f,
										priceDollars: 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"
								placeholder="e.g. 129.99"
							/>
							{errors.priceDollars && (
								<p className="mt-1 text-xs text-red-500">
									{errors.priceDollars}
								</p>
							)}
						</div>
					</div>

					{/* Category */}
					<div>
						<label className="block text-sm font-medium text-gray-700 mb-1">
							Category
						</label>
						<CategoryPicker
							value={form.categoryId}
							onChange={(id) => setForm((f) => ({ ...f, categoryId: id }))}
						/>
					</div>

					{/* Notes */}
					<div>
						<label
							htmlFor="modal-candidate-notes"
							className="block text-sm font-medium text-gray-700 mb-1"
						>
							Notes
						</label>
						<textarea
							id="modal-candidate-notes"
							value={form.notes}
							onChange={(e) =>
								setForm((f) => ({ ...f, notes: e.target.value }))
							}
							rows={3}
							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 resize-none"
							placeholder="Any additional notes..."
						/>
					</div>

					{/* Pros */}
					<div>
						<label
							htmlFor="modal-candidate-pros"
							className="block text-sm font-medium text-gray-700 mb-1"
						>
							Pros
						</label>
						<textarea
							id="modal-candidate-pros"
							value={form.pros}
							onChange={(e) => setForm((f) => ({ ...f, pros: e.target.value }))}
							rows={3}
							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 resize-none"
							placeholder="One pro per line..."
						/>
					</div>

					{/* Cons */}
					<div>
						<label
							htmlFor="modal-candidate-cons"
							className="block text-sm font-medium text-gray-700 mb-1"
						>
							Cons
						</label>
						<textarea
							id="modal-candidate-cons"
							value={form.cons}
							onChange={(e) => setForm((f) => ({ ...f, cons: e.target.value }))}
							rows={3}
							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 resize-none"
							placeholder="One con per line..."
						/>
					</div>

					{/* Product Link */}
					<div>
						<label
							htmlFor="modal-candidate-url"
							className="block text-sm font-medium text-gray-700 mb-1"
						>
							Product Link
						</label>
						<input
							id="modal-candidate-url"
							type="url"
							value={form.productUrl}
							onChange={(e) =>
								setForm((f) => ({ ...f, productUrl: 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"
							placeholder="https://..."
						/>
						{errors.productUrl && (
							<p className="mt-1 text-xs text-red-500">{errors.productUrl}</p>
						)}
					</div>

					{/* Actions */}
					<div className="flex gap-3 pt-2">
						<button
							type="submit"
							disabled={createCandidate.isPending}
							className="flex-1 py-2.5 px-4 bg-gray-700 hover:bg-gray-800 disabled:opacity-50 text-white text-sm font-medium rounded-lg transition-colors"
						>
							{createCandidate.isPending ? "Adding..." : "Add Candidate"}
						</button>
						<button
							type="button"
							onClick={onClose}
							className="py-2.5 px-4 text-sm text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded-lg transition-colors"
						>
							Cancel
						</button>
					</div>
				</form>
			</div>
		</div>
	);
}
