import type { ColumnDef, Table } from "@tanstack/react-table";
import {
	Crown,
	Mail,
	MessagesSquare,
	Paperclip,
	Plus,
	Search,
	ShoppingBag,
	Tags,
	User,
	UserCog,
	X,
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
import { useRef, useState } from "react";
import toast from "react-hot-toast";
import { NotePopover } from "~/components/notePopover";
import { DataTable } from "~/components/ui/data-table";
import { DataTableColumnHeader } from "~/components/ui/dataTable-header";
import type {
	PinnedFiltro,
	SearchFiltro,
} from "~/components/ui/dataTable-toolbar";
import { UserAvatar } from "~/components/user_avatar";
import { MutationPageRestore } from "~/lib/tableUtils";
import { cn } from "~/lib/utils";
import type { Etichette } from "~/schemas/public/Etichette";
import type { UsersId } from "~/schemas/public/Users";
import type { UserWChatInfo } from "~/server/controllers/user.controller";
import { api } from "~/utils/api";
import { Etichetta } from "../etichette";
import { WhatsAppIcon2 } from "../svgs";
import { Button } from "../ui/button";
import {
	ContextMenuContent,
	ContextMenuItem,
	ContextMenuLabel,
	ContextMenuSeparator,
	ContextMenuSub,
	ContextMenuSubContent,
	ContextMenuSubTrigger,
} from "../ui/context-menu";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
} from "../ui/dialog";
import { Separator } from "../ui/separator";

