/* 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 useStats from "@/hooks/useStats";
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 {useRouter} from "next/router";
import Layout from "@/components/High/Layout";
import clsx from "clsx";
import Select from "@/components/Low/Select";
import useGroups from "@/hooks/useGroups";
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 useTrainingContentStore from "@/stores/trainingContentStore";
import StatsGridItem from "@/components/StatGridItem";
import {checkAccess} from "@/utils/permissions";

export const getServerSideProps = withIronSessionSsr(({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,
			},
		};
	}

	return {
		props: {user: req.session.user},
	};
}, sessionOptions);

const defaultSelectableCorporate = {
	value: "",
	label: "All",
};

export default function History({user}: {user: User}) {
	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<"months" | "weeks" | "days" | "assignments">();
	const {assignments} = useAssignments({});

	const {users} = useUsers();
	const {stats, isLoading: isStatsLoading} = useStats(statsUserId || user?.id);
	const {groups: allGroups} = useGroups({});
	const {groups} = useGroups({admin: user?.id, userType: user?.type});

	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");
	const router = useRouter();

	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 toggleFilter = (value: "months" | "weeks" | "days" | "assignments") => {
		setFilter((prev) => (prev === value ? undefined : value));
	};

	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);

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

	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");
		}
	};

	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}
				setShowSolutions={setShowSolutions}
				setUserSolutions={setUserSolutions}
				setSelectedModules={setSelectedModules}
				setInactivity={setInactivity}
				setTimeSpent={setTimeSpent}
				renderPdfIcon={renderPdfIcon}
			/>
		);
	};

	const selectableCorporates = [
		defaultSelectableCorporate,
		...users
			.filter((x) => groups.flatMap((g) => [g.admin, ...g.participants]).includes(x.id))
			.filter((x) => x.type === "corporate")
			.map((x) => ({
				value: x.id,
				label: `${x.name} - ${x.email}`,
			})),
	];

	const [selectedCorporate, setSelectedCorporate] = useState<string>(defaultSelectableCorporate.value);

	const getUsersList = (): User[] => {
		if (selectedCorporate) {
			const selectedCorporateGroups = allGroups.filter((x) => x.admin === selectedCorporate);
			const selectedCorporateGroupsParticipants = selectedCorporateGroups.flatMap((x) => x.participants);

			const userListWithUsers = selectedCorporateGroupsParticipants.map((x) => users.find((y) => y.id === x)) as User[];
			return userListWithUsers.filter((x) => x);
		}

		return user.type !== "mastercorporate" ? users : users.filter((x) => groups.flatMap((g) => [g.admin, ...g.participants]).includes(x.id));
	};

	const corporateFilteredUserList = getUsersList();

	const getSelectedUser = () => {
		if (selectedCorporate) {
			const userInCorporate = corporateFilteredUserList.find((x) => x.id === statsUserId);
			return userInCorporate || corporateFilteredUserList[0];
		}

		return users.find((x) => x.id === statsUserId) || user;
	};

	const selectedUser = getSelectedUser();
	const selectedUserSelectValue = selectedUser
		? {
				value: selectedUser.id,
				label: `${selectedUser.name} - ${selectedUser.email}`,
		  }
		: {
				value: "",
				label: "",
		  };
	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}>
					<div className="w-full flex -xl:flex-col -xl:gap-4 justify-between items-center">
						<div className="xl:w-3/4">
							{checkAccess(user, ["developer", "admin", "mastercorporate"]) && !training && (
								<>
									<label className="font-normal text-base text-mti-gray-dim">Corporate</label>

									<Select
										options={selectableCorporates}
										value={selectableCorporates.find((x) => x.value === selectedCorporate)}
										onChange={(value) => setSelectedCorporate(value?.value || "")}
										styles={{
											menuPortal: (base) => ({...base, zIndex: 9999}),
											option: (styles, state) => ({
												...styles,
												backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
												color: state.isFocused ? "black" : styles.color,
											}),
										}}></Select>
									<label className="font-normal text-base text-mti-gray-dim">User</label>

									<Select
										options={corporateFilteredUserList.map((x) => ({
											value: x.id,
											label: `${x.name} - ${x.email}`,
										}))}
										value={selectedUserSelectValue}
										onChange={(value) => setStatsUserId(value?.value!)}
										styles={{
											menuPortal: (base) => ({...base, zIndex: 9999}),
											option: (styles, state) => ({
												...styles,
												backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
												color: state.isFocused ? "black" : styles.color,
											}),
										}}
									/>
								</>
							)}
							{(user.type === "corporate" || user.type === "teacher") && groups.length > 0 && !training && (
								<>
									<label className="font-normal text-base text-mti-gray-dim">User</label>

									<Select
										options={users
											.filter((x) => groups.flatMap((y) => y.participants).includes(x.id))
											.map((x) => ({
												value: x.id,
												label: `${x.name} - ${x.email}`,
											}))}
										value={selectedUserSelectValue}
										onChange={(value) => setStatsUserId(value?.value!)}
										styles={{
											menuPortal: (base) => ({...base, zIndex: 9999}),
											option: (styles, state) => ({
												...styles,
												backgroundColor: state.isFocused ? "#D5D9F0" : state.isSelected ? "#7872BF" : "white",
												color: state.isFocused ? "black" : styles.color,
											}),
										}}
									/>
								</>
							)}
							{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>
							)}
						</div>
						<div className="flex gap-4 w-full justify-center xl:justify-end">
							<button
								className={clsx(
									"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
									"transition duration-300 ease-in-out",
									filter === "assignments" && "!bg-mti-purple-light !text-white",
								)}
								onClick={() => toggleFilter("assignments")}>
								Assignments
							</button>
							<button
								className={clsx(
									"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
									"transition duration-300 ease-in-out",
									filter === "months" && "!bg-mti-purple-light !text-white",
								)}
								onClick={() => toggleFilter("months")}>
								Last month
							</button>
							<button
								className={clsx(
									"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
									"transition duration-300 ease-in-out",
									filter === "weeks" && "!bg-mti-purple-light !text-white",
								)}
								onClick={() => toggleFilter("weeks")}>
								Last week
							</button>
							<button
								className={clsx(
									"bg-mti-purple-ultralight text-mti-purple px-4 py-2 rounded-full hover:text-white hover:bg-mti-purple-light",
									"transition duration-300 ease-in-out",
									filter === "days" && "!bg-mti-purple-light !text-white",
								)}
								onClick={() => toggleFilter("days")}>
								Last day
							</button>
						</div>
					</div>
					{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>
			)}
		</>
	);
}
