import { useMutation, useQuery, useSuspenseQuery } from "@tanstack/react-query";
import { Shield, ShieldAlert, UserCheck, Trash2, Search, AlertTriangle, Ban, KeyRound } from "lucide-react";
import { useState } from "react";
import { toast } from "sonner";
import { authClient } from "~/client/lib/auth-client";
import { Button } from "~/client/components/ui/button";
import { cn } from "~/client/lib/utils";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "~/client/components/ui/table";
import { Badge } from "~/client/components/ui/badge";
import { Input } from "~/client/components/ui/input";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "~/client/components/ui/dialog";
import { CreateUserDialog } from "./create-user-dialog";
import {
	getAdminUsersOptions,
	getUserDeletionImpactOptions,
	deleteUserAccountMutation,
} from "~/client/api-client/@tanstack/react-query.gen";

export function UserManagement({ currentUser }: { currentUser: { id: string } | undefined | null }) {
	const [search, setSearch] = useState("");
	const [userToDelete, setUserToDelete] = useState<string | null>(null);
	const [userToBan, setUserToBan] = useState<{ id: string; name: string; isBanned: boolean } | null>(null);
	const [userToManageAccounts, setUserToManageAccounts] = useState<{
		id: string;
		name: string;
		accounts: { id: string; providerId: string }[];
	}>();

	const { data: deletionImpact, isLoading: isLoadingImpact } = useQuery({
		...getUserDeletionImpactOptions({ path: { userId: userToDelete ?? "" } }),
		enabled: Boolean(userToDelete),
	});

	const { data } = useSuspenseQuery({ ...getAdminUsersOptions() });

	const setRoleMutation = useMutation({
		mutationFn: async ({ userId, role }: { userId: string; role: "user" | "admin" }) => {
			const { error } = await authClient.admin.setRole({ userId, role });
			if (error) throw error;
		},
		onSuccess: () => {
			toast.success("User role updated successfully");
		},
		onError: (error) => {
			toast.error("Failed to update role", { description: error.message });
		},
	});

	const toggleBanUserMutation = useMutation({
		mutationFn: async ({ userId, ban }: { userId: string; ban: boolean }) => {
			const { error } = ban ? await authClient.admin.banUser({ userId }) : await authClient.admin.unbanUser({ userId });
			if (error) throw error;
		},
		onSuccess: () => {
			toast.success("User ban status updated successfully");
		},
		onMutate: () => {
			setUserToBan(null);
		},
		onError: (error) => {
			toast.error("Failed to update ban status", { description: error.message });
		},
	});

	const deleteUser = useMutation({
		mutationFn: async (userId: string) => {
			const { error } = await authClient.admin.removeUser({ userId });
			if (error) throw error;
		},
		onSuccess: () => {
			toast.success("User deleted successfully");
			setUserToDelete(null);
		},
		onError: (error) => {
			toast.error("Failed to delete user", { description: error.message });
		},
	});

	const deleteAccount = useMutation({
		...deleteUserAccountMutation(),
		onSuccess: (_data, variables) => {
			toast.success("Account removed successfully");
			setUserToManageAccounts((prev) => {
				if (!prev) return prev;
				return {
					...prev,
					accounts: prev.accounts.filter((a) => a.id !== variables.path.accountId),
				};
			});
		},
		onError: (error) => {
			toast.error("Failed to remove account", { description: error.message });
		},
	});

	const normalizedSearch = search.toLowerCase();
	const filteredUsers = data.users.filter((user) => {
		const name = user.name?.toLowerCase() ?? "";
		const email = user.email.toLowerCase();

		return name.includes(normalizedSearch) || email.includes(normalizedSearch);
	});

	return (
		<div className="space-y-4 p-6">
			<div className="flex items-center justify-between gap-4">
				<div className="relative flex-1 max-w-sm">
					<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
					<Input
						placeholder="Search users..."
						className="pl-8"
						value={search}
						onChange={(e) => setSearch(e.target.value)}
					/>
				</div>
				<CreateUserDialog />
			</div>

			<div className="rounded-md border">
				<Table>
					<TableHeader>
						<TableRow>
							<TableHead>User</TableHead>
							<TableHead>Role</TableHead>
							<TableHead>Status</TableHead>
							<TableHead className="text-right">Actions</TableHead>
						</TableRow>
					</TableHeader>
					<TableBody>
						<TableRow className={cn({ hidden: filteredUsers.length > 0 })}>
							<TableCell colSpan={4} className="h-24 text-center">
								No users found.
							</TableCell>
						</TableRow>
						{filteredUsers.map((user) => {
							const displayName = user.name ?? user.email;
							const isCurrentUser = user.id === currentUser?.id;
							const isBanned = Boolean(user.banned);

							return (
								<TableRow key={user.id}>
									<TableCell>
										<div className="flex flex-col">
											<span className="font-medium">{displayName}</span>
											<span className="text-sm text-muted-foreground">{user.email}</span>
										</div>
									</TableCell>
									<TableCell>
										<Badge>{user.role}</Badge>
									</TableCell>
									<TableCell>
										<Badge variant="outline" className={cn("text-red-500 border-red-500", { hidden: !isBanned })}>
											Banned
										</Badge>
										<Badge variant="outline" className={cn("bg-success/10 text-success", { hidden: isBanned })}>
											Active
										</Badge>
									</TableCell>
									<TableCell className="text-right">
										<div className={cn("flex justify-end gap-2")}>
											<Button
												variant="ghost"
												size="icon"
												title="Demote to User"
												className={cn({ hidden: user.role !== "admin" || isCurrentUser })}
												onClick={() => setRoleMutation.mutate({ userId: user.id, role: "user" })}
											>
												<ShieldAlert className="h-4 w-4" />
											</Button>
											<Button
												variant="ghost"
												size="icon"
												title="Promote to Admin"
												className={cn({ hidden: user.role === "admin" || isCurrentUser })}
												onClick={() => setRoleMutation.mutate({ userId: user.id, role: "admin" })}
											>
												<Shield className="h-4 w-4" />
											</Button>

											<Button
												variant="ghost"
												size="icon"
												title="Unban user"
												className={cn({ hidden: !isBanned || isCurrentUser })}
												onClick={() => setUserToBan({ id: user.id, name: displayName, isBanned: true })}
											>
												<UserCheck className="h-4 w-4" />
											</Button>
											<Button
												variant="ghost"
												size="icon"
												title="Ban user"
												className={cn({ hidden: isBanned || isCurrentUser })}
												onClick={() => setUserToBan({ id: user.id, name: displayName, isBanned: false })}
											>
												<Ban className="h-4 w-4" />
											</Button>

											<Button
												variant="ghost"
												size="icon"
												title="Delete User"
												className={cn({ hidden: isCurrentUser })}
												onClick={() => setUserToDelete(user.id)}
											>
												<Trash2 className="h-4 w-4 text-destructive" />
											</Button>

											<Button
												variant="ghost"
												size="icon"
												title="Manage Accounts"
												onClick={() =>
													setUserToManageAccounts({
														id: user.id,
														name: displayName,
														accounts: user.accounts,
													})
												}
											>
												<KeyRound className="h-4 w-4" />
											</Button>
										</div>
									</TableCell>
								</TableRow>
							);
						})}
					</TableBody>
				</Table>
			</div>

			<Dialog open={Boolean(userToDelete)} onOpenChange={(open) => !open && setUserToDelete(null)}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>Are you absolutely sure?</DialogTitle>
						<DialogDescription>
							This action cannot be undone. This will permanently delete the user account and remove their data from our
							servers.
						</DialogDescription>
					</DialogHeader>

					<div className={cn("space-y-4", { hidden: !deletionImpact?.organizations.length })}>
						<div className="flex items-start gap-3 p-3 text-sm border rounded-lg bg-destructive/10 border-destructive/20 text-destructive">
							<AlertTriangle className="w-4 h-4 mt-0.5 shrink-0" />
							<div className="space-y-1">
								<p className="font-semibold">Important: Data Deletion</p>
								<p>
									The following personal organizations and all their associated resources will be permanently deleted:
								</p>
							</div>
						</div>

						<div className="space-y-3 overflow-y-auto max-h-48">
							{deletionImpact?.organizations.map((org) => (
								<div key={org.id} className="p-3 border rounded-md bg-muted/50">
									<p className="font-medium">{org.name}</p>
									<div className="flex flex-wrap gap-x-4 gap-y-1 mt-1 text-xs text-muted-foreground">
										<span>{org.resources.volumesCount} Volumes</span>
										<span>{org.resources.repositoriesCount} Repositories</span>
										<span>{org.resources.backupSchedulesCount} Backups</span>
									</div>
								</div>
							))}
						</div>
					</div>

					<div className={cn("text-center py-4", { hidden: !isLoadingImpact })}>
						<p className="text-sm text-muted-foreground">Analyzing deletion impact...</p>
					</div>

					<DialogFooter>
						<Button variant="outline" onClick={() => setUserToDelete(null)}>
							Cancel
						</Button>
						<Button
							variant="destructive"
							disabled={isLoadingImpact || deleteUser.isPending}
							onClick={() => deleteUser.mutate(userToDelete!)}
						>
							Delete User
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>

			<Dialog open={Boolean(userToBan)} onOpenChange={(open) => !open && setUserToBan(null)}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>{userToBan?.isBanned ? "Unban" : "Ban"} User</DialogTitle>
						<DialogDescription>
							Are you sure you want to {userToBan?.isBanned ? "unban" : "ban"} {userToBan?.name}?
							{userToBan?.isBanned
								? " They will regain access to the system."
								: " They will be immediately signed out and lose access."}
						</DialogDescription>
					</DialogHeader>
					<DialogFooter>
						<Button variant="outline" onClick={() => setUserToBan(null)}>
							Cancel
						</Button>
						<Button
							variant="default"
							className={cn({ hidden: !userToBan?.isBanned })}
							onClick={() => toggleBanUserMutation.mutate({ userId: userToBan?.id ?? "", ban: false })}
						>
							Unban User
						</Button>
						<Button
							variant="destructive"
							className={cn({ hidden: Boolean(userToBan?.isBanned) })}
							onClick={() => toggleBanUserMutation.mutate({ userId: userToBan?.id ?? "", ban: true })}
						>
							Ban User
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>

			<Dialog open={Boolean(userToManageAccounts)} onOpenChange={(open) => !open && setUserToManageAccounts(undefined)}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>Manage Accounts</DialogTitle>
						<DialogDescription>Linked authentication accounts for {userToManageAccounts?.name}.</DialogDescription>
					</DialogHeader>

					<div className="space-y-2">
						<p
							className={cn("text-sm text-muted-foreground text-center py-4", {
								hidden: userToManageAccounts?.accounts.length,
							})}
						>
							No accounts linked.
						</p>
						{userToManageAccounts?.accounts.map((account) => (
							<div key={account.id} className="flex items-center justify-between p-3 border rounded-md">
								<span className="text-sm font-medium">{account.providerId}</span>
								<Button
									variant="ghost"
									size="icon"
									title="Remove account"
									disabled={deleteAccount.isPending}
									onClick={() =>
										deleteAccount.mutate({ path: { userId: userToManageAccounts.id, accountId: account.id } })
									}
								>
									<Trash2 className="h-4 w-4 text-destructive" />
								</Button>
							</div>
						))}
					</div>
					<DialogFooter>
						<Button variant="outline" onClick={() => setUserToManageAccounts(undefined)}>
							Close
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>
		</div>
	);
}