export const UsersTable = (props: { data: UserWChatInfo[] }) => {
	const router = useRouter();
	const { mutateAsync: swap } = api.auth.swapUser.useMutation({
		onSuccess: async () => {
			toast.success("Utente cambiato con successo");
			await router.push("/area-riservata/load-page");
		},
	});

	const [selected, setSelected] = useState<{
		id: UsersId;
		etichette: Etichette[];
	} | null>(null);

	const { data } = props;

	const tabledata = data.map((user) => {
		return {
			nome: user.nome,
			chatid: user.chatid,
			created_at: user.created_at,
			email: user.email,
			telefono: user.telefono,
			extra_telefono_numero: user.extra_telefono_numero,
			extra_telefono_titolo: user.extra_telefono_titolo,
			note: user.note,
			id: user.id,
			isAdmin: user.isAdmin ? "Admin" : "Utente",
			isBlocked: user.isBlocked ? "Bloccato" : "Attivo",
			username: user.username,
			etichette: user.etichette,
		};
	});

	const admin_options = [
		{ label: "Admin", value: "Admin" },
		{ label: "Utente", value: "Utente" },
	];

	const columns_titles = {
		created_at: "Creato il",
		email: "Email",
		note: "Note",
		telefono: "Telefono",
		isAdmin: "Ruolo",
		isBlocked: "Status",
		username: "User",
		etichette: "📎",
	};
	type Column = (typeof tabledata)[number];

	const tableRef = useRef<Table<Column> | null>(null);
	const utils = api.useUtils();
	const { onMutate, onSettled } = MutationPageRestore(tableRef);
	const { mutate, isPending } = api.users.editUser.useMutation({
		onSuccess: async () => {
			toast.success("Note aggiornate con successo");
			await utils.users.invalidate();
		},
		onMutate,
		onSettled,
		onError: (error) => {
			toast.error(error.message);
		},
	});

	const columns: ColumnDef<Column>[] = [
		{
			accessorKey: "etichette",
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.etichette}
				/>
			),
			cell: ({ row }) => {
				return (
					<div className="flex max-w-32 flex-wrap items-center gap-2">
						{row.original.etichette.map((e) => (
							<Etichetta
								color_hex={e.color_hex}
								key={e.id_etichetta}
								title={e.title}
							/>
						))}
					</div>
				);
			},
			enableHiding: false,
			enableSorting: false,
		},
		{
			accessorKey: "username",
			cell: ({ row }) => {
				const user = row.original;
				return (
					<Link
						aria-label="Visualizza Utente"
						className="flex items-center gap-2"
						href={`/area-riservata/admin/user-view/ricerca/${user.id}`}
					>
						<UserAvatar
							className="size-8"
							userId={user.id}
							username={user.username}
						/>
						<span className="font-semibold text-sm">{user.username}</span>
					</Link>
				);
			},
			enableHiding: false,
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.username}
				/>
			),
		},
		{
			accessorKey: "note",
			cell: ({ row }) => {
				const note = row.original.note;
				return (
					<NotePopover
						isPending={isPending}
						mutate={mutate}
						note={note}
						userId={row.original.id}
					/>
				);
			},
			header: ({ column }) => (
				<DataTableColumnHeader column={column} title={columns_titles.note} />
			),
			enableSorting: false,
		},

		{
			accessorFn: (row) =>
				`${row.telefono} ${row.nome} ${row.extra_telefono_numero} ${row.extra_telefono_titolo}`,
			id: "telefono", // ID is required when using accessorFn
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.telefono}
				/>
			),
			cell: ({ row }) => {
				const { nome, telefono, extra_telefono_numero, extra_telefono_titolo } =
					row.original;
				return (
					<div className="flex flex-col">
						<span>{telefono}</span>
						{extra_telefono_numero && (
							<>
								<span className="text-xs">{nome}</span>
								<span>{extra_telefono_numero}</span>
								<span className="text-xs">{extra_telefono_titolo}</span>
							</>
						)}
					</div>
				);
			},
			filterFn: "includesString",
		},
		{
			accessorKey: "email",
			header: ({ column }) => (
				<DataTableColumnHeader column={column} title={columns_titles.email} />
			),
		},
		{
			accessorKey: "created_at",
			cell: ({ row }) => {
				const date = row.getValue("created_at");
				return new Date(date as Date).toLocaleDateString();
			},
			enableHiding: false,
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.created_at}
				/>
			),
			sortingFn: "datetime",
		},
		{
			accessorKey: "isAdmin",
			cell: ({ row }) => {
				const isadmin = admin_options.find(
					(status) => status.value === row.getValue("isAdmin"),
				);

				if (!isadmin) {
					return null;
				}

				return (
					<div
						className={cn(
							"flex w-25 items-center",
							isadmin.value === "Admin" && "text-green-500",
						)}
					>
						{isadmin.value === "Admin" && <Crown className="size-4" />}
						<span>{isadmin.label}</span>
					</div>
				);
			},
			filterFn: (row, id, value) => {
				return value.includes(row.getValue(id));
			},
			header: ({ column }) => (
				<DataTableColumnHeader column={column} title={columns_titles.isAdmin} />
			),
		},

		{
			accessorKey: "isBlocked",
			filterFn: (row, id, value) => {
				return value.includes(row.getValue(id));
			},
			header: ({ column }) => (
				<DataTableColumnHeader
					column={column}
					title={columns_titles.isBlocked}
				/>
			),
		},
	];

	const pinnedFiltri: PinnedFiltro[] = [
		{
			columnName: "isAdmin",
			options: [
				{ label: "Admin", value: "Admin" },
				{ label: "Utente", value: "Utente" },
			],
			title: "Ruolo",
		},
		{
			columnName: "isBlocked",
			options: [
				{ label: "Bloccato", value: "Bloccato" },
				{ label: "Attivo", value: "Attivo" },
			],
			title: "Status",
		},
	];
	const searchFiltro: SearchFiltro = {
		columnName: null,
		placeholder: "Cerca...",
	};
	return (
		<div className="mx-auto w-full px-2 py-10">
			<DataTable
				columns={columns}
				columns_titles={columns_titles}
				contextMenuContent={(data) => (
					<ContextMenuContent>
						<ContextMenuLabel className="flex h-8 items-center gap-2">
							<UserAvatar
								className="size-5"
								style={{ height: "1.25rem", width: "1.25rem" }}
								userId={data.id}
								username={data.username}
							/>
							<span className="font-semibold text-sm">{data.username}</span>
						</ContextMenuLabel>
						<ContextMenuItem>
							<Link
								aria-label="Visualizza Ricerca"
								className="flex w-full items-center gap-2"
								href={`/area-riservata/admin/user-view/ricerca/${data.id}`}
							>
								<Search className="text-muted-foreground" /> Ricerca
							</Link>
						</ContextMenuItem>
						<ContextMenuItem>
							<Link
								aria-label="Visualizza Comunicazioni"
								className="flex w-full items-center gap-2"
								href={`/area-riservata/admin/user-view/comunicazioni/${data.id}`}
							>
								<Mail className="text-muted-foreground" /> Comunicazioni
							</Link>
						</ContextMenuItem>
						<ContextMenuItem>
							<Link
								aria-label="Visualizza Profilo"
								className="flex w-full items-center gap-2"
								href={`/area-riservata/admin/user-view/edit-user/${data.id}`}
							>
								<UserCog className="text-muted-foreground" /> Profilo
							</Link>
						</ContextMenuItem>

						<ContextMenuItem>
							<Link
								aria-label="Visualizza Ordini"
								className="flex w-full items-center gap-2"
								href={`/area-riservata/admin/user-view/ordini/${data.id}`}
							>
								<ShoppingBag className="text-muted-foreground" /> Ordini
							</Link>
						</ContextMenuItem>
						<ContextMenuItem>
							<Link
								aria-label="Visualizza Allegati"
								className="flex w-full items-center gap-2"
								href={`/area-riservata/admin/user-view/allegati/${data.id}`}
							>
								<Paperclip className="text-muted-foreground" /> Allegati
							</Link>
						</ContextMenuItem>
						<ContextMenuSeparator />
						<ContextMenuItem>
							<Link
								aria-label="Visualizza Chat"
								className={cn(
									"flex w-full items-center gap-2",
									!data.chatid && "text-neutral-200",
								)}
								href={
									data.chatid
										? {
												pathname: "/area-riservata/admin/chats",
												query: { chatId: data.chatid },
											}
										: "/area-riservata/admin/chats"
								}
							>
								<MessagesSquare /> Chat
							</Link>
						</ContextMenuItem>
						{data.extra_telefono_numero ? (
							<ContextMenuSub>
								<ContextMenuSubTrigger className="flex w-full items-center gap-2">
									<WhatsAppIcon2 className="size-4 fill-muted-foreground stroke-0" />
									WhatsApp
								</ContextMenuSubTrigger>
								<ContextMenuSubContent>
									<ContextMenuItem>
										<Link
											className="flex w-full items-center gap-2"
											href={`https://wa.me/${data.telefono}`}
											target="_blank"
										>
											<WhatsAppIcon2 className="size-4 fill-muted-foreground stroke-0" />
											WhatsApp ({data.nome})
										</Link>
									</ContextMenuItem>
									<ContextMenuItem>
										<Link
											className="flex w-full items-center gap-2"
											href={`https://wa.me/${data.extra_telefono_numero}`}
											target="_blank"
										>
											<WhatsAppIcon2 className="size-4 fill-muted-foreground stroke-0" />
											WhatsApp ({data.extra_telefono_titolo})
										</Link>
									</ContextMenuItem>
								</ContextMenuSubContent>
							</ContextMenuSub>
						) : (
							<ContextMenuItem>
								<Link
									className="flex w-full items-center gap-2"
									href={`https://wa.me/${data.telefono}`}
									target="_blank"
								>
									<WhatsAppIcon2 className="size-4 fill-muted-foreground stroke-0" />
									WhatsApp
								</Link>
							</ContextMenuItem>
						)}

						<ContextMenuSeparator />
						<ContextMenuItem>
							<button
								aria-label="Login as User"
								className="flex w-full cursor-pointer items-center gap-2"
								onClick={async () => await swap({ id: data.id })}
								type="button"
							>
								<User /> Login
							</button>
						</ContextMenuItem>
						<ContextMenuItem>
							<button
								className="flex w-full cursor-pointer items-center gap-2"
								onClick={() => {
									setSelected({ id: data.id, etichette: data.etichette });
								}}
								type="button"
							>
								<Tags /> Etichette
							</button>
						</ContextMenuItem>
					</ContextMenuContent>
				)}
				data={tabledata}
				defaultColumnVisibility={{
					created_at: true,
					email: true,
					telefono: true,
					isAdmin: true,
					isBlocked: false,
					username: true,
				}}
				defaultSort={[{ desc: true, id: "created_at" }]}
				onTableInit={(t) => (tableRef.current = t)}
				pinnedFiltri={pinnedFiltri}
				searchColumn={searchFiltro}
				withContextMenu={true}
			/>
			<UsersEtichetteModal selected={selected} setSelected={setSelected} />
		</div>
	);
};

