import { type GetServerSideProps, type NextPage } from "next";
import Head from "next/head";

import { AiOutlineClear } from "react-icons/ai";
import { FaShieldAlt } from "react-icons/fa";
import { IoTrashBinOutline } from "react-icons/io5";
import { SiGithub, SiGoogle } from "react-icons/si";
import { GiStarFormation } from "react-icons/gi";
import { api } from "~/utils/api";
import { getServerAuthSession } from "../../server/auth";

export const getServerSideProps: GetServerSideProps = async (ctx) => {
  const session = await getServerAuthSession(ctx);

  // Redirect to login if not signed in
  if (!session) {
    return {
      redirect: {
        destination: `/api/auth/signin?callbackUrl=${ctx.resolvedUrl}`,
        permanent: false,
      },
    };
  }

  if (!session.user.isAdmin) {
    ctx.res.statusCode = 403;
    return {
      redirect: {
        destination: "/",
        permanent: false,
      },
    };
  }
  // Return session if logged in
  return {
    props: { session },
  };
};

const Admin: NextPage = () => {
  return (
    <>
      <Head>
        <title>Sprint Padawan - Admin</title>
        <meta name="description" content="Plan. Sprint. Repeat." />
      </Head>
      <div className="flex flex-col items-center justify-center text-center px-4 py-16 ">
        <div className="flex flex-col items-center">
          <AdminBody />
        </div>
      </div>
    </>
  );
};

export default Admin;

