/* eslint-disable @next/next/no-img-element */
import AssignmentCard from "@/components/High/AssignmentCard";
import Layout from "@/components/High/Layout";
import Button from "@/components/Low/Button";
import Separator from "@/components/Low/Separator";
import ProfileSummary from "@/components/ProfileSummary";
import { Session } from "@/hooks/useSessions";
import { Grading } from "@/interfaces";
import { EntityWithRoles } from "@/interfaces/entity";
import { Exam } from "@/interfaces/exam";
import { InviteWithEntity } from "@/interfaces/invite";
import { Assignment } from "@/interfaces/results";
import { Stat, User } from "@/interfaces/user";
import { sessionOptions } from "@/lib/session";
import useExamStore from "@/stores/examStore";
import { filterBy, findBy, mapBy, redirect, serialize } from "@/utils";
import { requestUser } from "@/utils/api";
import { activeAssignmentFilter } from "@/utils/assignments";
import { getAssignmentsByAssignee } from "@/utils/assignments.be";
import { getEntitiesWithRoles } from "@/utils/entities.be";
import { getExamsByIds } from "@/utils/exams.be";
import { sortByModule } from "@/utils/moduleUtils";
import { checkAccess } from "@/utils/permissions";
import { getSessionsByUser } from "@/utils/sessions.be";
import axios from "axios";
import clsx from "clsx";
import { withIronSessionSsr } from "iron-session/next";
import { uniqBy } from "lodash";
import moment from "moment";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMemo, useState } from "react";
import { BsArrowRepeat } from "react-icons/bs";
import { ToastContainer } from "react-toastify";

interface Props {
	user: User;
	entities: EntityWithRoles[];
	assignments: Assignment[];
	stats: Stat[];
	exams: Exam[];
	sessions: Session[];
	invites: InviteWithEntity[];
	grading: Grading;
}

export const getServerSideProps = withIronSessionSsr(async ({ req, res }) => {
	const user = await requestUser(req, res)
	const destination = Buffer.from(req.url || "/").toString("base64")
	if (!user) return redirect(`/login?destination=${destination}`)

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

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

	const entities = await getEntitiesWithRoles(entityIDS);
	const assignments = await getAssignmentsByAssignee(user.id, { archived: { $ne: true } });
	const sessions = await getSessionsByUser(user.id, 0, { "assignment.id": { $in: mapBy(assignments, 'id') } });

	const examIDs = uniqBy(
		assignments.flatMap((a) =>
			filterBy(a.exams, 'assignee', user.id).map((e) => ({ module: e.module, id: e.id, key: `${e.module}_${e.id}` })),
		),
		"key",
	);
	const exams = await getExamsByIds(examIDs);

	return { props: serialize({ user, entities, assignments, exams, sessions }) };
}, sessionOptions);

const destination = Buffer.from("/official-exam").toString("base64")

export default function OfficialExam({ user, entities, assignments, sessions, exams }: Props) {
	const [isLoading, setIsLoading] = useState(false)

	const router = useRouter();
	const state = useExamStore((state) => state);
	const reload = () => {
		setIsLoading(true)
		router.replace(router.asPath)
		setTimeout(() => setIsLoading(false), 500)
	}

	const startAssignment = (assignment: Assignment) => {
		const assignmentExams = exams.filter(e => {
			const exam = findBy(assignment.exams, 'id', e.id)
			return !!exam && exam.module === e.module
		})

		if (assignmentExams.every((x) => !!x)) {
			state.setUserSolutions([]);
			state.setShowSolutions(false);
			state.setExams(assignmentExams.sort(sortByModule));
			state.setSelectedModules(mapBy(assignmentExams.sort(sortByModule), 'module'));
			state.setAssignment(assignment);

			router.push(`/exam?assignment=${assignment.id}&destination=${destination}`);
		}
	};

	const loadSession = async (session: Session) => {
		state.setShuffles(session.userSolutions.map((x) => ({ exerciseID: x.exercise, shuffles: x.shuffleMaps ? x.shuffleMaps : [] })));
		state.setSelectedModules(session.selectedModules);
		state.setExam(session.exam);
		state.setExams(session.exams);
		state.setSessionId(session.sessionId);
		state.setAssignment(session.assignment);
		state.setExerciseIndex(session.exerciseIndex);
		state.setPartIndex(session.partIndex);
		state.setModuleIndex(session.moduleIndex);
		state.setTimeSpent(session.timeSpent);
		state.setUserSolutions(session.userSolutions);
		state.setShowSolutions(false);
		state.setQuestionIndex(session.questionIndex);

		router.push(`/exam?assignment=${session.assignment?.id}&destination=${destination}`);
	};

	const logout = async () => {
		axios.post("/api/logout").finally(() => {
			setTimeout(() => router.reload(), 500);
		});
	};

	const studentAssignments = useMemo(() => assignments.filter(activeAssignmentFilter), [assignments]);
	const assignmentSessions = useMemo(() => sessions.filter(s => mapBy(studentAssignments, 'id').includes(s.assignment?.id || "")), [sessions, studentAssignments])

	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 />
			<Layout user={user} hideSidebar>
				{entities.length > 0 && (
					<div className="absolute right-4 top-4 rounded-lg bg-neutral-200 px-2 py-1">
						<b>{mapBy(entities, "label")?.join(", ")}</b>
					</div>
				)}

				<ProfileSummary user={user} items={[]} removeLevel />

				<Separator />

				{/* Assignments */}
				<section className="flex flex-col gap-1 md:gap-3">
					<div
						onClick={reload}
						className="text-mti-purple-light hover:text-mti-purple-dark flex cursor-pointer items-center gap-2 transition duration-300 ease-in-out">
						<span className="text-mti-black text-lg font-bold">Assignments</span>
						<BsArrowRepeat className={clsx("text-xl", isLoading && "animate-spin")} />
					</div>
					<span className="text-mti-gray-taupe scrollbar-hide flex gap-8 overflow-x-scroll">
						{studentAssignments.length === 0 && "Assignments will appear here. It seems that for now there are no assignments for you."}
						{studentAssignments
							.sort((a, b) => moment(a.startDate).diff(b.startDate))
							.map((a) =>
								<AssignmentCard
									key={a.id}
									assignment={a}
									user={user}
									session={assignmentSessions.find(s => s.assignment?.id === a.id)}
									startAssignment={startAssignment}
									resumeAssignment={loadSession}
								/>
							)}
					</span>
				</section>

				<Button onClick={logout} variant="outline" color="red" className="max-w-[200px] w-full absolute bottom-8 left-8">Sign out</Button>
			</Layout>
		</>
	);
}
