import { Download, Pen, Trash } from "lucide-react";
import type { GetServerSideProps } from "next";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { type FormEvent, useState } from "react";
import toast from "react-hot-toast";
import z from "zod";
import { AllegatoIframe } from "~/components/allegato-iframe";
import { Confirm } from "~/components/confirm";
import { DocNotFoundPage } from "~/components/doc_not_found";
import { AreaRiservataLayout } from "~/components/Layout";
import { LoadingPage } from "~/components/loading";
import { Button } from "~/components/ui/button";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from "~/components/ui/dialog";
import Input from "~/components/ui/input";
import { getStorageUrl } from "~/lib/storage_utils";
import { redirectTo500 } from "~/lib/utils";
import type { NextPageWithLayout } from "~/pages/_app";
import { useTranslation } from "~/providers/I18nProvider";
import { useEnforcedSession } from "~/providers/SessionProvider";
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
import { api } from "~/utils/api";

type AllegatoViewProps = {
	allegatoId: string;
};

/**
 * Pagina di visualizzazione dell'allegato: /area-riservata/allegato/[allegatoId]
 */
const AllegatoView: NextPageWithLayout<AllegatoViewProps> = ({
	allegatoId,
}: AllegatoViewProps) => {
	const { t } = useTranslation();
	const session = useEnforcedSession();
	const { data: fileInfos, isLoading } = api.storage.getFileInfos.useQuery({
		storageId: allegatoId,
	});
	const utils = api.useUtils();
	const router = useRouter();
	const { mutate: deleteFile } = api.storage.deleteFile.useMutation({
		onMutate: () => {
			const toastId = toast.loading(t.caricamento, {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.retrieveUserFileData.invalidate();

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

			await router.push("/area-riservata/admin/storage");
		},
	});

	if (isLoading) return <LoadingPage />;

	if (!fileInfos) return <DocNotFoundPage />;

	return (
		<>
			<Head>
				<title>Infoalloggi.it | {fileInfos.originalName}</title>
			</Head>

			<div className="flex h-full w-full grow flex-col md:flex-row">
				<div className="flex grow flex-col justify-center space-y-2 p-4">
					<div className="mx-auto flex flex-wrap items-center gap-4">
						<span>{fileInfos.originalName}</span>
						<span>
							caricato il {new Date(fileInfos.uploadedAt).toLocaleString("it")}
						</span>
						<Link
							href={getStorageUrl({
								storageId: fileInfos.id,
								params: { mode: "download" },
							})}
						>
							<Button className="flex gap-2">
								<Download size={16} />
								Download
							</Button>
						</Link>
						<RinominaDialog
							allegatoId={allegatoId}
							filename={fileInfos.originalName}
						/>
						{session.user.isAdmin && (
							<Confirm
								description="Sei sicuro di voler eliminare questo allegato?"
								onConfirm={() => deleteFile({ storageId: allegatoId })}
								title="Elimina allegato"
							>
								<Button className="flex gap-2" variant="destructive">
									<Trash size={16} />
									Elimina
								</Button>
							</Confirm>
						)}
					</div>
					<AllegatoIframe allegato={fileInfos} />
				</div>
			</div>
		</>
	);
};

AllegatoView.getLayout = function getLayout(page) {
	return <AreaRiservataLayout noSidebar>{page}</AreaRiservataLayout>;
};

export const getServerSideProps = (async (context) => {
	const allegatoId = context.params?.allegatoId;
	if (!allegatoId || typeof allegatoId !== "string") {
		return {
			notFound: true,
		};
	}

	const parsedStorageId = z.string().safeParse(allegatoId);

	if (!parsedStorageId.success) {
		return {
			notFound: true,
		};
	}

	const access_token = context.req.cookies.access_token;

	const helper = await TrpcAuthedFetchingIstance({ access_token });
	if (helper) {
		await helper.trpc.storage.getFileInfos.prefetch({
			storageId: parsedStorageId.data,
		});

		return {
			props: {
				allegatoId: parsedStorageId.data,
				trpcState: helper.trpc.dehydrate(),
			},
		};
	}
	return redirectTo500;
}) satisfies GetServerSideProps<AllegatoViewProps>;

export default AllegatoView;

const RinominaDialog = ({
	allegatoId,
	filename,
}: {
	allegatoId: string;
	filename: string | null;
}) => {
	const { t } = useTranslation();
	const utils = api.useUtils();
	const [editOpen, setEditOpen] = useState(false);

	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.getFileInfos.invalidate({
				storageId: allegatoId,
			});
			toast.success(t.successo, {
				icon: "👍",
				id: context?.toastId,
			});
		},
	});

	const handleEditSubmit = (e: FormEvent<HTMLFormElement>) => {
		e.preventDefault();
		const form = e.currentTarget;
		const formData = new FormData(form);
		if (!formData.get("filename")) {
			return;
		}
		renameFile({
			fileId: allegatoId,
			name: formData.get("filename") as string,
		});
	};
	return (
		<Dialog onOpenChange={setEditOpen} open={editOpen}>
			<DialogTrigger asChild>
				<Button
					className="flex gap-2"
					onClick={() => console.log("rinomina")}
					variant="info"
				>
					<Pen size={16} />
					Rinomina
				</Button>
			</DialogTrigger>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>{t.modifica}</DialogTitle>
					<DialogDescription className="sr-only">modifica</DialogDescription>
				</DialogHeader>

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