import Separator from "@/components/Low/Separator";
import AssignmentCard from "@/components/AssignmentCard";
import { useAllowedEntities } from "@/hooks/useEntityPermissions";
import { useListSearch } from "@/hooks/useListSearch";
import usePagination from "@/hooks/usePagination";
import { EntityWithRoles } from "@/interfaces/entity";
import { Assignment } from "@/interfaces/results";
import { User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import { findBy, mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import {
  activeAssignmentFilter,
  archivedAssignmentFilter,
  futureAssignmentFilter,
  pastAssignmentFilter,
  startHasExpiredAssignmentFilter,
} from "@/utils/assignments";
import { getAssignments, getEntitiesAssignments } from "@/utils/assignments.be";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { checkAccess, findAllowedEntities } from "@/utils/permissions";
import { getEntitiesUsers, getUsers } from "@/utils/users.be";
import { withIronSessionSsr } from "iron-session/next";
import Head from "next/head";
import Link from "next/link";
import { useRouter } from "next/router";
import { useMemo } from "react";
import { BsChevronLeft, BsPlus } from "react-icons/bs";

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

  if (
    !checkAccess(user, [
      "admin",
      "developer",
      "corporate",
      "teacher",
      "mastercorporate",
    ])
  )
    return redirect("/");
  const isAdmin = checkAccess(user, ["developer", "admin"]);
  const entityIDS = mapBy(user.entities, "id") || [];
  const entities = await (isAdmin
    ? getEntitiesWithRoles()
    : getEntitiesWithRoles(entityIDS));

  const allowedEntities = findAllowedEntities(
    user,
    entities,
    "view_assignments"
  );
  const [users, assignments] = await Promise.all([
    await (isAdmin
      ? getUsers({}, 0, {}, { _id: 0, id: 1, name: 1 })
      : getEntitiesUsers(mapBy(allowedEntities, "id"), {}, 0, {
          _id: 0,
          id: 1,
          name: 1,
        })),
    await (isAdmin
      ? getAssignments()
      : getEntitiesAssignments(mapBy(allowedEntities, "id"))),
  ]);

  return {
    props: serialize({ user, users, entities: allowedEntities, assignments }),
  };
}, sessionOptions);

const SEARCH_FIELDS = [["name"]];

interface Props {
  assignments: Assignment[];
  entities: EntityWithRoles[];
  user: User;
  users: User[];
}

