/* eslint-disable @next/next/no-img-element */
import Modal from "@/components/Modal";
import useStats from "@/hooks/useStats";
import useUsers from "@/hooks/useUsers";
import { CorporateUser, Group, Stat, User } from "@/interfaces/user";
import UserList from "@/pages/(admin)/Lists/UserList";
import { dateSorter } from "@/utils";
import moment from "moment";
import { useEffect, useState } from "react";
import {
  BsArrowLeft,
  BsArrowRepeat,
  BsClipboard2Data,
  BsClipboard2DataFill,
  BsClipboard2Heart,
  BsClipboard2X,
  BsClipboardPulse,
  BsClock,
  BsEnvelopePaper,
  BsGlobeCentralSouthAsia,
  BsPaperclip,
  BsPeople,
  BsPerson,
  BsPersonAdd,
  BsPersonFill,
  BsPersonFillGear,
  BsPersonGear,
  BsPlus,
  BsRepeat,
  BsRepeat1,
} from "react-icons/bs";
import UserCard from "@/components/UserCard";
import useGroups from "@/hooks/useGroups";
import { calculateAverageLevel, calculateBandScore } from "@/utils/score";
import { MODULE_ARRAY } from "@/utils/moduleUtils";
import { Module } from "@/interfaces";
import { groupByExam } from "@/utils/stats";
import IconCard from "./IconCard";
import GroupList from "@/pages/(admin)/Lists/GroupList";
import useAssignments from "@/hooks/useAssignments";
import { Assignment } from "@/interfaces/results";
import AssignmentCard from "./AssignmentCard";
import Button from "@/components/Low/Button";
import clsx from "clsx";
import ProgressBar from "@/components/Low/ProgressBar";
import AssignmentCreator from "./AssignmentCreator";
import AssignmentView from "./AssignmentView";
import { getUserCorporate } from "@/utils/groups";

interface Props {
  user: User;
}

