import type { Models } from "@nontara/server/models";
import { useForm } from "@tanstack/react-form";
import { Loader2, Plus, Save } from "lucide-react";
import { useCallback, useEffect, useMemo, useRef } from "react";
import { Button } from "@/components/ui/button";
import {
	Dialog,
	DialogClose,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "@/components/ui/select";
import { FolderExplorer } from "./FolderExplorer";

const LIBRARY_TYPE_OPTIONS = [
	{ label: "Movies", value: "MOVIE" as Models.LibraryData["type"] },
	{ label: "Series", value: "SERIES" as Models.LibraryData["type"] },
] as const;

interface LibraryDialogProps {
	mode: "NEW" | "EDITING";
	open: boolean;
	onOpenChange: (open: boolean) => void;
	onSubmit: (library: Omit<Models.LibraryData, "id"> & { id?: string }) => void;
	defaultLibraryType: Models.LibraryData["type"];
	initialLibrary?: Models.LibraryData;
}

export function LibraryDialog({
	mode,
	open,
	onOpenChange,
	onSubmit,
	defaultLibraryType,
	initialLibrary,
}: LibraryDialogProps) {
	const libraryPathRef = useRef<HTMLInputElement>(null);
	const isEditing = useMemo(() => mode === "EDITING", [mode]);

	const form = useForm({
		defaultValues: useMemo(() => {
			return {
				type: initialLibrary?.type || defaultLibraryType,
				name: initialLibrary?.name || "",
				path: initialLibrary?.path || "",
			};
		}, [initialLibrary, defaultLibraryType]),
		onSubmit: async ({ value }) => {
			const libraryData = {
				...(initialLibrary?.id && { id: initialLibrary.id }),
				name: value.name,
				path: value.path,
				type: value.type,
			};
			onSubmit(libraryData);
			handleDialogOpenChange(false);
		},
		validators: {
			onSubmit: ({ value }) => {
				const errors: Record<string, string> = {};
				if (!value.name?.trim()) {
					errors.name = "Display name is required";
				}
				if (!value.path?.trim()) {
					errors.path = "Folder path is required";
				}
				return Object.keys(errors).length > 0 ? errors : undefined;
			},
		},
	});

	const handleDialogOpenChange = useCallback(
		(newOpen: boolean) => {
			onOpenChange(newOpen);
			if (!newOpen) {
				form.reset();
			}
		},
		[onOpenChange, form.reset],
	);

	const handlePathSelect = useCallback(
		(path: string) => {
			form.setFieldValue("path", path);
			if (libraryPathRef.current) {
				libraryPathRef.current.value = path;
			}
		},
		[form.setFieldValue],
	);

	// Reset form when dialog opens with new data
	useEffect(() => {
		if (open) {
			if (initialLibrary) {
				form.setFieldValue("type", initialLibrary.type);
				form.setFieldValue("name", initialLibrary.name);
				form.setFieldValue("path", initialLibrary.path);
				if (libraryPathRef.current) {
					libraryPathRef.current.value = initialLibrary.path;
				}
			} else {
				form.reset();
				if (libraryPathRef.current) {
					libraryPathRef.current.value = "";
				}
			}
		}
	}, [open, initialLibrary, form.setFieldValue, form.reset]);

	return (
		<Dialog open={open} onOpenChange={handleDialogOpenChange}>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>
						{isEditing ? "Edit media library" : "Add a media library"}
					</DialogTitle>
					<DialogDescription>
						{isEditing
							? "Adjust the details below to keep this library in sync."
							: "Point us to the folders you'd like Nontara to manage."}
					</DialogDescription>
				</DialogHeader>
				<form
					onSubmit={(event) => {
						event.preventDefault();
						event.stopPropagation();
						form.handleSubmit();
					}}
					className="space-y-6"
				>
					<form.Field name="type">
						{(field) => (
							<div className="space-y-2">
								<Label htmlFor="content-type">Content Type</Label>
								<Select
									value={field.state.value}
									onValueChange={(value: Models.LibraryData["type"]) =>
										field.handleChange(value)
									}
								>
									<SelectTrigger id="content-type" className="w-full">
										<SelectValue placeholder="Select content type" />
									</SelectTrigger>
									<SelectContent>
										{LIBRARY_TYPE_OPTIONS.map((option) => (
											<SelectItem key={option.value} value={option.value}>
												{option.label}
											</SelectItem>
										))}
									</SelectContent>
								</Select>
								{field.state.meta.errors.map((error) => (
									<p key={error} className="text-destructive text-sm">
										{error}
									</p>
								))}
							</div>
						)}
					</form.Field>

					<form.Field name="name">
						{(field) => (
							<div className="space-y-2">
								<Label htmlFor="display-name">Display Name</Label>
								<Input
									id="display-name"
									value={field.state.value}
									onChange={(event) => field.handleChange(event.target.value)}
									onBlur={field.handleBlur}
									placeholder="e.g. Family Movies"
									aria-invalid={field.state.meta.errors.length > 0}
								/>
								{field.state.meta.errors.map((error) => (
									<p key={error} className="text-destructive text-sm">
										{error}
									</p>
								))}
							</div>
						)}
					</form.Field>

					<form.Field name="path">
						{(field) => (
							<div className="space-y-2">
								<Label htmlFor="folder-path">Folder Path</Label>
								<Input
									ref={libraryPathRef}
									id="folder-path"
									value={field.state.value}
									onChange={(event) => {
										field.handleChange(event.target.value);
										if (libraryPathRef.current) {
											libraryPathRef.current.value = event.target.value;
										}
									}}
									onBlur={field.handleBlur}
									placeholder="/media/movies"
									aria-invalid={field.state.meta.errors.length > 0}
								/>
								{field.state.meta.errors.map((error) => (
									<p key={error} className="text-destructive text-sm">
										{error}
									</p>
								))}
							</div>
						)}
					</form.Field>

					<FolderExplorer
						onPathSelect={handlePathSelect}
						initialPath={isEditing ? initialLibrary?.path : undefined}
					/>
					<DialogFooter>
						<DialogClose asChild>
							<Button type="button" variant="outline">
								Cancel
							</Button>
						</DialogClose>
						<form.Subscribe>
							{(state) => {
								const hasErrors = Object.keys(state.errors).length > 0;
								const isEmpty =
									!state.values.name?.trim() || !state.values.path?.trim();
								const canSubmit = state.canSubmit && !hasErrors && !isEmpty;

								return (
									<Button
										type="submit"
										disabled={!canSubmit || state.isSubmitting}
										variant={canSubmit ? "default" : "secondary"}
										className={`min-w-[120px] transition-all duration-200 ${
											!canSubmit ? "cursor-not-allowed opacity-60" : ""
										}`}
									>
										{state.isSubmitting ? (
											<>
												<Loader2 className="h-4 w-4 animate-spin" />
												{isEditing ? "Saving..." : "Adding..."}
											</>
										) : isEditing ? (
											<>
												<Save className="h-4 w-4" />
												Save Changes
											</>
										) : (
											<>
												<Plus className="h-4 w-4" />
												Add Library
											</>
										)}
									</Button>
								);
							}}
						</form.Subscribe>
					</DialogFooter>
				</form>
			</DialogContent>
		</Dialog>
	);
}