const UsersEtichetteModal = ({
	selected,
	setSelected,
}: {
	selected: { id: UsersId; etichette: Etichette[] } | null;
	setSelected: React.Dispatch<
		React.SetStateAction<{ id: UsersId; etichette: Etichette[] } | null>
	>;
}) => {
	const utils = api.useUtils();

	const { data: etichette } = api.etichette.getAllEtichette.useQuery();

	const { mutate: addEtichetta } = api.etichette.addUserEtichetta.useMutation({
		onSuccess: async () => {
			toast.success("Etichetta aggiunta con successo");
			await utils.etichette.getAllEtichette.invalidate();
			await utils.users.getUsersWChatInfo.invalidate();
		},
		onError: () => {
			toast.error("Errore nell'aggiunta dell'etichetta");
		},
	});
	const { mutate: removeEtichetta } =
		api.etichette.removeUserEtichetta.useMutation({
			onSuccess: async () => {
				toast.success("Etichetta rimossa con successo");
				await utils.etichette.getAllEtichette.invalidate();
				await utils.users.getUsersWChatInfo.invalidate();
			},
			onError: () => {
				toast.error("Errore nella rimozione dell'etichetta");
			},
		});

	return (
		<Dialog
			onOpenChange={(v) => {
				if (!v) setSelected(null);
			}}
			open={!!selected}
		>
			<DialogContent>
				<DialogHeader>
					<DialogTitle>Etichette</DialogTitle>
					<DialogDescription className="sr-only">Etichette</DialogDescription>
				</DialogHeader>
				<div className="space-y-5">
					<div className="flex flex-col gap-2">
						<h3>Etichette Attive</h3>
						{selected?.etichette.map((etichetta) => (
							<div
								className="flex items-center gap-2"
								key={`${etichetta.id_etichetta}${selected.id}`}
							>
								<Etichetta
									color_hex={etichetta.color_hex}
									title={etichetta.title}
								/>
								<Button
									onClick={() => {
										removeEtichetta({
											userId: selected.id,
											etichettaId: etichetta.id_etichetta,
										});
										setSelected((prev) => {
											if (!prev) return prev;
											return {
												...prev,
												etichette: prev.etichette.filter(
													(e) => e.id_etichetta !== etichetta.id_etichetta,
												),
											};
										});
									}}
									size="sm"
									variant="destructive"
								>
									<X className="size-4" />
								</Button>
							</div>
						))}
					</div>
					<Separator />
					<div className="flex flex-col gap-2">
						<h3>Aggiungi Etichetta</h3>
						{etichette
							?.filter(
								(e) =>
									!selected?.etichette.some(
										(etichetta) => etichetta.id_etichetta === e.id_etichetta,
									),
							)
							.map((e) => (
								<div className="flex items-center gap-2" key={e.id_etichetta}>
									<Etichetta color_hex={e.color_hex} title={e.title} />
									<Button
										onClick={() => {
											if (selected) {
												addEtichetta({
													userId: selected.id,
													etichettaId: e.id_etichetta,
												});
												setSelected((prev) => {
													if (!prev) return prev;
													return {
														...prev,
														etichette: [
															...prev.etichette,
															{
																id_etichetta: e.id_etichetta,
																color_hex: e.color_hex,
																title: e.title,
															},
														],
													};
												});
											}
										}}
										size="sm"
										variant="success"
									>
										<Plus className="size-4" />
									</Button>
								</div>
							))}
					</div>
				</div>
			</DialogContent>
		</Dialog>
	);
};
