import { useMutation, useQuery, useSuspenseQuery } from "@tanstack/react-query";
import { createFileRoute, redirect } from "@tanstack/react-router";
import { createColumnHelper } from "@tanstack/react-table";
import { format } from "date-fns-tz";
import { KeyRound } from "lucide-react";
import { Suspense } from "react";
import { toast } from "sonner";
import { Button } from "../../components/ui/button";
import { Input } from "../../components/ui/input";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "../../components/ui/select";
import {
	Tooltip,
	TooltipContent,
	TooltipTrigger,
} from "../../components/ui/tooltip";
import { authClient } from "../../lib/auth-client";
import { selectableRoles } from "../../lib/auth-permissions";
import { getUsers } from "../../lib/queries/getUsers";
import { permissionQuery } from "../../lib/queries/permsCheck";
import LstTable from "../../lib/tableStuff/LstTable";
import SearchableHeader from "../../lib/tableStuff/SearchableHeader";
import SkellyTable from "../../lib/tableStuff/SkellyTable";
import { trackLstEvent } from "../../lib/umami.utils";
import NewUser from "./-components/Newuser";

export const Route = createFileRoute("/admin/users")({
	beforeLoad: async ({ location }) => {
		const { data: session } = await authClient.getSession();
		// const allowedRole = ["systemAdmin", "admin"];
		const canAccess = await authClient.admin.hasPermission({
			permissions: {
				user: ["create"],
			},
		});

		if (!session?.user) {
			throw redirect({
				to: "/",
				search: {
					redirect: location.href,
				},
			});
		}

		//if (!allowedRole.includes(session.user.role as string)) {
		if (!canAccess) {
			throw redirect({
				to: "/",
			});
		}

		return { user: session.user };
	},
	component: RouteComponent,
});

