import { Search, SquarePen } from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useCallback, useState } from "react";
import { Etichetta, EtichetteModal } from "~/components/etichette";
import { LoadingPage } from "~/components/loading";
import {
	AlertDialog,
	AlertDialogAction,
	AlertDialogCancel,
	AlertDialogContent,
	AlertDialogDescription,
	AlertDialogFooter,
	AlertDialogHeader,
	AlertDialogTitle,
} from "~/components/ui/alert-dialog";
import { Button, buttonVariants } from "~/components/ui/button";
import {
	CommandDialog,
	CommandEmpty,
	CommandGroup,
	CommandInput,
	CommandItem,
	CommandList,
} from "~/components/ui/command";
import {
	ContextMenu,
	ContextMenuContent,
	ContextMenuItem,
	ContextMenuSeparator,
	ContextMenuSub,
	ContextMenuSubContent,
	ContextMenuSubTrigger,
	ContextMenuTrigger,
} from "~/components/ui/context-menu";
import Input from "~/components/ui/input";
import { UserAvatar } from "~/components/user_avatar";
import { useMediaQuery } from "~/hooks/use-media-query";
import { cn } from "~/lib/utils";
import type { ChatsChatid } from "~/schemas/public/Chats";
import type { ActiveChatsType } from "~/server/controllers/chat.controller";
import type { NonNullableUser } from "~/server/controllers/user.controller";
import { api } from "~/utils/api";

type LastMessage = {
	message: string | null;
	time: Date;
	isLastSender: boolean;
};

