/* eslint-disable @next/next/no-img-element */
import Head from "next/head";
import {withIronSessionSsr} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {Stat, User} from "@/interfaces/user";
import {useEffect, useRef, useState} from "react";
import useFilterRecordsByUser from "@/hooks/useFilterRecordsByUser";
import {groupByDate} from "@/utils/stats";
import moment from "moment";
import useUsers from "@/hooks/useUsers";
import useExamStore from "@/stores/examStore";
import {ToastContainer} from "react-toastify";
import Layout from "@/components/High/Layout";
import clsx from "clsx";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import useAssignments from "@/hooks/useAssignments";
import {uuidv4} from "@firebase/util";
import {usePDFDownload} from "@/hooks/usePDFDownload";
import useRecordStore from "@/stores/recordStore";
import StatsGridItem from "@/components/Medium/StatGridItem";
import RecordFilter from "@/components/Medium/RecordFilter";
import {useRouter} from "next/router";
import useTrainingContentStore from "@/stores/trainingContentStore";
import {Assignment} from "@/interfaces/results";
import {getUsers} from "@/utils/users.be";
import {getAssignments, getAssignmentsByAssigner} from "@/utils/assignments.be";
import useGradingSystem from "@/hooks/useGrading";

export const getServerSideProps = withIronSessionSsr(async ({req, res}) => {
	const user = req.session.user;

	if (!user || !user.isVerified) {
		return {
			redirect: {
				destination: "/login",
				permanent: false,
			},
		};
	}

	if (shouldRedirectHome(user)) {
		return {
			redirect: {
				destination: "/",
				permanent: false,
			},
		};
	}

	const users = await getUsers();
	const assignments = await getAssignments();

	return {
		props: {user, users, assignments},
	};
}, sessionOptions);

type Filter = "months" | "weeks" | "days" | "assignments" | undefined;

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