const AdminBody: React.FC = () => {
  const {
    data: usersCount,
    isLoading: usersCountLoading,
    isFetching: usersCountFetching,
    refetch: refetchUsersCount,
  } = api.user.countAll.useQuery();
  const {
    data: users,
    isLoading: usersLoading,
    isFetching: usersFetching,
    refetch: refetchUsers,
  } = api.user.getAll.useQuery();
  const {
    data: roomsCount,
    isLoading: roomsCountLoading,
    isFetching: roomsCountFetching,
    refetch: refetchRoomsCount,
  } = api.room.countAll.useQuery();
  const {
    data: votesCount,
    isLoading: votesCountLoading,
    isFetching: votesCountFetching,
    refetch: refetchVotesCount,
  } = api.vote.countAll.useQuery();

  const getProviders = (user: {
    createdAt: Date;
    accounts: {
      provider: string;
    }[];
    sessions: {
      id: string;
    }[];
    id: string;
    isAdmin: boolean;
    isVIP: boolean;
    name: string | null;
    email: string | null;
  }) => {
    return user.accounts.map((account) => {
      return account.provider;
    });
  };

  const deleteUserMutation = api.user.delete.useMutation({
    onSuccess: async () => {
      await refetchData();
    },
  });

  const clearSessionsByUserMutation = api.session.deleteAllByUserId.useMutation(
    {
      onSuccess: async () => {
        await refetchData();
      },
    }
  );

  const clearSessionsMutation = api.session.deleteAll.useMutation({
    onSuccess: async () => {
      await refetchData();
    },
  });

  const setAdminMutation = api.user.setAdmin.useMutation({
    onSuccess: async () => {
      await refetchData();
    },
  });

  const setVIPMutation = api.user.setVIP.useMutation({
    onSuccess: async () => {
      await refetchData();
    },
  });

  const deleteUserHandler = async (userId: string) => {
    await deleteUserMutation.mutateAsync({ userId });
  };

  const clearSessionsByUserHandler = async (userId: string) => {
    await clearSessionsByUserMutation.mutateAsync({ userId });
  };

  const clearSessionsHandler = async () => {
    await clearSessionsMutation.mutateAsync();
  };

  const setAdmin = async (userId: string, value: boolean) => {
    await setAdminMutation.mutateAsync({ userId, value });
  };

  const setVIP = async (userId: string, value: boolean) => {
    await setVIPMutation.mutateAsync({ userId, value });
  };

  const refetchData = async () => {
    await Promise.all([
      refetchUsers(),
      refetchUsersCount(),
      refetchRoomsCount(),
      refetchVotesCount(),
    ]);
  };

  return (
    <>
      <h1 className="text-4xl font-bold">Admin Panel</h1>

      <div className="stats stats-horizontal shadow bg-neutral m-4">
        <div className="stat">
          <div className="stat-title">Users</div>
          <div className="stat-value">
            {usersCountLoading || usersCountFetching ? (
              <span className="loading loading-dots loading-lg"></span>
            ) : (
              <>{usersCount ? usersCount : "0"}</>
            )}
          </div>
        </div>

        <div className="stat">
          <div className="stat-title">Rooms</div>
          <div className="stat-value">
            {roomsCountLoading || roomsCountFetching ? (
              <span className="loading loading-dots loading-lg"></span>
            ) : (
              <>{roomsCount ? roomsCount : "0"}</>
            )}
          </div>
        </div>

        <div className="stat">
          <div className="stat-title">Votes</div>
          <div className="stat-value">
            {votesCountLoading || votesCountFetching ? (
              <span className="loading loading-dots loading-lg"></span>
            ) : (
              <>{votesCount ? votesCount : "0"}</>
            )}
          </div>
        </div>
      </div>

      {usersCountFetching ||
      usersFetching ||
      roomsCountFetching ||
      votesCountFetching ? (
        <span className="loading loading-dots loading-lg"></span>
      ) : (
        <div className="flex flex-row flex-wrap text-center items-center justify-center gap-2">
          <button
            className="btn btn-primary m-2"
            onClick={() => void clearSessionsHandler()}
          >
            Delete All Sessions
          </button>

          <button
            className="btn btn-primary"
            onClick={() => void refetchData()}
          >
            Re-fetch
          </button>
        </div>
      )}

      <div className="card max-w-[80vw] bg-neutral shadow-xl m-4">
        <div className="card-body">
          <h2 className="card-title">Users:</h2>

          {usersLoading || usersFetching ? (
            <span className="loading loading-dots loading-lg"></span>
          ) : (
            <div className="overflow-x-scroll">
              <table className="table text-center">
                {/* head */}
                <thead>
                  <tr className="border-white">
                    <th>ID</th>
                    <th>Name</th>
                    <th>Created At</th>
                    <th># Sessions</th>
                    <th>Providers</th>
                    <th>Actions</th>
                  </tr>
                </thead>
                <tbody className="">
                  {users
                    ?.sort((user1, user2) =>
                      user2.createdAt > user1.createdAt ? 1 : -1
                    )
                    .map((user) => {
                      return (
                        <tr key={user.id} className="hover">
                          <td className="max-w-[100px] break-words">
                            {user.id}
                          </td>

                          <td className="max-w-[100px] break-normal">
                            {user.name}
                          </td>
                          <td className="max-w-[100px] break-normal">
                            {user.createdAt.toLocaleDateString()}
                          </td>
                          <td className="max-w-[100px] break-normal">
                            {user.sessions.length}
                          </td>
                          <td className="max-w-[100px] break-normal">
                            {getProviders(user).includes("google") && (
                              <SiGoogle className="text-xl m-1 inline-block hover:text-secondary" />
                            )}
                            {getProviders(user).includes("github") && (
                              <SiGithub className="text-xl m-1 inline-block hover:text-secondary" />
                            )}
                          </td>
                          <td>
                            <button className="m-2">
                              {user.isAdmin ? (
                                <FaShieldAlt
                                  className="text-xl inline-block text-primary"
                                  onClick={() => void setAdmin(user.id, false)}
                                />
                              ) : (
                                <FaShieldAlt
                                  className="text-xl inline-block"
                                  onClick={() => void setAdmin(user.id, true)}
                                />
                              )}
                            </button>
                            <button className="m-2">
                              {user.isVIP ? (
                                <GiStarFormation
                                  className="text-xl inline-block text-secondary"
                                  onClick={() => void setVIP(user.id, false)}
                                />
                              ) : (
                                <GiStarFormation
                                  className="text-xl inline-block"
                                  onClick={() => void setVIP(user.id, true)}
                                />
                              )}
                            </button>
                            <button
                              className="m-2"
                              onClick={() =>
                                void clearSessionsByUserHandler(user.id)
                              }
                            >
                              <AiOutlineClear className="text-xl inline-block hover:text-warning" />
                            </button>
                            <button
                              className="m-2"
                              onClick={() => void deleteUserHandler(user.id)}
                            >
                              <IoTrashBinOutline className="text-xl inline-block hover:text-error" />
                            </button>
                          </td>
                        </tr>
                      );
                    })}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
    </>
  );
};