export const ChatSidebar = ({ chatId }: { chatId: ChatsChatid | null }) => {
	const { data: activeChats, isLoading: loadingActiveChats } =
		api.chat.getActiveChats.useQuery(undefined, {
			refetchInterval: 5000, // Refetch every 5 seconds, Good enough for a chat sidebar
			refetchOnWindowFocus: true,
		});
	const { data: inactiveUsers, isLoading: loadingInactiveUsers } =
		api.users.getActiveUsersWithoutChat.useQuery();

	const router = useRouter();
	const isDesktop = useMediaQuery("(min-width: 768px)");
	const [selectedChat, setSelectedChat] = useState<ChatsChatid | null>(null);
	const [addDialogOpen, setAddDialogOpen] = useState(false);
	const [searchDialogOpen, setSearchDialogOpen] = useState(false);
	const [deleteModalOpen, setDeleteModalOpen] = useState(false);
	const [editEtichettaModalOpen, setEditEtichettaModalOpen] = useState(false);

	const utils = api.useUtils();
	const { mutate: deletechat } = api.chat.deleteChat.useMutation({
		onSuccess: async () => {
			await utils.chat.getActiveChats.invalidate();
			await utils.users.getActiveUsersWithoutChat.invalidate();
		},
	});

	const getVariant = (lastmessage: LastMessage | null) => {
		if (lastmessage) {
			return lastmessage.isLastSender ? "secondary" : "grey";
		}
		return "grey";
	};
	const getLastMessage = (lastmessage: LastMessage | null) => {
		if (lastmessage) {
			return `${lastmessage.isLastSender ? "Tu: " : ""}${lastmessage.message}`;
		}
		return "";
	};

	const handleChatSelection = useCallback(
		async (new_chatid: ChatsChatid) => {
			if (chatId === new_chatid) return;
			await router.push(`/area-riservata/admin/chats/${new_chatid}`);
			setSearchDialogOpen(false);
		},
		[chatId, router],
	);

	if (loadingActiveChats || loadingInactiveUsers) return <LoadingPage />;
	if (!activeChats || !inactiveUsers) return <div>Errore caricamento</div>;

	return (
		<div className="group relative flex h-full flex-col gap-4 py-2 data-[collapsed=true]:p-2">
			<div className="mx-2 flex flex-col items-center justify-between gap-2 sm:flex-row sm:gap-0">
				{isDesktop ? (
					<div className="relative">
						<Search className="absolute top-[0.8rem] left-2 size-4 text-muted-foreground" />
						<label className="sr-only" htmlFor="search">
							Search Chats
						</label>
						<Input className="m-0 pl-8" id="search" placeholder="Search" />
					</div>
				) : (
					<Button
						aria-label="Open Search Dialog"
						className="size-8"
						onClick={() => setSearchDialogOpen(true)}
						size="icon"
						variant="ghost"
					>
						<Search size={20} />
					</Button>
				)}

				<SearchUserComponent
					activeChats={activeChats}
					handleChatSelection={handleChatSelection}
					isOpen={searchDialogOpen}
					OpenChange={setSearchDialogOpen}
				/>
				<Button
					aria-label="Open Add User Dialog"
					className="size-8"
					onClick={() => setAddDialogOpen(true)}
					size="icon"
					variant="ghost"
				>
					<SquarePen size={20} />
				</Button>

				<NewUserComponent
					inactiveUsers={inactiveUsers}
					isOpen={addDialogOpen}
					OpenChange={setAddDialogOpen}
				/>
			</div>

			<nav className="grid gap-1 rounded-lg group-data-[collapsed=true]:justify-center group-data-[collapsed=true]:px-2">
				{activeChats.map((chat) => (
					<ContextMenu key={chat.userinfo.username}>
						<ContextMenuTrigger asChild>
							<Button
								aria-label="Select Chat"
								className={cn(
									buttonVariants({
										size: !isDesktop ? "icon" : "xl",
										variant: getVariant(chat.lastmessage),
									}),

									!isDesktop ? "p-1" : "justify-start gap-4",
									"h-fit w-full",
								)}
								onClick={() => handleChatSelection(chat.id)}
							>
								<UserAvatar
									className="size-10"
									userId={chat.userinfo.id}
									username={chat.userinfo.username}
								/>

								{isDesktop && (
									<div className="flex h-full max-w-28 flex-col text-left align-top">
										<span>{chat.userinfo.username}</span>
										<div className="flex flex-wrap gap-2">
											{chat.etichette.map((etichetta) => (
												<Etichetta
													className="text-xs"
													color_hex={etichetta.color_hex}
													key={etichetta.id_etichetta}
													title={etichetta.title}
												/>
											))}
										</div>

										<span className="truncate text-muted-foreground text-xs">
											{getLastMessage(chat.lastmessage)}
										</span>
										<span className="truncate text-muted-foreground text-xs">
											{chat.lastmessage &&
												new Date(chat.lastmessage.time).toLocaleString("it", {
													day: "2-digit",
													hour: "2-digit",
													minute: "2-digit",
													month: "2-digit",
													year: "numeric",
												})}
										</span>
									</div>
								)}
							</Button>
						</ContextMenuTrigger>
						<ChatSidebarContextMenu
							chatid={chat.id}
							setDeleteModalOpen={setDeleteModalOpen}
							setEditEtichettaModalOpen={setEditEtichettaModalOpen}
							setSelectedChat={setSelectedChat}
						/>
					</ContextMenu>
				))}
				{selectedChat && (
					<>
						<AlertDialog
							onOpenChange={setDeleteModalOpen}
							open={deleteModalOpen}
						>
							<AlertDialogContent>
								<AlertDialogHeader>
									<AlertDialogTitle>Sei assolutamente sicuro?</AlertDialogTitle>
									<AlertDialogDescription>
										Questa azione non può essere annullata. Questo eliminerà
										definitivamente la chat e rimuoverà i dati dai nostri
										server.
									</AlertDialogDescription>
								</AlertDialogHeader>
								<AlertDialogFooter>
									<AlertDialogCancel>Annulla</AlertDialogCancel>
									<AlertDialogAction
										aria-label="Delete Chat"
										className={cn(buttonVariants({ variant: "destructive" }))}
										onClick={() => {
											if (selectedChat) {
												deletechat({
													chatId: selectedChat,
												});
											}
										}}
									>
										Continua
									</AlertDialogAction>
								</AlertDialogFooter>
							</AlertDialogContent>
						</AlertDialog>
						<EtichetteModal
							chatId={selectedChat}
							onOpenChange={setEditEtichettaModalOpen}
							open={editEtichettaModalOpen}
						/>
					</>
				)}
			</nav>
		</div>
	);
};

