"use client";

/**
 * File Upload Field
 *
 * COPIED VERBATIM FROM: components/onboarding/steps/file-upload-step.tsx:457-584
 * Renders a file upload drop zone with file list
 */

import {
	AlertCircle,
	File,
	FileCode,
	FileImage,
	FileText,
	Upload,
	X,
} from "lucide-react";
import { useRef, useState } from "react";
import {
	ANIMATION_CLASSES,
	getStaggerStyle,
	STAGGER_PRESETS,
} from "../animations";
import { cx } from "../lib/utils";
import { OnboardingLabel } from "../primitives/onboarding-label";
import type { FileUploadFieldProps } from "../types/fields";

/**
 * Format file size
 * COPIED VERBATIM FROM: components/onboarding/steps/file-upload-step.tsx
 */
function formatFileSize(bytes: number): string {
	if (bytes === 0) return "0 Bytes";
	const k = 1024;
	const sizes = ["Bytes", "KB", "MB", "GB"];
	const i = Math.floor(Math.log(bytes) / Math.log(k));
	return parseFloat((bytes / k ** i).toFixed(2)) + " " + sizes[i];
}

/**
 * Get file icon based on mime type
 * COPIED VERBATIM FROM: components/onboarding/steps/file-upload-step.tsx
 */
function getFileIcon(file: File) {
	if (file.type.startsWith("image/")) return FileImage;
	if (file.type.startsWith("text/")) return FileText;
	if (
		file.type.includes("json") ||
		file.type.includes("javascript") ||
		file.type.includes("typescript")
	)
		return FileCode;
	return File;
}

export function FileUploadField({
	id: _id,
	label,
	description,
	accept,
	maxSize,
	maxFiles = 1,
	required = false,
	dropZoneTitle = "Drop files here or click to upload",
	dropZoneSubtitle,
	files,
	onChange,
	onRemove,
	showFileSize = true,
	animationIndex = 0,
	disabled = false,
	error,
}: FileUploadFieldProps) {
	const fileInputRef = useRef<HTMLInputElement>(null);
	const [dragOver, setDragOver] = useState(false);

	const canAddMore = !maxFiles || files.length < maxFiles;

	const handleDragOver = (e: React.DragEvent) => {
		e.preventDefault();
		setDragOver(true);
	};

	const handleDragLeave = (e: React.DragEvent) => {
		e.preventDefault();
		setDragOver(false);
	};

	const handleDrop = (e: React.DragEvent) => {
		e.preventDefault();
		setDragOver(false);
		if (e.dataTransfer.files) {
			onChange(e.dataTransfer.files);
		}
	};

	const handleFiles = (fileList: FileList | null) => {
		if (fileList) {
			onChange(fileList);
		}
	};

	const defaultSubtitle = (
		<>
			{accept && `Accepted: ${accept}`}
			{accept && maxSize && " · "}
			{maxSize && `Max size: ${formatFileSize(maxSize)}`}
			{(accept || maxSize) && maxFiles && " · "}
			{maxFiles && `Max files: ${maxFiles}`}
		</>
	);

	return (
		<div
			className={ANIMATION_CLASSES.fadeInUp}
			style={getStaggerStyle(
				animationIndex,
				STAGGER_PRESETS.formFields.baseDelay,
				STAGGER_PRESETS.formFields.increment,
				STAGGER_PRESETS.formFields.duration,
			)}
		>
			<OnboardingLabel className="mb-2 block text-base font-medium text-foreground">
				{label}
				{required && <span className="ml-1 text-destructive">*</span>}
			</OnboardingLabel>

			{description && (
				<p className="mb-2 text-sm text-muted-foreground">{description}</p>
			)}

			{/* Drop zone */}
			{canAddMore && (
				<div
					onDragOver={handleDragOver}
					onDragLeave={handleDragLeave}
					onDrop={handleDrop}
					onClick={() => fileInputRef.current?.click()}
					className={cx(
						"relative cursor-pointer rounded-lg border-2 border-dashed p-6 transition-colors",
						"hover:border-primary/50 hover:bg-muted/50",
						dragOver
							? "border-primary bg-primary/5"
							: "border-border bg-background",
						error && "border-destructive",
						disabled && "pointer-events-none opacity-50",
					)}
				>
					<input
						ref={fileInputRef}
						type="file"
						accept={accept}
						multiple={!maxFiles || maxFiles > 1}
						onChange={(e) => handleFiles(e.target.files)}
						className="sr-only"
						disabled={disabled}
					/>

					<div className="flex flex-col items-center gap-2 text-center">
						<div className="rounded-full bg-muted p-3">
							<Upload className="size-5 text-muted-foreground" />
						</div>
						<div>
							<p className="text-sm font-medium text-foreground">
								{dropZoneTitle}
							</p>
							<p className="mt-1 text-xs text-muted-foreground">
								{dropZoneSubtitle || defaultSubtitle}
							</p>
						</div>
					</div>
				</div>
			)}

			{/* Uploaded files list */}
			{files.length > 0 && (
				<div className="mt-3 space-y-2">
					{files.map((uploadedFile) => {
						const FileIcon = getFileIcon(uploadedFile.file);
						return (
							<div
								key={uploadedFile.id}
								className={cx(
									"flex items-center gap-3 rounded-lg border p-3",
									"bg-card",
									uploadedFile.status === "error" &&
										"border-destructive bg-destructive/5",
								)}
							>
								{/* Thumbnail / Icon */}
								<div className="flex-shrink-0">
									{uploadedFile.preview ? (
										<img
											src={uploadedFile.preview}
											alt={uploadedFile.file.name}
											className="size-10 rounded object-cover"
										/>
									) : (
										<div className="flex size-10 items-center justify-center rounded bg-muted">
											<FileIcon className="size-5 text-muted-foreground" />
										</div>
									)}
								</div>

								{/* File info */}
								<div className="min-w-0 flex-1">
									<p className="truncate text-sm font-medium text-foreground">
										{uploadedFile.file.name}
									</p>
									{showFileSize && (
										<p className="text-xs text-muted-foreground">
											{formatFileSize(uploadedFile.file.size)}
										</p>
									)}

									{/* Progress bar */}
									{uploadedFile.status === "uploading" && (
										<div className="mt-1.5 h-1 overflow-hidden rounded-full bg-muted">
											<div
												className="h-full bg-primary transition-all duration-200"
												style={{ width: `${uploadedFile.progress}%` }}
											/>
										</div>
									)}

									{/* Error message */}
									{uploadedFile.status === "error" && uploadedFile.error && (
										<p className="mt-1 flex items-center gap-1 text-xs text-destructive">
											<AlertCircle className="size-3" />
											{uploadedFile.error}
										</p>
									)}
								</div>

								{/* Remove button */}
								<button
									type="button"
									onClick={() => onRemove(uploadedFile.id)}
									className={cx(
										"flex-shrink-0 rounded-full p-1 transition-colors",
										"hover:bg-muted",
										"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
									)}
									aria-label={`Remove ${uploadedFile.file.name}`}
									disabled={disabled}
								>
									<X className="size-4 text-muted-foreground" />
								</button>
							</div>
						);
					})}
				</div>
			)}

			{error && <p className="mt-1.5 text-sm text-destructive">{error}</p>}
		</div>
	);
}
