/* eslint-disable @next/next/no-img-element */
import UserDisplayList from "@/components/UserDisplayList";
import IconCard from "@/components/IconCard";
import { EntityWithRoles } from "@/interfaces/entity";
import { Assignment } from "@/interfaces/results";
import { Group, Stat, User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import { dateSorter, filterBy, mapBy, redirect, serialize } from "@/utils";
import { getEntitiesAssignments } from "@/utils/assignments.be";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { getGroupsByEntities } from "@/utils/groups.be";
import { checkAccess, findAllowedEntities } from "@/utils/permissions";
import { calculateAverageLevel } from "@/utils/score";
import { groupByExam } from "@/utils/stats";
import { getStatsByUsers } from "@/utils/stats.be";
import { withIronSessionSsr } from "iron-session/next";
import Head from "next/head";
import { useRouter } from "next/router";
import {
  BsEnvelopePaper,
  BsPeople,
  BsPersonFill,
  BsPersonFillGear,
} from "react-icons/bs";
import { ToastContainer } from "react-toastify";
import { requestUser } from "@/utils/api";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
import { getEntitiesUsers } from "@/utils/users.be";
import { isAdmin } from "@/utils/users";
import { useMemo } from "react";

interface Props {
  user: User;
  students: User[];
  entities: EntityWithRoles[];
  assignments: Assignment[];
  stats: Stat[];
  groups: Group[];
}

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", "teacher"]))
    return redirect("/");

  const entityIDS = mapBy(user.entities, "id") || [];

  const entities = await getEntitiesWithRoles(
    isAdmin(user) ? undefined : entityIDS
  );

  const filteredEntities = findAllowedEntities(user, entities, "view_students");

  const [students, assignments, groups] = await Promise.all([
    getEntitiesUsers(
      mapBy(filteredEntities, "id"),
      {
        type: "student",
      },
      0,
      {
        _id: 0,
        id: 1,
        name: 1,
        email: 1,
        profilePicture: 1,
        levels: 1,
        registrationDate: 1,
      }
    ),
    getEntitiesAssignments(entityIDS),
    getGroupsByEntities(entityIDS),
  ]);

  const stats = await getStatsByUsers(students.map((u) => u.id));

  return {
    props: serialize({ user, students, entities, assignments, stats, groups }),
  };
}, sessionOptions);

export default function Dashboard({
  user,
  students,
  entities,
  assignments,
  stats,
  groups,
}: Props) {
  const router = useRouter();

  const allowedEntityStatistics = useAllowedEntities(
    user,
    entities,
    "view_entity_statistics"
  );
  const allowedStudentPerformance = useAllowedEntities(
    user,
    entities,
    "view_student_performance"
  );
  const entitiesLabels = useMemo(
    () => mapBy(entities, "label")?.join(", "),
    [entities]
  );

  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>{entitiesLabels}</b>
            </div>
          )}
          <section className="grid grid-cols-5 -md:grid-cols-2 place-items-center gap-4 text-center">
            <IconCard
              Icon={BsPersonFill}
              onClick={() => router.push("/users?type=student")}
              label="Students"
              value={students.length}
              color="purple"
            />
            <IconCard
              onClick={() => router.push("/classrooms")}
              Icon={BsPeople}
              label="Classrooms"
              value={groups.length}
              color="purple"
            />
            {allowedStudentPerformance.length > 0 && (
              <IconCard
                Icon={BsPersonFillGear}
                onClick={() => router.push("/users/performance")}
                label="Student Performance"
                value={students.length}
                color="purple"
              />
            )}
            {allowedEntityStatistics.length > 0 && (
              <IconCard
                Icon={BsPersonFillGear}
                onClick={() => router.push("/statistical")}
                label="Entity Statistics"
                value={allowedEntityStatistics.length}
                color="purple"
              />
            )}
            <IconCard
              Icon={BsEnvelopePaper}
              onClick={() => router.push("/assignments")}
              label="Assignments"
              value={assignments.filter((a) => !a.archived).length}
              color="purple"
            />
          </section>
        </div>

        <section className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full justify-between">
          <UserDisplayList
            users={students.sort((a, b) =>
              dateSorter(a, b, "desc", "registrationDate")
            )}
            title="Latest Students"
          />
          <UserDisplayList
            users={students.sort(
              (a, b) =>
                calculateAverageLevel(b.levels) -
                calculateAverageLevel(a.levels)
            )}
            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>
      </>
    </>
  );
}