const SearchUserComponent = ({
	isOpen,
	OpenChange,
	activeChats,
	handleChatSelection,
}: {
	isOpen: boolean;
	OpenChange: (status: boolean) => void;
	activeChats: ActiveChatsType[];
	handleChatSelection: (chatId: ChatsChatid) => void;
}) => {
	return (
		<CommandDialog onOpenChange={OpenChange} open={isOpen}>
			<CommandInput
				className="border-none ring-0 focus:ring-0 focus-visible:ring-0"
				placeholder="Digita il nome utente..."
			/>
			<CommandList>
				<CommandEmpty>Nessun risultato</CommandEmpty>
				<CommandGroup
					className="pb-2"
					heading={activeChats.length > 0 ? "Suggerimenti" : undefined}
				>
					{activeChats?.map((chat) => (
						<CommandItem
							className="rounded-md"
							key={chat.id}
							onSelect={() => {
								handleChatSelection(chat.id);
							}}
						>
							<span className="flex items-center gap-2">
								<UserAvatar
									className="size-8"
									userId={chat.userinfo.id}
									username={chat.userinfo.username}
								/>

								<span>
									<span className="block font-medium">
										{chat.userinfo.username}
									</span>
								</span>
							</span>
						</CommandItem>
					))}
				</CommandGroup>
			</CommandList>
		</CommandDialog>
	);
};

const NewUserComponent = ({
	isOpen,
	OpenChange,
	inactiveUsers,
}: {
	isOpen: boolean;
	OpenChange: (status: boolean) => void;
	inactiveUsers: NonNullableUser[];
}) => {
	const utils = api.useUtils();
	const { mutate: createNewChat } = api.chatSSE.create.useMutation({
		onSuccess: async () => {
			await utils.chat.getActiveChats.invalidate();
			OpenChange(false);
		},
	});
	return (
		<CommandDialog onOpenChange={OpenChange} open={isOpen}>
			<CommandInput
				className="border-none ring-0 focus:ring-0 focus-visible:ring-0"
				placeholder="Digita il nome utente..."
			/>
			<CommandList>
				<CommandEmpty>Nessun risultato</CommandEmpty>
				<CommandGroup
					className="pb-2"
					heading={inactiveUsers.length > 0 ? "Suggerimenti" : undefined}
				>
					{inactiveUsers?.map((user) => (
						<CommandItem
							className="rounded-md"
							key={user.id}
							onSelect={() => {
								createNewChat({
									userId: 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>
		</CommandDialog>
	);
};

const ChatSidebarContextMenu = ({
	chatid,
	setSelectedChat,
	setDeleteModalOpen,
	setEditEtichettaModalOpen,
}: {
	chatid: ChatsChatid;
	setSelectedChat: (chat: ChatsChatid | null) => void;
	setDeleteModalOpen: (status: boolean) => void;
	setEditEtichettaModalOpen: (status: boolean) => void;
}) => {
	const { data: chatData } = api.chat.getChatInfobyId.useQuery({
		chatId: chatid,
	});
	if (!chatData) return null;

	return (
		<>
			<ContextMenuContent>
				<ContextMenuSub>
					<ContextMenuSubTrigger>Etichette</ContextMenuSubTrigger>
					<ContextMenuSubContent className="w-48">
						<ContextMenuItem asChild>
							<button
								aria-label="Edit Chat Labels"
								className="w-full cursor-pointer"
								onClick={() => {
									setSelectedChat(chatid);
									setEditEtichettaModalOpen(true);
								}}
								type="button"
							>
								Modifica
							</button>
						</ContextMenuItem>
					</ContextMenuSubContent>
				</ContextMenuSub>
				<ContextMenuSeparator />
				<ContextMenuItem>
					<Link
						aria-label="View User Profile"
						href={`/area-riservata/admin/user-view/edit-user/${chatData.user_ref}`}
						target="_blank"
					>
						Profilo
					</Link>
				</ContextMenuItem>

				<ContextMenuItem>
					<Link
						aria-label="View User Orders"
						href={`/area-riservata/admin/user-view/ordini/${chatData.user_ref}`}
						target="_blank"
					>
						Ordini
					</Link>
				</ContextMenuItem>
				<ContextMenuItem>
					<Link
						aria-label="View User Attachments"
						href={`/area-riservata/admin/user-view/allegati/${chatData.user_ref}`}
						target="_blank"
					>
						Allegati
					</Link>
				</ContextMenuItem>
				<ContextMenuSub>
					<ContextMenuSubTrigger>Altro</ContextMenuSubTrigger>
					<ContextMenuSubContent className="w-48">
						<ContextMenuItem
							aria-label="Edit Chat"
							className="cursor-pointer rounded-md bg-red-500 text-white hover:bg-red-500/90 focus:bg-red-500/90 focus:text-white"
							onClick={() => {
								setSelectedChat(chatid);
								setDeleteModalOpen(true);
							}}
						>
							Elimina Chat
						</ContextMenuItem>
					</ContextMenuSubContent>
				</ContextMenuSub>
			</ContextMenuContent>
		</>
	);
};
