import type { ColumnDef, Table } from "@tanstack/react-table";
import { ExternalLink, MoreHorizontal, Pen, Trash } from "lucide-react";
import Link from "next/link";
import { type FormEvent, useEffect, useState } from "react";
import toast from "react-hot-toast";
import {
	AlertDialog,
	AlertDialogAction,
	AlertDialogCancel,
	AlertDialogContent,
	AlertDialogDescription,
	AlertDialogFooter,
	AlertDialogHeader,
	AlertDialogTitle,
	AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Button, buttonVariants } from "~/components/ui/button";
import { Checkbox } from "~/components/ui/checkbox";
import { DataTable } from "~/components/ui/data-table";
import { DataTableColumnHeader } from "~/components/ui/dataTable-header";
import type { SearchFiltro } from "~/components/ui/dataTable-toolbar";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
} from "~/components/ui/dialog";
import {
	DropdownMenu,
	DropdownMenuContent,
	DropdownMenuItem,
	DropdownMenuLabel,
	DropdownMenuSeparator,
	DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import Input from "~/components/ui/input";
import { cn } from "~/lib/utils";
import { useStorageTable } from "~/providers/StorageTableProvider";
import type { FileMetadataWithAdmin } from "~/server/services/storage.service";
import { api } from "~/utils/api";

export const StorageTable = ({
	data,
	handleDelete,
}: {
	data: FileMetadataWithAdmin[];

	handleDelete: (id: string) => void;
}) => {
	const { setTable, cb_onStateChange } = useStorageTable();

	const [deleteConfirmId, setDeleteConfirmId] = useState<string | null>(null);

	const [renameTarget, setRenameTarget] = useState<{
		allegatoId: string;
		filename: string | null;
	} | null>(null);

	const [tableInstance, setTableInstance] = useState<Table<Column> | null>(
		null,
	);

	// Defer the state update for `setTable`
	useEffect(() => {
		if (tableInstance) {
			setTable(tableInstance);
		}
	}, [tableInstance, setTable]);

	const tabledata = data;

	const columns_titles = {
		actions: "Azioni",
		uploadedAt: "Data creazione",
		type: "Tipo file",
		originalName: "Nome file",
		from_admin: "Caricato da",
		id: "Codice",
	};
	type Column = (typeof tabledata)[number];

	const columns: ColumnDef<Column>[] = [
		{
			cell: ({ row }) => (
				<Checkbox
					aria-label="Select row"
					checked={row.getIsSelected()}
					onCheckedChange={(value) => row.toggleSelected(!!value)}
				/>
			),
			enableHiding: false,
			enableSorting: false,
			header: ({ table }) => (
				<Checkbox
					aria-label="Select all"
					checked={
						table.getIsAllPageRowsSelected() ||
						(table.getIsSomePageRowsSelected() && "indeterminate")
					}
					onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
				/>
			),
			id: "select",
		},
		{
			accessorKey: "originalName",
			cell: ({ row }) => {
				return (
					<Link
						aria-label="Visualizza Allegato"
						className="text-blue-600 underline underline-offset-2"
						href={`/area-riservata/allegato-view/${row.original.id}`}
						target="_blank"
					>
						{row.original.originalName}
					</Link>
				);
			},
			enableHiding: false,
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.originalName}
				/>
			),
		},
		{
			accessorKey: "uploadedAt",
			cell: ({ row }) => {
				const date = row.getValue("uploadedAt");
				return new Date(date as Date).toLocaleDateString();
			},

			enableHiding: false,
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.uploadedAt}
				/>
			),
		},
		{
			accessorKey: "from_admin",
			cell: ({ row }) => {
				return row.original.from_admin ? "Admin" : "Utente";
			},

			enableHiding: false,
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.from_admin}
				/>
			),
		},
		{
			cell: ({ row }) => {
				const data = row.original;

				return (
					<DropdownMenu>
						<DropdownMenuTrigger asChild>
							<Button className="size-8 p-0" variant="ghost">
								<span className="sr-only">Open menu</span>
								<MoreHorizontal />
							</Button>
						</DropdownMenuTrigger>
						<DropdownMenuContent align="end">
							<DropdownMenuLabel>Azioni</DropdownMenuLabel>

							<DropdownMenuItem>
								<Link
									aria-label="Visualizza Allegato"
									className="flex items-center gap-2"
									href={`/area-riservata/allegato-view/${data.id}`}
									target="_blank"
								>
									<ExternalLink className="size-5" />
									Visualizza
								</Link>
							</DropdownMenuItem>
							<DropdownMenuSeparator />
							<DropdownMenuItem
								aria-label="Rinomina Allegato"
								className="flex w-full items-center gap-2"
								onClick={() =>
									setRenameTarget({
										allegatoId: data.id,
										filename: data.originalName,
									})
								}
								role="button"
							>
								<Pen className="size-5" />
								Rinomina
							</DropdownMenuItem>
							<DropdownMenuSeparator />
							<DropdownMenuItem
								aria-label="Elimina Allegato"
								className="flex w-full items-center gap-2"
								onClick={() => setDeleteConfirmId(data.id)}
								role="button"
							>
								<Trash className="size-5" />
								Elimina
							</DropdownMenuItem>
						</DropdownMenuContent>
					</DropdownMenu>
				);
			},
			enableHiding: false,
			id: "actions",
		},
	];

	const searchFiltro: SearchFiltro = {
		columnName: "originalName",
		placeholder: "Cerca file ...",
	};
	return (
		<div className="mx-auto w-full px-2 py-4">
			<DataTable
				columns={columns}
				columns_titles={columns_titles}
				data={tabledata}
				defaultSort={[{ desc: true, id: "uploadedAt" }]}
				onStateChange={cb_onStateChange}
				onTableInit={setTableInstance}
				pinnedFiltri={undefined}
				searchColumn={searchFiltro}
			/>
			{deleteConfirmId !== null && (
				<AlertDialog
					onOpenChange={() => setDeleteConfirmId(null)}
					open={deleteConfirmId !== null}
				>
					<AlertDialogTrigger asChild></AlertDialogTrigger>
					<AlertDialogContent>
						<AlertDialogHeader>
							<AlertDialogTitle>Elimina allegato</AlertDialogTitle>
							<AlertDialogDescription>
								Sei sicuro di voler eliminare questo allegato?
							</AlertDialogDescription>
						</AlertDialogHeader>
						<AlertDialogFooter>
							<AlertDialogCancel>Annulla</AlertDialogCancel>
							<AlertDialogAction
								className={cn(buttonVariants({ variant: "destructive" }))}
								onClick={() => {
									handleDelete(deleteConfirmId);
									setDeleteConfirmId(null);
								}}
							>
								Procedi
							</AlertDialogAction>
						</AlertDialogFooter>
					</AlertDialogContent>
				</AlertDialog>
			)}

			{renameTarget !== null && (
				<RinominaDialog
					renameTarget={renameTarget}
					setRenameTarget={setRenameTarget}
				/>
			)}
		</div>
	);
};