export default function TeacherDashboard({ user }: Props) {
  const [page, setPage] = useState("");
  const [selectedUser, setSelectedUser] = useState<User>();
  const [showModal, setShowModal] = useState(false);
  const [selectedAssignment, setSelectedAssignment] = useState<Assignment>();
  const [isCreatingAssignment, setIsCreatingAssignment] = useState(false);
  const [corporateUserToShow, setCorporateUserToShow] =
    useState<CorporateUser>();

  const { stats } = useStats();
  const { users, reload } = useUsers();
  const { groups } = useGroups(user.id);
  const {
    assignments,
    isLoading: isAssignmentsLoading,
    reload: reloadAssignments,
  } = useAssignments({ assigner: user.id });

  useEffect(() => {
    setShowModal(!!selectedUser && page === "");
  }, [selectedUser, page]);

  useEffect(() => {
    getUserCorporate(user.id).then(setCorporateUserToShow);
  }, [user]);

  const studentFilter = (user: User) =>
    user.type === "student" &&
    groups.flatMap((g) => g.participants).includes(user.id);

  const getStatsByStudent = (user: User) =>
    stats.filter((s) => s.user === user.id);

  const UserDisplay = (displayUser: User) => (
    <div
      onClick={() => setSelectedUser(displayUser)}
      className="flex w-full p-4 gap-4 items-center hover:bg-mti-purple-ultralight cursor-pointer transition ease-in-out duration-300"
    >
      <img
        src={displayUser.profilePicture}
        alt={displayUser.name}
        className="rounded-full w-10 h-10"
      />
      <div className="flex flex-col gap-1 items-start">
        <span>{displayUser.name}</span>
        <span className="text-sm opacity-75">{displayUser.email}</span>
      </div>
    </div>
  );

  const StudentsList = () => {
    const filter = (x: User) =>
      x.type === "student" &&
      (!!selectedUser
        ? groups
            .filter((g) => g.admin === selectedUser.id)
            .flatMap((g) => g.participants)
            .includes(x.id) || false
        : groups.flatMap((g) => g.participants).includes(x.id));

    return (
      <UserList
        user={user}
        filters={[filter]}
        renderHeader={(total) => (
          <div className="flex flex-col gap-4">
            <div
              onClick={() => setPage("")}
              className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"
            >
              <BsArrowLeft className="text-xl" />
              <span>Back</span>
            </div>
            <h2 className="text-2xl font-semibold">Students ({total})</h2>
          </div>
        )}
      />
    );
  };

  const GroupsList = () => {
    const filter = (x: Group) =>
      x.admin === user.id || x.participants.includes(user.id);

    return (
      <>
        <div className="flex flex-col gap-4">
          <div
            onClick={() => setPage("")}
            className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"
          >
            <BsArrowLeft className="text-xl" />
            <span>Back</span>
          </div>
          <h2 className="text-2xl font-semibold">
            Groups ({groups.filter(filter).length})
          </h2>
        </div>

        <GroupList user={user} />
      </>
    );
  };

  const averageLevelCalculator = (studentStats: Stat[]) => {
    const formattedStats = studentStats
      .map((s) => ({
        focus: users.find((u) => u.id === s.user)?.focus,
        score: s.score,
        module: s.module,
      }))
      .filter((f) => !!f.focus);
    const bandScores = formattedStats.map((s) => ({
      module: s.module,
      level: calculateBandScore(
        s.score.correct,
        s.score.total,
        s.module,
        s.focus!
      ),
    }));

    const levels: { [key in Module]: number } = {
      reading: 0,
      listening: 0,
      writing: 0,
      speaking: 0,
      level: 0,
    };
    bandScores.forEach((b) => (levels[b.module] += b.level));

    return calculateAverageLevel(levels);
  };

  const AssignmentsPage = () => {
    const activeFilter = (a: Assignment) =>
      moment(a.endDate).isAfter(moment()) &&
      moment(a.startDate).isBefore(moment()) &&
      a.assignees.length > a.results.length;
    const pastFilter = (a: Assignment) =>
      (moment(a.endDate).isBefore(moment()) ||
        a.assignees.length === a.results.length) &&
      !a.archived;
    const archivedFilter = (a: Assignment) => a.archived;
    const futureFilter = (a: Assignment) =>
      moment(a.startDate).isAfter(moment());

    return (
      <>
        <AssignmentView
          isOpen={!!selectedAssignment && !isCreatingAssignment}
          onClose={() => {
            setSelectedAssignment(undefined);
            setIsCreatingAssignment(false);
            reloadAssignments();
          }}
          assignment={selectedAssignment}
        />
        <AssignmentCreator
          assignment={selectedAssignment}
          groups={groups.filter(
            (x) => x.admin === user.id || x.participants.includes(user.id)
          )}
          users={users.filter(
            (x) =>
              x.type === "student" &&
              (!!selectedUser
                ? groups
                    .filter((g) => g.admin === selectedUser.id)
                    .flatMap((g) => g.participants)
                    .includes(x.id) || false
                : groups.flatMap((g) => g.participants).includes(x.id))
          )}
          assigner={user.id}
          isCreating={isCreatingAssignment}
          cancelCreation={() => {
            setIsCreatingAssignment(false);
            setSelectedAssignment(undefined);
            reloadAssignments();
          }}
        />
        <div className="w-full flex justify-between items-center">
          <div
            onClick={() => setPage("")}
            className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"
          >
            <BsArrowLeft className="text-xl" />
            <span>Back</span>
          </div>
          <div
            onClick={reloadAssignments}
            className="flex gap-2 items-center text-mti-purple-light cursor-pointer hover:text-mti-purple-dark transition ease-in-out duration-300"
          >
            <span>Reload</span>
            <BsArrowRepeat
              className={clsx(
                "text-xl",
                isAssignmentsLoading && "animate-spin"
              )}
            />
          </div>
        </div>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Active Assignments ({assignments.filter(activeFilter).length})
          </h2>
          <div className="flex flex-wrap gap-2">
            {assignments.filter(activeFilter).map((a) => (
              <AssignmentCard
                {...a}
                onClick={() => setSelectedAssignment(a)}
                key={a.id}
              />
            ))}
          </div>
        </section>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Planned Assignments ({assignments.filter(futureFilter).length})
          </h2>
          <div className="flex flex-wrap gap-2">
            <div
              onClick={() => setIsCreatingAssignment(true)}
              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>
            </div>
            {assignments.filter(futureFilter).map((a) => (
              <AssignmentCard
                {...a}
                onClick={() => {
                  setSelectedAssignment(a);
                  setIsCreatingAssignment(true);
                }}
                key={a.id}
              />
            ))}
          </div>
        </section>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Past Assignments ({assignments.filter(pastFilter).length})
          </h2>
          <div className="flex flex-wrap gap-2">
            {assignments.filter(pastFilter).map((a) => (
              <AssignmentCard
                {...a}
                onClick={() => setSelectedAssignment(a)}
                key={a.id}
                allowDownload
                reload={reloadAssignments}
                allowArchive
              />
            ))}
          </div>
        </section>
        <section className="flex flex-col gap-4">
          <h2 className="text-2xl font-semibold">
            Archived Assignments ({assignments.filter(archivedFilter).length})
          </h2>
          <div className="flex flex-wrap gap-2">
            {assignments.filter(archivedFilter).map((a) => (
              <AssignmentCard
                {...a}
                onClick={() => setSelectedAssignment(a)}
                key={a.id}
                allowDownload
                reload={reloadAssignments}
                allowUnarchive
              />
            ))}
          </div>
        </section>
      </>
    );
  };

  const DefaultDashboard = () => (
    <>
      {corporateUserToShow && (
        <div className="absolute top-4 right-4 bg-neutral-200 px-2 rounded-lg py-1">
          Linked to:{" "}
          <b>
            {corporateUserToShow?.corporateInformation?.companyInformation
              .name || corporateUserToShow.name}
          </b>
        </div>
      )}
      <section
        className={clsx(
          "flex -lg:flex-wrap gap-4 items-center -lg:justify-center lg:justify-start text-center",
          !!corporateUserToShow && "mt-12 xl:mt-6"
        )}
      >
        <IconCard
          onClick={() => setPage("students")}
          Icon={BsPersonFill}
          label="Students"
          value={users.filter(studentFilter).length}
          color="purple"
        />
        <IconCard
          Icon={BsClipboard2Data}
          label="Exams Performed"
          value={
            stats.filter((s) =>
              groups.flatMap((g) => g.participants).includes(s.user)
            ).length
          }
          color="purple"
        />
        <IconCard
          Icon={BsPaperclip}
          label="Average Level"
          value={averageLevelCalculator(
            stats.filter((s) =>
              groups.flatMap((g) => g.participants).includes(s.user)
            )
          ).toFixed(1)}
          color="purple"
        />
        <IconCard
          Icon={BsPeople}
          label="Groups"
          value={groups.length}
          color="purple"
          onClick={() => setPage("groups")}
        />
        <div
          onClick={() => setPage("assignments")}
          className="bg-white rounded-xl shadow p-4 flex flex-col gap-4 items-center w-96 h-52 justify-center cursor-pointer hover:shadow-xl transition ease-in-out duration-300"
        >
          <BsEnvelopePaper className="text-6xl text-mti-purple-light" />
          <span className="flex flex-col gap-1 items-center text-xl">
            <span className="text-lg">Assignments</span>
            <span className="font-semibold text-mti-purple-light">
              {assignments.filter((a) => !a.archived).length}
            </span>
          </span>
        </div>
      </section>

      <section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 w-full justify-between">
        <div className="bg-white shadow flex flex-col rounded-xl w-full">
          <span className="p-4">Latest students</span>
          <div className="flex flex-col items-start h-96 overflow-scroll scrollbar-hide">
            {users
              .filter(studentFilter)
              .sort((a, b) => dateSorter(a, b, "desc", "registrationDate"))
              .map((x) => (
                <UserDisplay key={x.id} {...x} />
              ))}
          </div>
        </div>
        <div className="bg-white shadow flex flex-col rounded-xl w-full">
          <span className="p-4">Highest level students</span>
          <div className="flex flex-col items-start h-96 overflow-scroll scrollbar-hide">
            {users
              .filter(studentFilter)
              .sort(
                (a, b) =>
                  calculateAverageLevel(b.levels) -
                  calculateAverageLevel(a.levels)
              )
              .map((x) => (
                <UserDisplay key={x.id} {...x} />
              ))}
          </div>
        </div>
        <div className="bg-white shadow flex flex-col rounded-xl w-full">
          <span className="p-4">Highest exam count students</span>
          <div className="flex flex-col items-start h-96 overflow-scroll scrollbar-hide">
            {users
              .filter(studentFilter)
              .sort(
                (a, b) =>
                  Object.keys(groupByExam(getStatsByStudent(b))).length -
                  Object.keys(groupByExam(getStatsByStudent(a))).length
              )
              .map((x) => (
                <UserDisplay key={x.id} {...x} />
              ))}
          </div>
        </div>
      </section>
    </>
  );

  return (
    <>
      <Modal isOpen={showModal} onClose={() => setSelectedUser(undefined)}>
        <>
          {selectedUser && (
            <div className="w-full flex flex-col gap-8">
              <UserCard
                loggedInUser={user}
                onClose={(shouldReload) => {
                  setSelectedUser(undefined);
                  if (shouldReload) reload();
                }}
                onViewStudents={
                  selectedUser.type === "corporate" ||
                  selectedUser.type === "teacher"
                    ? () => setPage("students")
                    : undefined
                }
                onViewTeachers={
                  selectedUser.type === "corporate"
                    ? () => setPage("teachers")
                    : undefined
                }
                user={selectedUser}
              />
            </div>
          )}
        </>
      </Modal>
      {page === "students" && <StudentsList />}
      {page === "groups" && <GroupsList />}
      {page === "assignments" && <AssignmentsPage />}
      {page === "" && <DefaultDashboard />}
    </>
  );
}