export default function History({user, users, assignments}: Props) {
	const router = useRouter();
	const [statsUserId, setStatsUserId, training, setTraining] = useRecordStore((state) => [
		state.selectedUser,
		state.setSelectedUser,
		state.training,
		state.setTraining,
	]);

	// const [statsUserId, setStatsUserId] = useState<string | undefined>(user.id);
	const [groupedStats, setGroupedStats] = useState<{[key: string]: Stat[]}>();
	const [filter, setFilter] = useState<Filter>();

	const {data: stats, isLoading: isStatsLoading} = useFilterRecordsByUser<Stat[]>(statsUserId || user?.id);
	const {gradingSystem} = useGradingSystem();

	const setExams = useExamStore((state) => state.setExams);
	const setShowSolutions = useExamStore((state) => state.setShowSolutions);
	const setUserSolutions = useExamStore((state) => state.setUserSolutions);
	const setSelectedModules = useExamStore((state) => state.setSelectedModules);
	const setInactivity = useExamStore((state) => state.setInactivity);
	const setTimeSpent = useExamStore((state) => state.setTimeSpent);
	const renderPdfIcon = usePDFDownload("stats");

	useEffect(() => setStatsUserId(user.id), [setStatsUserId, user]);

	useEffect(() => {
		if (stats && !isStatsLoading) {
			setGroupedStats(
				groupByDate(
					stats.filter((x) => {
						if (
							(x.module === "writing" || x.module === "speaking") &&
							!x.isDisabled &&
							!x.solutions.every((y) => Object.keys(y).includes("evaluation"))
						)
							return false;
						return true;
					}),
				),
			);
		}
	}, [stats, isStatsLoading]);

	//   useEffect(() => {
	//     // just set this initially
	//     if (!statsUserId) setStatsUserId(user.id);
	//   }, []);

	const filterStatsByDate = (stats: {[key: string]: Stat[]}) => {
		if (filter && filter !== "assignments") {
			const filterDate = moment()
				.subtract({[filter as string]: 1})
				.format("x");
			const filteredStats: {[key: string]: Stat[]} = {};

			Object.keys(stats).forEach((timestamp) => {
				if (timestamp >= filterDate) filteredStats[timestamp] = stats[timestamp];
			});
			return filteredStats;
		}

		if (filter && filter === "assignments") {
			const filteredStats: {[key: string]: Stat[]} = {};

			Object.keys(stats).forEach((timestamp) => {
				if (stats[timestamp].map((s) => s.assignment === undefined).includes(false))
					filteredStats[timestamp] = [...stats[timestamp].filter((s) => !!s.assignment)];
			});

			return filteredStats;
		}

		return stats;
	};

	const MAX_TRAINING_EXAMS = 10;
	const [selectedTrainingExams, setSelectedTrainingExams] = useState<string[]>([]);
	const setTrainingStats = useTrainingContentStore((state) => state.setStats);

	const handleTrainingContentSubmission = () => {
		if (groupedStats) {
			const groupedStatsByDate = filterStatsByDate(groupedStats);
			const allStats = Object.keys(groupedStatsByDate);
			const selectedStats = selectedTrainingExams.reduce<Record<string, Stat[]>>((accumulator, moduleAndTimestamp) => {
				const timestamp = moduleAndTimestamp.split("-")[1];
				if (allStats.includes(timestamp) && !accumulator.hasOwnProperty(timestamp)) {
					accumulator[timestamp] = groupedStatsByDate[timestamp];
				}
				return accumulator;
			}, {});
			setTrainingStats(Object.values(selectedStats).flat());
			router.push("/training");
		}
	};

	useEffect(() => {
		const handleRouteChange = (url: string) => {
			setTraining(false);
		};
		router.events.on("routeChangeStart", handleRouteChange);
		return () => {
			router.events.off("routeChangeStart", handleRouteChange);
		};
	}, [router.events, setTraining]);

	const customContent = (timestamp: string) => {
		if (!groupedStats) return <></>;

		const dateStats = groupedStats[timestamp];

		return (
			<StatsGridItem
				key={uuidv4()}
				stats={dateStats}
				timestamp={timestamp}
				user={user}
				assignments={assignments}
				users={users}
				training={training}
				selectedTrainingExams={selectedTrainingExams}
				setSelectedTrainingExams={setSelectedTrainingExams}
				maxTrainingExams={MAX_TRAINING_EXAMS}
				setExams={setExams}
				gradingSystem={gradingSystem?.steps}
				setShowSolutions={setShowSolutions}
				setUserSolutions={setUserSolutions}
				setSelectedModules={setSelectedModules}
				setInactivity={setInactivity}
				setTimeSpent={setTimeSpent}
				renderPdfIcon={renderPdfIcon}
			/>
		);
	};

	return (
		<>
			<Head>
				<title>Record | 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 />
			{user && (
				<Layout user={user}>
					<RecordFilter user={user} filterState={{filter: filter, setFilter: setFilter}}>
						{training && (
							<div className="flex flex-row">
								<div className="font-semibold text-2xl mr-4">
									Select up to 10 exercises
									{`(${selectedTrainingExams.length}/${MAX_TRAINING_EXAMS})`}
								</div>
								<button
									className={clsx(
										"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light ml-4 disabled:cursor-not-allowed",
										"transition duration-300 ease-in-out",
									)}
									disabled={selectedTrainingExams.length == 0}
									onClick={handleTrainingContentSubmission}>
									Submit
								</button>
							</div>
						)}
					</RecordFilter>
					{groupedStats && Object.keys(groupedStats).length > 0 && !isStatsLoading && (
						<div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 w-full gap-4 xl:gap-6">
							{Object.keys(filterStatsByDate(groupedStats))
								.sort((a, b) => parseInt(b) - parseInt(a))
								.map(customContent)}
						</div>
					)}
					{groupedStats && Object.keys(groupedStats).length === 0 && !isStatsLoading && (
						<span className="font-semibold ml-1">No record to display...</span>
					)}
					{isStatsLoading && (
						<div className="absolute left-1/2 top-1/2 flex h-fit w-fit -translate-x-1/2 -translate-y-1/2 animate-pulse flex-col items-center gap-12">
							<span className="loading loading-infinity w-32 bg-mti-green-light" />
						</div>
					)}
				</Layout>
			)}
		</>
	);
}
