import { createFileRoute, Link } from "@tanstack/react-router";
import { useState } from "react";
import { CategoryPicker } from "../../../../components/CategoryPicker";
import { GearImage, imageContainerBg } from "../../../../components/GearImage";
import { ImageCropEditor } from "../../../../components/ImageCropEditor";
import { ImageUpload } from "../../../../components/ImageUpload";
import { StatusBadge } from "../../../../components/StatusBadge";
import { useUpdateCandidate } from "../../../../hooks/useCandidates";
import { useFormatters } from "../../../../hooks/useFormatters";
import { useThread } from "../../../../hooks/useThreads";
import { LucideIcon } from "../../../../lib/iconData";
import { useUIStore } from "../../../../stores/uiStore";

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

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

function CandidateDetailPage() {
	const { threadId: threadIdParam, candidateId: candidateIdParam } =
		Route.useParams();
	const threadId = Number(threadIdParam);
	const candidateId = Number(candidateIdParam);
	const { data: thread, isLoading, isError } = useThread(threadId);
	const updateCandidate = useUpdateCandidate(threadId);
	const { weight, price } = useFormatters();
	const openResolveDialog = useUIStore((s) => s.openResolveDialog);
	const openConfirmDeleteCandidate = useUIStore(
		(s) => s.openConfirmDeleteCandidate,
	);

	const [isEditing, setIsEditing] = useState(false);
	const [editingCrop, setEditingCrop] = useState(false);
	const [form, setForm] = useState<FormData>({
		name: "",
		weightGrams: "",
		priceDollars: "",
		categoryId: 1,
		notes: "",
		productUrl: "",
		imageFilename: null,
		pros: "",
		cons: "",
	});
	const [errors, setErrors] = useState<Record<string, string>>({});

	const candidate = thread?.candidates.find((c) => c.id === candidateId);
	const isActive = thread?.status === "active";

	function enterEditMode() {
		if (!candidate) return;
		setForm({
			name: candidate.name,
			weightGrams:
				candidate.weightGrams != null ? String(candidate.weightGrams) : "",
			priceDollars:
				candidate.priceCents != null
					? (candidate.priceCents / 100).toFixed(2)
					: "",
			categoryId: candidate.categoryId,
			notes: candidate.notes ?? "",
			productUrl: candidate.productUrl ?? "",
			imageFilename: candidate.imageFilename ?? null,
			pros: candidate.pros ?? "",
			cons: candidate.cons ?? "",
		});
		setErrors({});
		setIsEditing(true);
	}

	function cancelEdit() {
		setIsEditing(false);
		setErrors({});
	}

	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 handleSave() {
		if (!validate()) return;

		updateCandidate.mutate(
			{
				candidateId,
				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: () => setIsEditing(false),
			},
		);
	}

	// Loading state
	if (isLoading) {
		return (
			<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
				<div className="animate-pulse space-y-6">
					<div className="h-4 bg-gray-100 rounded w-24" />
					<div className="aspect-[16/9] bg-gray-100 rounded-xl" />
					<div className="space-y-3">
						<div className="h-6 bg-gray-100 rounded w-48" />
						<div className="flex gap-2">
							<div className="h-7 bg-gray-100 rounded-full w-20" />
							<div className="h-7 bg-gray-100 rounded-full w-24" />
							<div className="h-7 bg-gray-100 rounded-full w-28" />
						</div>
						<div className="h-4 bg-gray-100 rounded w-full" />
						<div className="h-4 bg-gray-100 rounded w-3/4" />
					</div>
				</div>
			</div>
		);
	}

	// Error / not found
	if (isError || !thread || !candidate) {
		return (
			<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
				<Link
					to="/threads/$threadId"
					params={{ threadId: String(threadId) }}
					className="text-sm text-gray-400 hover:text-gray-600 transition-colors"
				>
					&larr; Back to thread
				</Link>
				<div className="text-center py-16">
					<p className="text-sm text-gray-500">Candidate not found</p>
				</div>
			</div>
		);
	}

	const imageUrl = candidate.imageFilename
		? `/uploads/${candidate.imageFilename}`
		: null;

	return (
		<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
			{/* Back navigation */}
			<div className="mb-6">
				<Link
					to="/threads/$threadId"
					params={{ threadId: String(threadId) }}
					className="text-sm text-gray-400 hover:text-gray-600 transition-colors"
				>
					&larr; Back to thread
				</Link>
			</div>

			{/* Image */}
			{isEditing ? (
				<div className="mb-6">
					<ImageUpload
						value={form.imageFilename}
						imageUrl={imageUrl}
						onChange={(filename) =>
							setForm((f) => ({ ...f, imageFilename: filename }))
						}
					/>
				</div>
			) : editingCrop && imageUrl ? (
				<div className="mb-6">
					<ImageCropEditor
						imageUrl={imageUrl}
						dominantColor={candidate.dominantColor}
						initialZoom={candidate.cropZoom ?? 1}
						initialX={candidate.cropX ?? 0}
						initialY={candidate.cropY ?? 0}
						aspect={16 / 9}
						onSave={(crop) => {
							updateCandidate.mutate({
								threadId,
								candidateId: candidate.id,
								data: {
									cropZoom: crop.zoom,
									cropX: crop.x,
									cropY: crop.y,
								},
							});
							setEditingCrop(false);
						}}
						onCancel={() => setEditingCrop(false)}
					/>
				</div>
			) : imageUrl ? (
				<>
					<div
						className="aspect-[16/9] rounded-xl overflow-hidden mb-2"
						style={{
							backgroundColor: imageContainerBg(candidate.dominantColor),
						}}
					>
						<GearImage
							src={imageUrl}
							alt={candidate.name}
							dominantColor={candidate.dominantColor}
							cropZoom={candidate.cropZoom}
							cropX={candidate.cropX}
							cropY={candidate.cropY}
						/>
					</div>
					{!isEditing && (
						<button
							type="button"
							onClick={() => setEditingCrop(true)}
							className="mb-4 text-sm text-gray-500 hover:text-gray-700 transition-colors"
						>
							Adjust framing
						</button>
					)}
				</>
			) : null}

			{/* Header */}
			<div className="mb-6">
				{isEditing ? (
					<div className="space-y-1">
						<input
							type="text"
							value={form.name}
							onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))}
							className="w-full text-2xl font-bold text-gray-900 px-3 py-2 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent"
						/>
						{errors.name && (
							<p className="text-xs text-red-500">{errors.name}</p>
						)}
					</div>
				) : (
					<div className="flex items-start justify-between gap-4">
						<h1 className="text-2xl font-bold text-gray-900">
							{candidate.name}
						</h1>
						{isActive && (
							<>
								{/* Edit — desktop */}
								<button
									type="button"
									onClick={enterEditMode}
									className="shrink-0 hidden md:inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors"
								>
									<LucideIcon name="pencil" size={14} />
									Edit
								</button>
								{/* Edit — mobile */}
								<button
									type="button"
									onClick={enterEditMode}
									className="shrink-0 md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors"
									aria-label="Edit"
									title="Edit"
								>
									<LucideIcon name="pencil" size={16} />
								</button>
							</>
						)}
					</div>
				)}
			</div>

			{/* Badges */}
			<div className="flex flex-wrap items-center gap-2 mb-6">
				{isEditing ? (
					<>
						<div className="flex items-center gap-2">
							<label className="text-xs font-medium text-gray-500">
								Weight (g)
							</label>
							<input
								type="number"
								min="0"
								step="any"
								value={form.weightGrams}
								onChange={(e) =>
									setForm((f) => ({ ...f, weightGrams: e.target.value }))
								}
								className="w-24 px-2 py-1 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent"
								placeholder="g"
							/>
							{errors.weightGrams && (
								<p className="text-xs text-red-500">{errors.weightGrams}</p>
							)}
						</div>
						<div className="flex items-center gap-2">
							<label className="text-xs font-medium text-gray-500">
								Price ($)
							</label>
							<input
								type="number"
								min="0"
								step="0.01"
								value={form.priceDollars}
								onChange={(e) =>
									setForm((f) => ({ ...f, priceDollars: e.target.value }))
								}
								className="w-24 px-2 py-1 text-sm border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent"
								placeholder="$"
							/>
							{errors.priceDollars && (
								<p className="text-xs text-red-500">{errors.priceDollars}</p>
							)}
						</div>
						<div className="flex items-center gap-2">
							<label className="text-xs font-medium text-gray-500">
								Category
							</label>
							<CategoryPicker
								value={form.categoryId}
								onChange={(id) => setForm((f) => ({ ...f, categoryId: id }))}
							/>
						</div>
					</>
				) : (
					<>
						{candidate.weightGrams != null && (
							<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-blue-50 text-blue-500">
								{weight(candidate.weightGrams)}
							</span>
						)}
						{candidate.priceCents != null && (
							<span className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-green-50 text-green-500">
								{price(candidate.priceCents)}
							</span>
						)}
						{candidate.categoryName && (
							<span className="inline-flex items-center gap-1.5 px-3 py-1 rounded-full text-sm font-medium bg-gray-50 text-gray-600">
								<LucideIcon
									name={candidate.categoryIcon || "folder"}
									size={14}
								/>
								{candidate.categoryName}
							</span>
						)}
						<StatusBadge status={candidate.status} onStatusChange={() => {}} />
					</>
				)}
			</div>

			{/* Product Link */}
			{isEditing ? (
				<div className="mb-6">
					<label className="block text-sm font-medium text-gray-700 mb-1">
						Product Link
					</label>
					<input
						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>
			) : candidate.productUrl ? (
				<div className="mb-6">
					<a
						href={candidate.productUrl}
						target="_blank"
						rel="noopener noreferrer"
						className="inline-flex items-center gap-1.5 text-sm text-gray-500 hover:text-gray-700 transition-colors"
					>
						<LucideIcon name="external-link" size={14} />
						View product page
					</a>
				</div>
			) : null}

			{/* Pros & Cons */}
			{isEditing ? (
				<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-6">
					<div>
						<label className="block text-sm font-medium text-gray-700 mb-1">
							Pros
						</label>
						<textarea
							value={form.pros}
							onChange={(e) => setForm((f) => ({ ...f, pros: e.target.value }))}
							rows={4}
							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>
					<div>
						<label className="block text-sm font-medium text-gray-700 mb-1">
							Cons
						</label>
						<textarea
							value={form.cons}
							onChange={(e) => setForm((f) => ({ ...f, cons: e.target.value }))}
							rows={4}
							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>
				</div>
			) : candidate.pros || candidate.cons ? (
				<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-6">
					{candidate.pros && (
						<div>
							<h3 className="text-sm font-medium text-gray-700 mb-2">Pros</h3>
							<ul className="space-y-1">
								{candidate.pros
									.split("\n")
									.filter((line) => line.trim())
									.map((pro) => (
										<li
											key={pro}
											className="flex items-start gap-2 text-sm text-gray-600"
										>
											<LucideIcon
												name="plus"
												size={14}
												className="text-green-500 mt-0.5 shrink-0"
											/>
											{pro.trim()}
										</li>
									))}
							</ul>
						</div>
					)}
					{candidate.cons && (
						<div>
							<h3 className="text-sm font-medium text-gray-700 mb-2">Cons</h3>
							<ul className="space-y-1">
								{candidate.cons
									.split("\n")
									.filter((line) => line.trim())
									.map((con) => (
										<li
											key={con}
											className="flex items-start gap-2 text-sm text-gray-600"
										>
											<LucideIcon
												name="minus"
												size={14}
												className="text-red-500 mt-0.5 shrink-0"
											/>
											{con.trim()}
										</li>
									))}
							</ul>
						</div>
					)}
				</div>
			) : null}

			{/* Notes */}
			{isEditing ? (
				<div className="mb-6">
					<label className="block text-sm font-medium text-gray-700 mb-1">
						Notes
					</label>
					<textarea
						value={form.notes}
						onChange={(e) => setForm((f) => ({ ...f, notes: e.target.value }))}
						rows={4}
						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>
			) : candidate.notes ? (
				<div className="mb-6">
					<h3 className="text-sm font-medium text-gray-700 mb-2">Notes</h3>
					<p className="text-sm text-gray-600 leading-relaxed whitespace-pre-wrap">
						{candidate.notes}
					</p>
				</div>
			) : null}

			{/* Edit mode actions */}
			{isEditing && (
				<div className="flex gap-3 mb-6">
					<button
						type="button"
						onClick={handleSave}
						disabled={updateCandidate.isPending}
						className="px-4 py-2 bg-gray-700 hover:bg-gray-800 disabled:opacity-50 text-white text-sm font-medium rounded-lg transition-colors"
					>
						{updateCandidate.isPending ? "Saving..." : "Save Changes"}
					</button>
					<button
						type="button"
						onClick={cancelEdit}
						className="px-4 py-2 text-sm text-gray-600 hover:text-gray-800 hover:bg-gray-100 rounded-lg transition-colors"
					>
						Cancel
					</button>
				</div>
			)}

			{/* Thread-specific actions */}
			{!isEditing && isActive && (
				<div className="flex gap-3 pt-4 border-t border-gray-100">
					{/* Pick as winner — desktop */}
					<button
						type="button"
						onClick={() => openResolveDialog(threadId, candidateId)}
						className="hidden md:inline-flex items-center gap-1.5 px-4 py-2 bg-amber-50 hover:bg-amber-100 text-amber-700 text-sm font-medium rounded-lg transition-colors"
					>
						<LucideIcon name="trophy" size={14} />
						Pick as winner
					</button>
					{/* Pick as winner — mobile */}
					<button
						type="button"
						onClick={() => openResolveDialog(threadId, candidateId)}
						className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 bg-amber-50 hover:bg-amber-100 text-amber-700 rounded-lg transition-colors"
						aria-label="Pick as winner"
						title="Pick as winner"
					>
						<LucideIcon name="trophy" size={16} />
					</button>
					{/* Delete — desktop */}
					<button
						type="button"
						onClick={() => openConfirmDeleteCandidate(candidateId)}
						className="hidden md:inline-flex items-center gap-1.5 px-4 py-2 text-sm text-red-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors"
					>
						<LucideIcon name="trash-2" size={14} />
						Delete
					</button>
					{/* Delete — mobile */}
					<button
						type="button"
						onClick={() => openConfirmDeleteCandidate(candidateId)}
						className="md:hidden inline-flex items-center justify-center min-w-[44px] min-h-[44px] p-2 text-red-500 hover:text-red-600 hover:bg-red-50 rounded-lg transition-colors"
						aria-label="Delete"
						title="Delete"
					>
						<LucideIcon name="trash-2" size={16} />
					</button>
				</div>
			)}
		</div>
	);
}
