import { ChevronsUpDown, RefreshCcw } from "lucide-react";
import type { GetServerSideProps } from "next";
import { useState } from "react";
import toast from "react-hot-toast";
import { AreaRiservataLayout } from "~/components/Layout";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { StorageTable } from "~/components/tables/storage-table";
import { Button } from "~/components/ui/button";
import {
	Command,
	CommandEmpty,
	CommandGroup,
	CommandInput,
	CommandItem,
	CommandList,
} from "~/components/ui/command";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
} from "~/components/ui/dialog";
import {
	Popover,
	PopoverContent,
	PopoverTrigger,
} from "~/components/ui/popover";
import { Separator } from "~/components/ui/separator";
import { UploadModal } from "~/components/upload_modal";
import { UserAvatar } from "~/components/user_avatar";
import { cn } from "~/lib/utils";
import type { NextPageWithLayout } from "~/pages/_app";
import { useTranslation } from "~/providers/I18nProvider";
import {
	StorageTableProvider,
	type StorageTable as StorageTableType,
	useStorageTable,
} from "~/providers/StorageTableProvider";

import type { Users } from "~/schemas/public/Users";
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
import { api } from "~/utils/api";

const AdminStorage: NextPageWithLayout = () => {
	const { data, isLoading, refetch } = api.storage.getAll.useQuery();
	const { t } = useTranslation();
	const utils = api.useUtils();
	const { mutate: deleteFiles } = api.storage.deleteFile.useMutation({
		onMutate: () => {
			const toastId = toast.loading(t.caricamento, {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.getAll.invalidate();

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

	const handleDelete = (id: string) => {
		deleteFiles({ storageId: id });
	};

	const handleRefetch = async () => {
		await refetch();
	};

	if (isLoading) return <LoadingPage />;
	if (!data) return <Status500 />;
	//magari query amche file ownership per poter filtrare in tab se da admin o da utente o una lista di utenti a cui è visibile il file
	return (
		<StorageTableProvider>
			<div className="mx-1 flex-1 overflow-auto">
				<div className="mx-auto py-8">
					<StorageTableHeader
						handleDelete={handleDelete}
						handleRefetch={handleRefetch}
					/>

					<StorageTable data={data} handleDelete={handleDelete} />
				</div>
			</div>
		</StorageTableProvider>
	);
};

export const getServerSideProps = (async (context) => {
	const access_token = context.req.cookies.access_token;

	const helpers = await TrpcAuthedFetchingIstance({ access_token });
	if (helpers) {
		await helpers.trpc.storage.getAll.prefetch();
		return {
			props: {
				trpcState: helpers.trpc.dehydrate(),
			},
		};
	}
	return {
		props: {},
	};
}) satisfies GetServerSideProps;
export default AdminStorage;

const StorageTableHeader = ({
	handleRefetch,
	handleDelete,
}: {
	handleRefetch: () => Promise<void>;
	handleDelete: (id: string) => void;
}) => {
	const { table } = useStorageTable();
	if (!table) return null;
	return (
		<div className="mx-3 flex flex-wrap items-center justify-between gap-3">
			<div className="flex max-w-lg items-center gap-3">
				<h3 className="font-bold text-accent-foreground text-xl sm:text-2xl">
					Impostazioni
				</h3>
				<button
					className="cursor-pointer hover:scale-110"
					onClick={async () => {
						await handleRefetch();
						table.resetRowSelection();
					}}
					type="button"
				>
					<RefreshCcw className="size-6" />
				</button>
			</div>
			<div className="flex max-w-lg flex-wrap items-center gap-3">
				<UploadModal
					cb_onUpload={() => {
						table.setRowSelection({});
					}}
				/>
				<Actions handleDelete={handleDelete} table={table} />
			</div>
		</div>
	);
};

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

const Actions = ({
	handleDelete,
	table,
}: {
	handleDelete: (id: string) => void;
	table: StorageTableType;
}) => {
	const { selectedRows } = useStorageTable();
	const [visbOpen, setVisbOpen] = useState(false);

	const deleteSelected = () => {
		selectedRows.forEach((row) => handleDelete(row.id));
		table.resetRowSelection();
	};

	return (
		<div className="flex items-center gap-4 md:mt-0">
			<Button
				className="transition-all duration-100"
				disabled={selectedRows.length === 0}
				onClick={() => setVisbOpen(true)}
				variant="info"
			>
				Modifica Visibilità
			</Button>

			<Button
				className="transition-all duration-100"
				disabled={selectedRows.length === 0}
				onClick={() => deleteSelected()}
				variant="destructive"
			>
				Elimina
			</Button>
			{visbOpen && (
				<VisibComponent
					open={visbOpen}
					setOpen={setVisbOpen}
					storageIds={selectedRows.map((r) => r.id)}
				/>
			)}
		</div>
	);
};

const VisibComponent = ({
	storageIds,
	open,
	setOpen,
}: {
	storageIds: string[];
	open: boolean;
	setOpen: (v: boolean) => void;
}) => {
	const utils = api.useUtils();
	const { data, isLoading } = api.storage.getStorageAccessDetails.useQuery({
		storageIds,
	});
	const { data: users } = api.users.getUsers.useQuery();

	const { mutate: remove } = api.storage.deleteUserStorageEntry.useMutation({
		onMutate: () => {
			const toastId = toast.loading("Rimozione utente in corso", {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.getStorageAccessDetails.invalidate();
			toast.success("Utente rimosso", {
				icon: "🗑️",
				id: context?.toastId,
			});
		},
	});
	const { mutate: add } = api.storage.addUserStorageEntry.useMutation({
		onMutate: () => {
			const toastId = toast.loading("Aggiunta utente in corso", {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.getStorageAccessDetails.invalidate();
			toast.success("Utente aggiunto", {
				icon: "👍",
				id: context?.toastId,
			});
		},
	});

	const { mutate: reset } = api.storage.deleteFilesFromUserStorage.useMutation({
		onMutate: () => {
			const toastId = toast.loading("Reset visibilità in corso", {
				icon: "🪛",
			});
			return { toastId };
		},
		onSuccess: async (_error, _variables, context) => {
			await utils.storage.getStorageAccessDetails.invalidate();
			toast.success("Reset effettuato", {
				icon: "👍",
				id: context?.toastId,
			});
		},
	});

	return (
		<>
			<Dialog onOpenChange={setOpen} open={open}>
				<DialogContent className="max-w-2xl">
					<DialogHeader>
						<DialogTitle>Modifica Visibilità</DialogTitle>
						<DialogDescription className="sr-only">
							Modifica la visibilità degli allegati selezionati
						</DialogDescription>
					</DialogHeader>
					<div className="flex flex-col gap-4">
						{isLoading ? (
							<LoadingPage />
						) : (
							<>
								<div className="flex items-center gap-3">
									<p>Seleziona utente:</p>
									<UtentiCombo
										onSelect={(user) => {
											for (const allegato of storageIds) {
												add({
													storageId: allegato,
													userId: user.id,
													from_admin: true,
												});
											}
										}}
										users={users || []}
									/>
									<Button
										className="ml-auto"
										onClick={() => reset({ storageIds })}
										variant="destructive"
									>
										Reset
									</Button>
								</div>
								{data?.map((allegato, i) => (
									<div
										className={cn(
											"flex flex-col gap-3 rounded-md p-2",
											i % 2 === 0 && "bg-gray-200",
										)}
										key={allegato.id}
									>
										<p className="font-semibold text-lg">
											File: {allegato.originalName}
										</p>
										<div className="flex items-center gap-3">
											<p>Visibile a:</p>
											{allegato.users.length === 0 ? (
												<p>Nessuno</p>
											) : (
												<ul className="flex gap-2">
													{allegato.users.map((user) => (
														<li key={user.id}>
															<Button
																className="after:content-['X']"
																onClick={() =>
																	remove({
																		storageId: allegato.id,
																		userId: user.id,
																	})
																}
																variant="outline"
															>
																{user.username}
															</Button>
														</li>
													))}
												</ul>
											)}
										</div>
									</div>
								))}
							</>
						)}
						<Separator />
					</div>
				</DialogContent>
			</Dialog>
		</>
	);
};

const UtentiCombo = ({
	users,
	onSelect,
}: {
	users: Users[];
	onSelect: (user: Users) => void;
}) => {
	const [open, setOpen] = useState(false);

	return (
		<Popover onOpenChange={setOpen} open={open}>
			<PopoverTrigger asChild>
				<Button
					aria-expanded={open}
					className="w-auto justify-between"
					role="combobox"
					variant="outline"
				>
					Seleziona utente...
					<ChevronsUpDown className="ml-2 size-4 shrink-0 opacity-50" />
				</Button>
			</PopoverTrigger>
			<PopoverContent className="w-auto p-0">
				<Command>
					<CommandInput placeholder="Cerca Utente..." />
					<CommandList>
						<CommandEmpty>Nessun utente.</CommandEmpty>
						<CommandGroup>
							{users.map((user) => (
								<CommandItem
									key={user.id}
									onSelect={(currentValue) => {
										// biome-ignore lint/style/noNonNullAssertion: <known lenght>
										onSelect(users.find((u) => u.id === currentValue)!);
										setOpen(false);
									}}
									value={user.id}
								>
									<span className="flex items-center gap-2">
										<UserAvatar
											className="size-8"
											userId={user.id}
											username={user.username}
										/>

										<span>
											<span className="block font-medium">{user.username}</span>
										</span>
									</span>
								</CommandItem>
							))}
						</CommandGroup>
					</CommandList>
				</Command>
			</PopoverContent>
		</Popover>
	);
};
