import { format } from "date-fns";
import {
	Download,
	File,
	FileArchive,
	FileAudio,
	FileCode,
	FileSpreadsheet,
	FileText,
	FileVideo,
	ImageIcon,
	MoreVertical,
	Pencil,
	Trash2,
	TriangleAlert,
} from "lucide-react";
import Link from "next/link";
import { type FormEvent, useState } from "react";
import toast from "react-hot-toast";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { Button } from "~/components/ui/button";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
} from "~/components/ui/dialog";
import {
	DropdownMenu,
	DropdownMenuContent,
	DropdownMenuItem,
	DropdownMenuTrigger,
} from "~/components/ui/dropdown-menu";
import Input from "~/components/ui/input";
import { Separator } from "~/components/ui/separator";
import { UploadModal } from "~/components/upload_modal";
import { getStorageUrl } from "~/lib/storage_utils";

import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import type { UsersId } from "~/schemas/public/Users";
import type { FileMetadata } from "~/server/services/storage.service";
import { api } from "~/utils/api";

export const AllegatiComp = ({
	userId,
	isAdmin,
}: {
	userId: UsersId;
	isAdmin: boolean;
}) => {
	const { t } = useTranslation();
	const { data: allegati, isLoading: isLoadingAllegati } =
		api.storage.retrieveUserFileData.useQuery({ userId });

	const { mutate: deleteFile } = api.storage.deleteUserStorageEntry.useMutation(
		{
			onMutate: () => {
				const toastId = toast.loading(t.caricamento, {
					icon: "🪛",
				});
				return { toastId };
			},
			onSuccess: async (_error, _variables, context) => {
				await utils.storage.retrieveUserFileData.invalidate({
					userId: userId,
				});
				await utils.servizio.getAllServiziData.invalidate({ userId });

				toast.success(t.allegati.allegato_rimosso, {
					icon: "🗑️",
					id: context?.toastId,
				});
			},
		},
	);

	const { mutate: renameFile } = api.storage.renameFile.useMutation({
		onMutate: () => {
			setEditOpen(false);
			const toastId = toast.loading(t.caricamento, {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.retrieveUserFileData.invalidate({
				userId: userId,
			});
			toast.success(t.successo, {
				icon: "👍",
				id: context?.toastId,
			});
		},
	});
	const [editData, setEditData] = useState<{
		id: string;
		filename: string;
	} | null>(null);
	const [editOpen, setEditOpen] = useState(false);

	const handleEditSubmit = (e: FormEvent<HTMLFormElement>) => {
		e.preventDefault();
		const form = e.currentTarget;
		const formData = new FormData(form);
		if (!formData.get("id") || !formData.get("filename")) {
			return;
		}
		renameFile({
			fileId: formData.get("id") as string,
			name: formData.get("filename") as string,
		});
	};

	const utils = api.useUtils();

	if (isLoadingAllegati) return <LoadingPage />;
	if (!allegati) return <Status500 />;

	const from_admin = allegati.filter((a) => a.from_admin);
	const not_from_admin = allegati.filter((a) => !a.from_admin);

	return (
		<div className="flex flex-col space-y-4">
			<h1 className="font-bold text-2xl">{t.allegati.title}</h1>
			<h1 className="font-semibold text-xl">{t.allegati.da_info}</h1>
			{from_admin && (
				<FileList
					delete_onClick={(id) => deleteFile({ storageId: id, userId })}
					files={from_admin}
					isAdmin={isAdmin}
					selectHandler={(id, filename) => {
						setEditData({ filename, id });
						setEditOpen(true);
					}}
				/>
			)}
			<Separator />
			<div className="flex items-center gap-3">
				<UploadModal isAdmin={isAdmin} userId={userId} />{" "}
				<span className="text-sm">Max 5 MB per file</span>
			</div>
			<div className="space-y-2 rounded-md border border-orange-500 p-2">
				<div className="flex items-center gap-2 text-orange-500">
					<TriangleAlert className="size-5" />
					{t.importante}:
				</div>
				<span className="text-sm">{t.allegati.disclamer}</span>
			</div>

			{not_from_admin && (
				<FileList
					delete_onClick={(id) => deleteFile({ storageId: id, userId })}
					files={not_from_admin}
					isAdmin={isAdmin}
					selectHandler={(id, filename) => {
						setEditData({ filename, id });
						setEditOpen(true);
					}}
				/>
			)}
			<EditFileDialog
				data={editData}
				handleEditSubmit={handleEditSubmit}
				onOpenChange={setEditOpen}
				open={editOpen}
			/>
		</div>
	);
};

export const ExtIcon = ({
	mimeType,
	className,
}: {
	mimeType: string;
	className?: string;
}) => {
	const lower = mimeType?.toLowerCase() || "";

	if (!lower) return <File className={cn("size-5 text-gray-500", className)} />;

	// PDF
	if (lower.includes("pdf")) {
		return <FileText className={cn("size-5 text-red-500", className)} />;
	}

	// Images
	if (
		lower.startsWith("image/") ||
		/\b(jpg|jpeg|png|gif|svg|webp)\b/.test(lower)
	) {
		return <ImageIcon className={cn("size-5 text-blue-500", className)} />;
	}

	// Code files
	if (/\b(html|css|js|jsx|ts|tsx|json|xml)\b/.test(lower)) {
		return <FileCode className={cn("size-5 text-emerald-500", className)} />;
	}

	// Spreadsheets
	if (/\b(xls|xlsx|csv)\b/.test(lower)) {
		return (
			<FileSpreadsheet className={cn("size-5 text-green-600", className)} />
		);
	}

	// Archives
	if (/\b(zip|rar|7z|tar|gz)\b/.test(lower)) {
		return <FileArchive className={cn("size-5 text-amber-600", className)} />;
	}

	// Audio
	if (/\b(mp3|wav|ogg|flac)\b/.test(lower)) {
		return <FileAudio className={cn("size-5 text-purple-500", className)} />;
	}

	// Video
	if (/\b(mp4|avi|mov|wmv|webm)\b/.test(lower)) {
		return <FileVideo className={cn("size-5 text-pink-500", className)} />;
	}

	return <File className={cn("size-5 text-gray-500", className)} />;
};

const EditFileDialog = ({
	open,
	onOpenChange,
	data,
	handleEditSubmit,
}: {
	open: boolean;
	onOpenChange: (status: boolean) => void;
	data: {
		id: string;
		filename: string;
	} | null;
	handleEditSubmit: (e: FormEvent<HTMLFormElement>) => void;
}) => {
	const { t } = useTranslation();
	return (
		<Dialog onOpenChange={onOpenChange} open={open}>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>{t.modifica}</DialogTitle>
					<DialogDescription className="sr-only">Edit</DialogDescription>
				</DialogHeader>
				{data && (
					<form method="post" onSubmit={handleEditSubmit}>
						<div className="flex items-center gap-3">
							<label className="sr-only" htmlFor="id">
								ID
							</label>
							<Input
								className="hidden"
								name="id"
								readOnly
								type="text"
								value={data.id}
							/>
							<label className="sr-only" htmlFor="filename">
								filename
							</label>
							<Input
								className="mt-0"
								defaultValue={data.filename || undefined}
								id="filename"
								name="filename"
								placeholder="Modifica messaggio"
								type="text"
							/>
							<Button type="submit">{t.salva}</Button>
						</div>
					</form>
				)}
			</DialogContent>
		</Dialog>
	);
};

interface FileListProps {
	files: FileMetadata[];
	delete_onClick: (id: string) => void;
	isAdmin: boolean;
	selectHandler: (id: string, filename: string) => void;
}

function FileList({
	files,
	delete_onClick,
	isAdmin,
	selectHandler,
}: FileListProps) {
	return (
		<div className="w-full">
			<div className="rounded-md border">
				<div className="grid grid-cols-12 gap-2 bg-muted/50 p-4 font-medium text-muted-foreground text-sm">
					<div className="col-span-6 md:col-span-8">File</div>
					<div className="col-span-4 md:col-span-3">Data</div>
					<div className="col-span-2 text-right md:col-span-1">Azioni</div>
				</div>
				<div className="divide-y">
					{files.map((file) => (
						<div
							className="grid grid-cols-12 items-center gap-2 p-4 text-sm transition-colors hover:bg-muted/50"
							key={file.id}
						>
							<div className="col-span-6 flex items-center gap-2 md:col-span-8">
								<div className="shrink-0">
									<ExtIcon mimeType={file.mimeType} />
								</div>
								<Link
									aria-label="Allegato"
									className="truncate font-medium text-foreground hover:underline"
									href={`/area-riservata/allegato-view/${file.id}`}
									target="_blank"
								>
									{file.originalName}
								</Link>
							</div>

							<div className="col-span-4 text-muted-foreground md:col-span-3">
								{format(new Date(file.uploadedAt), "d MMM yyyy")}
							</div>
							<div className="col-span-2 flex justify-end gap-1 md:col-span-1">
								<Link
									href={getStorageUrl({
										storageId: file.id,
										params: { mode: "download" },
									})}
								>
									<Button
										className="flex size-8 gap-1 text-sm"
										size="icon"
										variant="outline"
									>
										<Download className="size-4" />
									</Button>
								</Link>

								{isAdmin && (
									<DropdownMenu>
										<DropdownMenuTrigger asChild>
											<Button className="size-8" size="icon" variant="ghost">
												<MoreVertical className="size-4" />
												<span className="sr-only">More options</span>
											</Button>
										</DropdownMenuTrigger>
										<DropdownMenuContent align="end">
											<DropdownMenuItem
												aria-label="Rinomina"
												onClick={() =>
													selectHandler(file.id, file.originalName || "")
												}
											>
												<Pencil className="mr-2 size-4" />
												Rinomina
											</DropdownMenuItem>
											<DropdownMenuItem
												aria-label="Elimina"
												className="text-destructive focus:text-destructive"
												onClick={() => delete_onClick(file.id)}
											>
												<Trash2 className="mr-2 size-4" />
												Elimina
											</DropdownMenuItem>
										</DropdownMenuContent>
									</DropdownMenu>
								)}
							</div>
						</div>
					))}
				</div>
			</div>
		</div>
	);
}