const UserTable = () => {
	const { data, refetch } = useSuspenseQuery(getUsers());
	//const { data: session } = useSession();
	const { data: canImpersonate = false } = useQuery(
		permissionQuery({
			user: ["impersonate"],
		}),
	);
	const { data: canUpdate = false } = useQuery(
		permissionQuery({
			user: ["update"],
		}),
	);

	const updatePassword = useMutation({
		mutationFn: async ({ user, password }: { user: any; password: string }) => {
			return authClient.admin.setUserPassword({
				userId: user.id,
				newPassword: password,
			});
		},
		onSuccess: () => {
			toast.success("Password updated");
		},
		onError: (error) => {
			toast.error(error.message);
		},
	});

	const handleRoleChange = async (row: any, newRole: string) => {
		//console.log("update this user", row, newRole);

		const { data, error } = await authClient.admin.updateUser({
			userId: row.id,
			data: { role: newRole },
		});

		if (error) {
			console.error(error);
			toast.error(error.message);
			return;
		}

		toast.success(`${data.name}, role was just changed to: ${newRole}`);
		refetch();
	};

	const columnHelper = createColumnHelper<any>();

	const columns = [
		columnHelper.accessor("name", {
			header: ({ column }) => (
				<SearchableHeader column={column} title="Name" searchable={true} />
			),
			filterFn: "includesString",
			cell: (i) => i.getValue(),
		}),
		columnHelper.accessor("username", {
			header: ({ column }) => (
				<SearchableHeader column={column} title="Username" searchable={true} />
			),
			filterFn: "includesString",
			cell: (i) => i.getValue(),
		}),
		columnHelper.accessor("email", {
			header: ({ column }) => (
				<SearchableHeader column={column} title="Email" searchable={true} />
			),
			filterFn: "includesString",
			cell: (i) => i.getValue(),
		}),

		// columnHelper.accessor("role", {
		// 	header: ({ column }) => (
		// 		<SearchableHeader column={column} title="Role" searchable={false} />
		// 	),
		// 	filterFn: "includesString",
		// 	cell: (i) => i.getValue(),
		// }),
		columnHelper.accessor("role", {
			header: ({ column }) => <SearchableHeader column={column} title="Role" />,
			filterFn: "includesString",
			cell: ({ row, getValue }) => {
				const currentRole = getValue();

				return (
					<Select
						value={currentRole}
						onValueChange={(newRole) => {
							handleRoleChange(row.original, newRole);
						}}
					>
						<SelectTrigger className="w-[180px]">
							<SelectValue placeholder="Select role" />
						</SelectTrigger>

						<SelectContent>
							{selectableRoles.map((role) => (
								<SelectItem key={role.value} value={role.value}>
									{role.label}
								</SelectItem>
							))}
						</SelectContent>
					</Select>
				);
			},
		}),
	];

	if (canUpdate) {
		columns.push(
			columnHelper.accessor("changePassword", {
				header: ({ column }) => (
					<SearchableHeader column={column} title="Change Password" />
				),
				filterFn: "includesString",
				cell: ({ row }) => {
					return (
						<div className="flex flex-row items-center gap-2">
							<Input
								type="password"
								placeholder="New password"
								className="w-[200px]"
								onKeyDown={(e) => {
									if (e.key !== "Enter") return;

									const password = e.currentTarget.value.trim();

									if (!password) return;

									updatePassword.mutate({
										user: row.original,
										password,
									});

									e.currentTarget.value = "";
								}}
							/>
							<Tooltip>
								<TooltipTrigger>
									<Button
										size="icon"
										variant="outline"
										onClick={(e) => {
											const input =
												e.currentTarget.parentElement?.querySelector("input");

											const password = input?.value.trim();

											if (!password) return;

											updatePassword.mutate({
												user: row.original,
												password,
											});

											if (input) {
												input.value = "";
											}
										}}
									>
										<KeyRound className="h-4 w-4" />
									</Button>
								</TooltipTrigger>
								<TooltipContent>
									<p>
										Update Password, fill out and press enter or update here
									</p>
								</TooltipContent>
							</Tooltip>
						</div>
					);
				},
			}),
		);
	}

	if (canImpersonate) {
		columns.push(
			columnHelper.accessor("banned", {
				header: ({ column }) => (
					<SearchableHeader column={column} title="Banned" searchable={false} />
				),
				filterFn: "includesString",
				cell: (i) => <span>{i.getValue() ? "True" : "False"}</span>,
			}),
			columnHelper.accessor("impersonate", {
				header: ({ column }) => (
					<SearchableHeader
						column={column}
						title="Impersonate User"
						searchable={false}
					/>
				),
				filterFn: "includesString",
				cell: (i) => {
					const beSomeone = async () => {
						trackLstEvent("impersonateUser_click", {
							module: "users",
							action: "click",
							label: "impersonating user",
							page: window.location.pathname,
						});

						const { data, error } = await authClient.admin.impersonateUser({
							userId: i.row.original.id, // required
						});

						if (data) {
							await authClient.getSession();
							window.location.replace("/lst/app");
						}

						if (error) {
							console.log(error);
						}
					};

					const cantImpersonate = ["admin", "systemAdmin"];
					if (cantImpersonate.includes(i.row.original.role)) return;
					return <Button onClick={beSomeone}>Become user</Button>;
				},
			}),
		);
	}

	columns.push(
		columnHelper.accessor("updatedAt", {
			header: ({ column }) => (
				<SearchableHeader
					column={column}
					title="Updated at"
					searchable={false}
				/>
			),
			filterFn: "includesString",
			cell: (i) => format(i.getValue(), "M/d/yyyy HH:mm"),
		}),
	);

	return (
		<div>
			<div className="flex justify-end m-2">
				<NewUser refetch={refetch} />
			</div>
			<LstTable data={data} columns={columns} pageSize={50} />
		</div>
	);
};

function RouteComponent() {
	// const createUser = async () => {
	// 	const { data: newUser, error } = await authClient.admin.createUser({
	// 		email: "cowch@gmail.com", // required
	// 		password: "crazypassword", // required
	// 		name: "James Smith", // required
	// 		role: "manager",
	// 	});
	// };

	// const besomeone = async () => {
	// 	const { data, error } = await authClient.admin.impersonateUser({
	// 		userId: "iswCNVzQ9cWulbmsaMbeX6e7fV6Eme6t", // required
	// 	});

	// 	await authClient.getSession();
	// 	window.location.replace("/lst/app");
	// };

	return (
		<Suspense fallback={<SkellyTable />}>
			<UserTable />
		</Suspense>
	);
}