const RinominaDialog = ({
	renameTarget,
	setRenameTarget,
}: {
	renameTarget: { allegatoId: string; filename: string | null };
	setRenameTarget: (
		target: { allegatoId: string; filename: string | null } | null,
	) => void;
}) => {
	const utils = api.useUtils();

	const { mutateAsync: renameFile } = api.storage.renameFile.useMutation({
		onMutate: () => {
			const toastId = toast.loading("Modifica in corso", {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.getAll.invalidate();
			toast.success("File rinominato con successo", {
				icon: "👍",
				id: context?.toastId,
			});
		},
	});

	const handleEditSubmit = async (e: FormEvent<HTMLFormElement>) => {
		e.preventDefault();
		const form = e.currentTarget;
		const formData = new FormData(form);
		if (!formData.get("filename")) {
			return;
		}
		await renameFile({
			fileId: renameTarget.allegatoId,
			name: formData.get("filename") as string,
		});
	};
	return (
		<Dialog
			onOpenChange={() => setRenameTarget(null)}
			open={renameTarget !== null}
		>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>Rinomina</DialogTitle>
					<DialogDescription className="sr-only">Rinomina</DialogDescription>
				</DialogHeader>

				<form method="post" onSubmit={handleEditSubmit}>
					<div className="flex items-center gap-3">
						<Input
							className="mt-0"
							defaultValue={renameTarget.filename || undefined}
							minLength={5}
							name="filename"
							placeholder="Rinomina File"
							type="text"
						/>
						<Button type="submit">Salva</Button>
					</div>
				</form>
			</DialogContent>
		</Dialog>
	);
};
