import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { createFileRoute } from "@tanstack/react-router";
import {
	Database,
	Film,
	FolderOpen,
	FolderSync,
	Monitor,
	MoreVertical,
	Pencil,
	Plus,
	Trash2,
} from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
} from "@/components/ui/card";
import {
	Dialog,
	DialogClose,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import {
	DropdownMenu,
	DropdownMenuContent,
	DropdownMenuItem,
	DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
	Empty,
	EmptyContent,
	EmptyDescription,
	EmptyHeader,
	EmptyMedia,
	EmptyTitle,
} from "@/components/ui/empty";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "@/components/ui/select";
import { Skeleton } from "@/components/ui/skeleton";
import { useTRPC } from "@/utils/trpc";

export const Route = createFileRoute("/dashboard/libraries")({
	component: RouteComponent,
});

type LibraryType = "MOVIE" | "SERIES";

interface Library {
	id: number;
	name: string;
	type: LibraryType;
	path: string;
	primaryLanguage: string;
	fallbackLanguage: string;
	createdAt: string;
	updatedAt: string;
}

interface LibraryFormData {
	name: string;
	type: LibraryType;
	path: string;
	primaryLanguage: string;
	fallbackLanguage: string;
}

function RouteComponent() {
	const trpc = useTRPC();
	const queryClient = useQueryClient();
	const [createDialogOpen, setCreateDialogOpen] = useState(false);
	const [editDialogOpen, setEditDialogOpen] = useState(false);
	const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
	const [selectedLibrary, setSelectedLibrary] = useState<Library | null>(null);

	const {
		data: libraries,
		isLoading,
		error,
	} = useQuery(trpc.dashboard.libraries.list.queryOptions());

	const createMutation = useMutation(
		trpc.dashboard.libraries.create.mutationOptions(),
	);

	const updateMutation = useMutation(
		trpc.dashboard.libraries.update.mutationOptions(),
	);

	const deleteMutation = useMutation(
		trpc.dashboard.libraries.delete.mutationOptions(),
	);

	const scanMutation = useMutation(
		trpc.dashboard.libraries.scan.mutationOptions(),
	);

	const handleCreate = async (data: LibraryFormData) => {
		try {
			await createMutation.mutateAsync(data);
			queryClient.invalidateQueries({
				queryKey: trpc.dashboard.libraries.list.queryKey(),
			});
			toast.success("Library created successfully");
			setCreateDialogOpen(false);
		} catch (error) {
			if (error instanceof Error) {
				toast.error(`Failed to create library: ${error.message}`);
			}
		}
	};

	const handleEdit = (library: Library) => {
		setSelectedLibrary(library);
		setEditDialogOpen(true);
	};

	const handleUpdate = async (data: LibraryFormData) => {
		if (!selectedLibrary) return;
		try {
			await updateMutation.mutateAsync({ ...data, id: selectedLibrary.id });
			queryClient.invalidateQueries({
				queryKey: trpc.dashboard.libraries.list.queryKey(),
			});
			toast.success("Library updated successfully");
			setEditDialogOpen(false);
			setSelectedLibrary(null);
		} catch (error) {
			if (error instanceof Error) {
				toast.error(`Failed to update library: ${error.message}`);
			}
		}
	};

	const handleDelete = (library: Library) => {
		setSelectedLibrary(library);
		setDeleteDialogOpen(true);
	};

	const confirmDelete = async () => {
		if (!selectedLibrary) return;
		try {
			await deleteMutation.mutateAsync({ id: selectedLibrary.id });
			queryClient.invalidateQueries({
				queryKey: trpc.dashboard.libraries.list.queryKey(),
			});
			toast.success("Library deleted successfully");
			setDeleteDialogOpen(false);
			setSelectedLibrary(null);
		} catch (error) {
			if (error instanceof Error) {
				toast.error(`Failed to delete library: ${error.message}`);
			}
		}
	};

	const handleScan = async (library: Library) => {
		try {
			toast.info(`Scanning library "${library.name}"...`);
			await scanMutation.mutateAsync({ id: library.id });
			toast.success(`Library "${library.name}" scanned successfully`);
		} catch (error) {
			if (error instanceof Error) {
				toast.error(`Failed to scan library: ${error.message}`);
			}
		}
	};

	if (error) {
		return (
			<div className="flex flex-1 flex-col gap-4 p-4">
				<Empty>
					<EmptyHeader>
						<EmptyMedia variant="icon">
							<Database />
						</EmptyMedia>
						<EmptyTitle>Error Loading Libraries</EmptyTitle>
						<EmptyDescription>{error.message}</EmptyDescription>
					</EmptyHeader>
				</Empty>
			</div>
		);
	}

	return (
		<div className="flex flex-1 flex-col gap-4 p-4">
			<div className="flex items-center justify-between">
				<div>
					<h2 className="font-bold text-2xl tracking-tight">
						Library Management
					</h2>
					<p className="text-muted-foreground text-sm">
						Manage your media libraries and folders
					</p>
				</div>
				<Button onClick={() => setCreateDialogOpen(true)}>
					<Plus className="mr-2 h-4 w-4" />
					Add Library
				</Button>
			</div>

			{isLoading ? (
				<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
					{[1, 2, 3].map((i) => (
						<Card key={i}>
							<CardHeader>
								<Skeleton className="h-6 w-3/4" />
								<Skeleton className="h-4 w-1/2" />
							</CardHeader>
							<CardContent>
								<Skeleton className="h-4 w-full" />
							</CardContent>
						</Card>
					))}
				</div>
			) : libraries && libraries.length > 0 ? (
				<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
					{libraries.map((library) => (
						<Card key={library.id}>
							<CardHeader>
								<div className="flex items-start justify-between">
									<div className="flex items-center gap-2">
										{library.type === "MOVIE" ? (
											<Film className="h-5 w-5 text-muted-foreground" />
										) : (
											<Monitor className="h-5 w-5 text-muted-foreground" />
										)}
										<div>
											<CardTitle className="text-lg">{library.name}</CardTitle>
											<CardDescription>
												<Badge variant="secondary" className="mt-1">
													{library.type === "MOVIE" ? "Movies" : "Series"}
												</Badge>
											</CardDescription>
										</div>
									</div>
									<DropdownMenu>
										<DropdownMenuTrigger asChild>
											<Button variant="ghost" size="icon">
												<MoreVertical className="h-4 w-4" />
											</Button>
										</DropdownMenuTrigger>
										<DropdownMenuContent align="end">
											<DropdownMenuItem
												onClick={() => handleScan(library)}
												disabled={scanMutation.isPending}
											>
												<FolderSync className="mr-2 h-4 w-4" />
												{scanMutation.isPending ? "Scanning..." : "Scan"}
											</DropdownMenuItem>
											<DropdownMenuItem onClick={() => handleEdit(library)}>
												<Pencil className="mr-2 h-4 w-4" />
												Edit
											</DropdownMenuItem>
											<DropdownMenuItem
												onClick={() => handleDelete(library)}
												className="text-destructive focus:text-destructive"
											>
												<Trash2 className="mr-2 h-4 w-4" />
												Delete
											</DropdownMenuItem>
										</DropdownMenuContent>
									</DropdownMenu>
								</div>
							</CardHeader>
							<CardContent>
								<div className="space-y-2 text-sm">
									<div className="flex items-center gap-2 text-muted-foreground">
										<FolderOpen className="h-4 w-4" />
										<span className="truncate">{library.path}</span>
									</div>
									<div className="flex gap-2 text-muted-foreground text-xs">
										<span>Primary: {library.primaryLanguage}</span>
										<span>•</span>
										<span>Fallback: {library.fallbackLanguage}</span>
									</div>
								</div>
							</CardContent>
						</Card>
					))}
				</div>
			) : (
				<Empty>
					<EmptyHeader>
						<EmptyMedia variant="icon">
							<Database />
						</EmptyMedia>
						<EmptyTitle>No Libraries Yet</EmptyTitle>
						<EmptyDescription>
							Get started by adding your first media library
						</EmptyDescription>
					</EmptyHeader>
					<EmptyContent>
						<Button onClick={() => setCreateDialogOpen(true)}>
							<Plus className="mr-2 h-4 w-4" />
							Add Library
						</Button>
					</EmptyContent>
				</Empty>
			)}

			<LibraryFormDialog
				open={createDialogOpen}
				onOpenChange={setCreateDialogOpen}
				onSubmit={handleCreate}
				title="Add Library"
				description="Create a new media library to manage your content"
				isLoading={createMutation.isPending}
			/>

			<LibraryFormDialog
				open={editDialogOpen}
				onOpenChange={setEditDialogOpen}
				onSubmit={handleUpdate}
				title="Edit Library"
				description="Update the library settings"
				initialData={selectedLibrary}
				isLoading={updateMutation.isPending}
			/>

			<Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>Delete Library</DialogTitle>
						<DialogDescription>
							Are you sure you want to delete "{selectedLibrary?.name}"? This
							action cannot be undone.
						</DialogDescription>
					</DialogHeader>
					<DialogFooter>
						<DialogClose asChild>
							<Button variant="outline">Cancel</Button>
						</DialogClose>
						<Button
							variant="destructive"
							onClick={confirmDelete}
							disabled={deleteMutation.isPending}
						>
							{deleteMutation.isPending ? "Deleting..." : "Delete"}
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>
		</div>
	);
}

interface LibraryFormDialogProps {
	open: boolean;
	onOpenChange: (open: boolean) => void;
	onSubmit: (data: LibraryFormData) => void;
	title: string;
	description: string;
	initialData?: Library | null;
	isLoading?: boolean;
}

function LibraryFormDialog({
	open,
	onOpenChange,
	onSubmit,
	title,
	description,
	initialData,
	isLoading = false,
}: LibraryFormDialogProps) {
	const [formData, setFormData] = useState<LibraryFormData>({
		name: initialData?.name || "",
		type: initialData?.type || "MOVIE",
		path: initialData?.path || "",
		primaryLanguage: initialData?.primaryLanguage || "en",
		fallbackLanguage: initialData?.fallbackLanguage || "en",
	});

	const handleSubmit = (e: React.FormEvent) => {
		e.preventDefault();
		onSubmit(formData);
	};

	const handleOpenChange = (open: boolean) => {
		onOpenChange(open);
		if (!open) {
			setFormData({
				name: "",
				type: "MOVIE",
				path: "",
				primaryLanguage: "en",
				fallbackLanguage: "en",
			});
		}
	};

	return (
		<Dialog open={open} onOpenChange={handleOpenChange}>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>{title}</DialogTitle>
					<DialogDescription>{description}</DialogDescription>
				</DialogHeader>
				<form onSubmit={handleSubmit} className="space-y-4">
					<div className="space-y-2">
						<Label htmlFor="name">Library Name</Label>
						<Input
							id="name"
							value={formData.name}
							onChange={(e) =>
								setFormData({ ...formData, name: e.target.value })
							}
							placeholder="e.g. Movies Collection"
							required
						/>
					</div>

					<div className="space-y-2">
						<Label htmlFor="type">Content Type</Label>
						<Select
							value={formData.type}
							onValueChange={(value: LibraryType) =>
								setFormData({ ...formData, type: value })
							}
						>
							<SelectTrigger id="type">
								<SelectValue />
							</SelectTrigger>
							<SelectContent>
								<SelectItem value="MOVIE">Movies</SelectItem>
								<SelectItem value="SERIES">Series</SelectItem>
							</SelectContent>
						</Select>
					</div>

					<div className="space-y-2">
						<Label htmlFor="path">Folder Path</Label>
						<Input
							id="path"
							value={formData.path}
							onChange={(e) =>
								setFormData({ ...formData, path: e.target.value })
							}
							placeholder="/media/movies"
							required
						/>
					</div>

					<div className="grid grid-cols-2 gap-4">
						<div className="space-y-2">
							<Label htmlFor="primaryLanguage">Primary Language</Label>
							<Input
								id="primaryLanguage"
								value={formData.primaryLanguage}
								onChange={(e) =>
									setFormData({ ...formData, primaryLanguage: e.target.value })
								}
								placeholder="en"
								required
							/>
						</div>

						<div className="space-y-2">
							<Label htmlFor="fallbackLanguage">Fallback Language</Label>
							<Input
								id="fallbackLanguage"
								value={formData.fallbackLanguage}
								onChange={(e) =>
									setFormData({ ...formData, fallbackLanguage: e.target.value })
								}
								placeholder="en"
								required
							/>
						</div>
					</div>

					<DialogFooter>
						<DialogClose asChild>
							<Button type="button" variant="outline" disabled={isLoading}>
								Cancel
							</Button>
						</DialogClose>
						<Button type="submit" disabled={isLoading}>
							{isLoading ? "Saving..." : initialData ? "Update" : "Create"}
						</Button>
					</DialogFooter>
				</form>
			</DialogContent>
		</Dialog>
	);
}
