/* eslint-disable @next/next/no-img-element */
import UserDisplayList from "@/components/UserDisplayList";
import IconCard from "@/components/IconCard";
import { EntityWithRoles } from "@/interfaces/entity";
import { Stat, StudentUser, Type, User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import { filterBy, mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import { countEntitiesAssignments } from "@/utils/assignments.be";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { countGroupsByEntities } from "@/utils/groups.be";
import {
  checkAccess,
  groupAllowedEntitiesByPermissions,
} from "@/utils/permissions";
import { groupByExam } from "@/utils/stats";
import { countAllowedUsers, getUsers } from "@/utils/users.be";
import { withIronSessionSsr } from "iron-session/next";
import moment from "moment";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMemo } from "react";
import {
  BsClock,
  BsEnvelopePaper,
  BsPencilSquare,
  BsPeople,
  BsPeopleFill,
  BsPersonFill,
  BsPersonFillGear,
} from "react-icons/bs";
import { ToastContainer } from "react-toastify";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
import { isAdmin } from "@/utils/users";

interface Props {
  user: User;
  students: StudentUser[];
  latestStudents: User[];
  latestTeachers: User[];
  userCounts: { [key in Type]: number };
  entities: EntityWithRoles[];
  assignmentsCount: number;
  stats: Stat[];
  groupsCount: number;
}

export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
  const user = await requestUser(req, res);
  if (!user || !user.isVerified) return redirect("/login");

  if (!checkAccess(user, ["admin", "developer", "corporate"]))
    return redirect("/");

  const entityIDS = mapBy(user.entities, "id") || [];
  const entities = await getEntitiesWithRoles(
    isAdmin(user) ? undefined : entityIDS
  );

  const {
    ["view_students"]: allowedStudentEntities,
    ["view_teachers"]: allowedTeacherEntities,
  } = groupAllowedEntitiesByPermissions(user, entities, [
    "view_students",
    "view_teachers",
  ]);

  const allowedStudentEntitiesIDS = mapBy(allowedStudentEntities, "id");
  const entitiesIDS = mapBy(entities, "id") || [];

  const [
    students,
    latestStudents,
    latestTeachers,
    userCounts,
    assignmentsCount,
    groupsCount,
  ] = await Promise.all([
    getUsers(
      { type: "student", "entities.id": { $in: allowedStudentEntitiesIDS } },
      10,
      { averageLevel: -1 },
      { _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
    ),
    getUsers(
      { type: "student", "entities.id": { $in: allowedStudentEntitiesIDS } },
      10,
      { registrationDate: -1 },
      { _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
    ),
    getUsers(
      {
        type: "teacher",
        "entities.id": { $in: mapBy(allowedTeacherEntities, "id") },
      },
      10,
      { registrationDate: -1 },
      { _id: 0, id: 1, name: 1, email: 1, profilePicture: 1 }
    ),
    countAllowedUsers(user, entities),
    countEntitiesAssignments(entitiesIDS, {
      archived: { $ne: true },
    }),
    countGroupsByEntities(entitiesIDS),
  ]);

  return {
    props: serialize({
      user,
      students,
      latestStudents,
      latestTeachers,
      userCounts,
      entities,
      assignmentsCount,
      groupsCount,
    }),
  };
}, sessionOptions);

export default function Dashboard({
  user,
  students,
  latestStudents,
  latestTeachers,
  userCounts,
  entities,
  assignmentsCount,
  stats = [],
  groupsCount,
}: Props) {
  const totalCount = useMemo(
    () =>
      userCounts.corporate +
      userCounts.mastercorporate +
      userCounts.student +
      userCounts.teacher,
    [userCounts]
  );

  const totalLicenses = useMemo(
    () =>
      entities.reduce(
        (acc, curr) => acc + parseInt(curr.licenses.toString()),
        0
      ),
    [entities]
  );

  const allowedEntityStatistics = useAllowedEntities(
    user,
    entities,
    "view_entity_statistics"
  );
  const allowedStudentPerformance = useAllowedEntities(
    user,
    entities,
    "view_student_performance"
  );

  const router = useRouter();

  return (
    <>
      <Head>
        <title>EnCoach</title>
        <meta
          name="description"
          content="A training platform for the IELTS exam provided by the Muscat Training Institute and developed by eCrop."
        />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <ToastContainer />
      <>
        <div className="w-full flex flex-col gap-4">
          {entities.length > 0 && (
            <div className="w-fit self-end bg-neutral-200 px-2 rounded-lg py-1">
              <b>{mapBy(entities, "label")?.join(", ")}</b>
            </div>
          )}
          <section className="grid grid-cols-5 -md:grid-cols-2 place-items-center gap-4 text-center">
            <IconCard
              onClick={() => router.push("/users?type=student")}
              Icon={BsPersonFill}
              label="Students"
              value={userCounts.student}
              color="purple"
            />
            <IconCard
              onClick={() => router.push("/users?type=teacher")}
              Icon={BsPencilSquare}
              label="Teachers"
              value={userCounts.teacher}
              color="purple"
            />
            <IconCard
              onClick={() => router.push("/classrooms")}
              Icon={BsPeople}
              label="Classrooms"
              value={groupsCount}
              color="purple"
            />
            <IconCard
              Icon={BsPeopleFill}
              onClick={() => router.push("/entities")}
              label="Entities"
              value={`${entities.length} - ${totalCount}/${totalLicenses}`}
              color="purple"
            />
            {allowedEntityStatistics.length > 0 && (
              <IconCard
                Icon={BsPersonFillGear}
                onClick={() => router.push("/statistical")}
                label="Entity Statistics"
                value={allowedEntityStatistics.length}
                color="purple"
              />
            )}
            {allowedStudentPerformance.length > 0 && (
              <IconCard
                Icon={BsPersonFillGear}
                onClick={() => router.push("/users/performance")}
                label="Student Performance"
                value={userCounts.student}
                color="purple"
              />
            )}
            <IconCard
              Icon={BsClock}
              label="Expiration Date"
              value={
                user.subscriptionExpirationDate
                  ? moment(user.subscriptionExpirationDate).format("DD/MM/yyyy")
                  : "Unlimited"
              }
              color="rose"
            />
            <IconCard
              Icon={BsEnvelopePaper}
              className="col-span-2"
              onClick={() => router.push("/assignments")}
              label="Assignments"
              value={assignmentsCount}
              color="purple"
            />
          </section>
        </div>

        <section className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full justify-between">
          <UserDisplayList users={latestStudents} title="Latest Students" />
          <UserDisplayList users={latestTeachers} title="Latest Teachers" />
          <UserDisplayList users={students} title="Highest level students" />
          <UserDisplayList
            users={students.sort(
              (a, b) =>
                Object.keys(groupByExam(filterBy(stats, "user", b))).length -
                Object.keys(groupByExam(filterBy(stats, "user", a))).length
            )}
            title="Highest exam count students"
          />
        </section>
      </>
    </>
  );
}
