import { useRef, useState } from "react";
import { apiUpload } from "../lib/api";
import { GearImage, imageContainerBg } from "./GearImage";
import { ImageCropEditor } from "./ImageCropEditor";

interface ImageUploadProps {
	value: string | null;
	imageUrl?: string | null;
	dominantColor?: string | null;
	onChange: (filename: string | null, dominantColor?: string | null) => void;
	onCropChange?: (crop: { zoom: number; x: number; y: number }) => void;
}

const MAX_SIZE_BYTES = 5 * 1024 * 1024; // 5MB
const ACCEPTED_TYPES = ["image/jpeg", "image/png", "image/webp"];

export function ImageUpload({
	value: _value,
	imageUrl,
	dominantColor,
	onChange,
	onCropChange,
}: ImageUploadProps) {
	const [uploading, setUploading] = useState(false);
	const [error, setError] = useState<string | null>(null);
	const [localPreview, setLocalPreview] = useState<string | null>(null);
	const [showCropEditor, setShowCropEditor] = useState(false);
	const [localCrop, setLocalCrop] = useState<{
		zoom: number;
		x: number;
		y: number;
	} | null>(null);
	const inputRef = useRef<HTMLInputElement>(null);

	async function handleFileChange(e: React.ChangeEvent<HTMLInputElement>) {
		const file = e.target.files?.[0];
		if (!file) return;

		setError(null);

		if (!ACCEPTED_TYPES.includes(file.type)) {
			setError("Please select a JPG, PNG, or WebP image.");
			return;
		}

		if (file.size > MAX_SIZE_BYTES) {
			setError("Image must be under 5MB.");
			return;
		}

		// Create local preview for immediate display
		const previewUrl = URL.createObjectURL(file);
		setLocalPreview(previewUrl);

		setUploading(true);
		try {
			const result = await apiUpload<{
				filename: string;
				dominantColor?: string | null;
			}>("/api/images", file);
			onChange(result.filename, result.dominantColor);
			if (onCropChange) {
				setShowCropEditor(true);
			}
		} catch {
			setError("Upload failed. Please try again.");
			setLocalPreview(null);
		} finally {
			setUploading(false);
			// Reset input so the same file can be re-selected
			if (inputRef.current) inputRef.current.value = "";
		}
	}

	function handleRemove(e: React.MouseEvent) {
		e.stopPropagation();
		setLocalPreview(null);
		setLocalCrop(null);
		onChange(null);
	}

	// Determine the display URL: local preview takes priority (just-uploaded),
	// then presigned URL from API, then nothing
	const displayUrl = localPreview || imageUrl || null;

	return (
		<div>
			{/* Crop editor overlay */}
			{showCropEditor && displayUrl && onCropChange && (
				<div className="mb-4">
					<ImageCropEditor
						imageUrl={displayUrl}
						dominantColor={dominantColor}
						onSave={(result) => {
							setLocalCrop(result);
							onCropChange(result);
							setShowCropEditor(false);
						}}
						onCancel={() => setShowCropEditor(false)}
					/>
				</div>
			)}

			{/* Hero image area */}
			{!showCropEditor && (
				<div
					onClick={() => inputRef.current?.click()}
					className="relative w-full aspect-[4/3] rounded-xl overflow-hidden cursor-pointer group"
					style={{
						backgroundColor: displayUrl
							? imageContainerBg(dominantColor)
							: undefined,
					}}
				>
					{displayUrl ? (
						<>
							<GearImage
								src={displayUrl}
								alt="Item"
								dominantColor={dominantColor}
								cropZoom={localCrop?.zoom}
								cropX={localCrop?.x}
								cropY={localCrop?.y}
							/>
							{/* Crop button */}
							{onCropChange && (
								<button
									type="button"
									onClick={(e) => {
										e.stopPropagation();
										setShowCropEditor(true);
									}}
									className="absolute top-2 right-11 w-7 h-7 flex items-center justify-center bg-white/80 hover:bg-white rounded-full text-gray-600 hover:text-gray-900 transition-colors shadow-sm"
									title="Adjust framing"
								>
									<svg
										className="w-4 h-4"
										fill="none"
										stroke="currentColor"
										viewBox="0 0 24 24"
										strokeWidth={2}
									>
										<path d="M6.13 1L6 16a2 2 0 0 0 2 2h15" />
										<path d="M1 6.13L16 6a2 2 0 0 1 2 2v15" />
									</svg>
								</button>
							)}
							{/* Remove button */}
							<button
								type="button"
								onClick={handleRemove}
								className="absolute top-2 right-2 w-7 h-7 flex items-center justify-center bg-white/80 hover:bg-white rounded-full text-gray-600 hover:text-gray-900 transition-colors shadow-sm"
							>
								<svg
									className="w-4 h-4"
									fill="none"
									stroke="currentColor"
									viewBox="0 0 24 24"
								>
									<path
										strokeLinecap="round"
										strokeLinejoin="round"
										strokeWidth={2}
										d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"
									/>
								</svg>
							</button>
						</>
					) : (
						<div className="w-full h-full bg-gray-100 flex flex-col items-center justify-center">
							{/* ImagePlus icon */}
							<svg
								className="w-10 h-10 text-gray-300 group-hover:text-gray-400 transition-colors"
								fill="none"
								stroke="currentColor"
								viewBox="0 0 24 24"
								strokeWidth={1.5}
							>
								<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
								<circle cx="9" cy="9" r="2" />
								<path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" />
								<path d="M14 4v3" />
								<path d="M12.5 5.5h3" />
							</svg>
							<span className="mt-2 text-sm text-gray-400 group-hover:text-gray-500 transition-colors">
								Click to add photo
							</span>
						</div>
					)}

					{/* Upload spinner overlay */}
					{uploading && (
						<div className="absolute inset-0 bg-white/60 flex items-center justify-center">
							<svg
								className="w-8 h-8 text-gray-500 animate-spin"
								fill="none"
								viewBox="0 0 24 24"
							>
								<circle
									className="opacity-25"
									cx="12"
									cy="12"
									r="10"
									stroke="currentColor"
									strokeWidth="4"
								/>
								<path
									className="opacity-75"
									fill="currentColor"
									d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
								/>
							</svg>
						</div>
					)}
				</div>
			)}

			<input
				ref={inputRef}
				type="file"
				accept="image/jpeg,image/png,image/webp"
				onChange={handleFileChange}
				className="hidden"
			/>
			{error && <p className="mt-1 text-xs text-red-500">{error}</p>}
		</div>
	);
}