export default function AssignmentsPage({
  assignments,
  entities,
  user,
  users,
}: Props) {
  const entitiesAllowCreate = useAllowedEntities(
    user,
    entities,
    "create_assignment"
  );
  const entitiesAllowEdit = useAllowedEntities(
    user,
    entities,
    "edit_assignment"
  );
  const entitiesAllowArchive = useAllowedEntities(
    user,
    entities,
    "archive_assignment"
  );

  const activeAssignments = useMemo(
    () => assignments.filter(activeAssignmentFilter),
    [assignments]
  );
  const plannedAssignments = useMemo(
    () => assignments.filter(futureAssignmentFilter),
    [assignments]
  );
  const pastAssignments = useMemo(
    () => assignments.filter(pastAssignmentFilter),
    [assignments]
  );
  const startExpiredAssignments = useMemo(
    () => assignments.filter(startHasExpiredAssignmentFilter),
    [assignments]
  );
  const archivedAssignments = useMemo(
    () => assignments.filter(archivedAssignmentFilter),
    [assignments]
  );

  const router = useRouter();

  const { rows: activeRows, renderSearch: renderActive } = useListSearch(
    SEARCH_FIELDS,
    activeAssignments
  );
  const { rows: plannedRows, renderSearch: renderPlanned } = useListSearch(
    SEARCH_FIELDS,
    plannedAssignments
  );
  const { rows: pastRows, renderSearch: renderPast } = useListSearch(
    SEARCH_FIELDS,
    pastAssignments
  );
  const { rows: expiredRows, renderSearch: renderExpired } = useListSearch(
    SEARCH_FIELDS,
    startExpiredAssignments
  );
  const { rows: archivedRows, renderSearch: renderArchived } = useListSearch(
    SEARCH_FIELDS,
    archivedAssignments
  );

  const { items: activeItems, renderMinimal: paginationActive } = usePagination(
    activeRows,
    16
  );
  const { items: plannedItems, renderMinimal: paginationPlanned } =
    usePagination(plannedRows, 16);
  const { items: pastItems, renderMinimal: paginationPast } = usePagination(
    pastRows,
    16
  );
  const { items: expiredItems, renderMinimal: paginationExpired } =
    usePagination(expiredRows, 16);
  const { items: archivedItems, renderMinimal: paginationArchived } =
    usePagination(archivedRows, 16);

  return (
    <>
      <Head>
        <title>Assignments | 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>
      <>
        <div className="flex flex-col gap-4">
          <div className="flex items-center gap-2">
            <Link
              href="/dashboard"
              className="text-mti-purple hover:text-mti-purple-dark transition ease-in-out duration-300 text-xl"
            >
              <BsChevronLeft />
            </Link>
            <h2 className="font-bold text-2xl">Assignments</h2>
          </div>
          <Separator />
        </div>
        <div className="flex flex-col gap-2">
          <span className="text-lg font-bold">Active Assignments Status</span>
          <div className="flex items-center gap-4">
            <span>
              <b>Total:</b>{" "}
              {activeAssignments.reduce(
                (acc, curr) => acc + curr.results.length,
                0
              )}
              /
              {activeAssignments.reduce(
                (acc, curr) => curr.exams.length + acc,
                0
              )}
            </span>
          </div>
        </div>

        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Active Assignments ({activeAssignments.length})
          </h2>
          <div className="w-full flex items-center gap-4">
            {renderActive()}
            {paginationActive()}
          </div>
          <div className="flex flex-wrap gap-2">
            {activeItems.map((a) => (
              <AssignmentCard
                {...a}
                entityObj={findBy(entities, "id", a.entity)}
                users={users}
                onClick={() => router.push(`/assignments/${a.id}`)}
                key={a.id}
              />
            ))}
          </div>
        </section>

        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Planned Assignments ({plannedAssignments.length})
          </h2>
          <div className="w-full flex items-center gap-4">
            {renderPlanned()}
            {paginationPlanned()}
          </div>
          <div className="flex flex-wrap gap-2">
            <Link
              href={
                entitiesAllowCreate.length > 0 ? "/assignments/creator" : ""
              }
              className="w-[250px] h-[200px] flex flex-col gap-2 items-center justify-center bg-white hover:bg-mti-purple-ultralight text-mti-purple-light hover:text-mti-purple-dark border border-mti-gray-platinum hover:drop-shadow p-4 cursor-pointer rounded-xl transition ease-in-out duration-300"
            >
              <BsPlus className="text-6xl" />
              <span className="text-lg">New Assignment</span>
            </Link>
            {plannedItems.map((a) => (
              <AssignmentCard
                {...a}
                users={users}
                entityObj={findBy(entities, "id", a.entity)}
                onClick={
                  mapBy(entitiesAllowEdit, "id").includes(a.entity || "")
                    ? () => router.push(`/assignments/creator/${a.id}`)
                    : () => router.push(`/assignments/${a.id}`)
                }
                key={a.id}
              />
            ))}
          </div>
        </section>

        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Past Assignments ({pastAssignments.length})
          </h2>
          <div className="w-full flex items-center gap-4">
            {renderPast()}
            {paginationPast()}
          </div>
          <div className="flex flex-wrap gap-2">
            {pastItems.map((a) => (
              <AssignmentCard
                {...a}
                users={users}
                entityObj={findBy(entities, "id", a.entity)}
                onClick={() => router.push(`/assignments/${a.id}`)}
                key={a.id}
                allowDownload
                allowArchive={mapBy(entitiesAllowArchive, "id").includes(
                  a.entity || ""
                )}
                allowExcelDownload
              />
            ))}
          </div>
        </section>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Assignments start expired ({startExpiredAssignments.length})
          </h2>
          <div className="w-full flex items-center gap-4">
            {renderExpired()}
            {paginationExpired()}
          </div>
          <div className="flex flex-wrap gap-2">
            {expiredItems.map((a) => (
              <AssignmentCard
                {...a}
                users={users}
                entityObj={findBy(entities, "id", a.entity)}
                onClick={() => router.push(`/assignments/${a.id}`)}
                key={a.id}
                allowDownload
                allowArchive={mapBy(entitiesAllowArchive, "id").includes(
                  a.entity || ""
                )}
                allowExcelDownload
              />
            ))}
          </div>
        </section>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Archived Assignments ({archivedAssignments.length})
          </h2>
          <div className="w-full flex items-center gap-4">
            {renderArchived()}
            {paginationArchived()}
          </div>
          <div className="flex flex-wrap gap-2">
            {archivedItems.map((a) => (
              <AssignmentCard
                {...a}
                users={users}
                onClick={() => router.push(`/assignments/${a.id}`)}
                key={a.id}
                entityObj={findBy(entities, "id", a.entity)}
                allowDownload
                allowUnarchive
                allowExcelDownload
              />
            ))}
          </div>
        </section>
      </>
    </>
  );
}
