import {useEffect, useState} from "react";
import {useRouter} from "next/router";
import axios from "axios";
import {Tab} from "@headlessui/react";
import {AiOutlineFileSearch} from "react-icons/ai";
import {MdOutlinePlaylistAddCheckCircle, MdOutlineSelfImprovement} from "react-icons/md";
import {BsChatLeftDots} from "react-icons/bs";
import Button from "@/components/Low/Button";
import clsx from "clsx";
import Exercise from "@/training/Exercise";
import TrainingScore from "@/training/TrainingScore";
import {ITrainingContent, ITrainingTip} from "@/training/TrainingInterfaces";
import {Stat, User} from "@/interfaces/user";
import Head from "next/head";
import Layout from "@/components/High/Layout";
import {ToastContainer} from "react-toastify";
import {withIronSessionSsr} from "iron-session/next";
import {shouldRedirectHome} from "@/utils/navigation.disabled";
import {sessionOptions} from "@/lib/session";
import qs from "qs";
import StatsGridItem from "@/components/Medium/StatGridItem";
import useExamStore from "@/stores/examStore";
import {usePDFDownload} from "@/hooks/usePDFDownload";
import useAssignments from "@/hooks/useAssignments";
import useUsers from "@/hooks/useUsers";
import Dropdown from "@/components/Dropdown";
import InfiniteCarousel from "@/components/InfiniteCarousel";
import {LuExternalLink} from "react-icons/lu";
import {uniqBy} from "lodash";
import {getExamById} from "@/utils/exams";
import {convertToUserSolutions} from "@/utils/stats";
import {sortByModule} from "@/utils/moduleUtils";

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 TrainingContent: React.FC<{user: User}> = ({user}) => {
	// Record stuff
	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 [trainingContent, setTrainingContent] = useState<ITrainingContent | null>(null);
	const [loading, setLoading] = useState(true);
	const [trainingTips, setTrainingTips] = useState<ITrainingTip[]>([]);
	const [currentTipIndex, setCurrentTipIndex] = useState(0);
	const {assignments} = useAssignments({});
	const {users} = useUsers();

	const router = useRouter();
	const {id} = router.query;

	useEffect(() => {
		const fetchTrainingContent = async () => {
			if (!id || typeof id !== "string") return;

			try {
				setLoading(true);
				const response = await axios.get<ITrainingContent>(`/api/training/${id}`);
				const trainingContent = response.data;

				const withExamsStats = {
					...trainingContent,
					exams: await Promise.all(
						trainingContent.exams.map(async (exam) => {
							const stats = await Promise.all(
								exam.stat_ids.map(async (statId) => {
									const statResponse = await axios.get<Stat>(`/api/stats/${statId}`);
									return statResponse.data;
								}),
							);
							return {...exam, stats};
						}),
					),
				};

				const tips = await axios.get<ITrainingTip[]>("/api/training/walkthrough", {
					params: {ids: trainingContent.tip_ids},
					paramsSerializer: (params) => qs.stringify(params, {arrayFormat: "repeat"}),
				});
				setTrainingTips(tips.data);
				setTrainingContent(withExamsStats);
			} catch (error) {
				router.push("/training");
			} finally {
				setLoading(false);
			}
		};

		fetchTrainingContent();
	}, [id, router]);

	const handleNext = () => {
		setCurrentTipIndex((prevIndex) => prevIndex + 1);
	};

	const handlePrevious = () => {
		setCurrentTipIndex((prevIndex) => prevIndex - 1);
	};

	const goToExam = (examNumber: number) => {
		const stats = trainingContent?.exams[examNumber].stats!;
		const examPromises = uniqBy(stats, "exam").map((stat) => {
			return getExamById(stat.module, stat.exam);
		});

		const {timeSpent, inactivity} = stats[0];

		Promise.all(examPromises).then((exams) => {
			if (exams.every((x) => !!x)) {
				if (!!timeSpent) setTimeSpent(timeSpent);
				if (!!inactivity) setInactivity(inactivity);
				setUserSolutions(convertToUserSolutions(stats));
				setShowSolutions(true);
				setExams(exams.map((x) => x!).sort(sortByModule));
				setSelectedModules(
					exams
						.map((x) => x!)
						.sort(sortByModule)
						.map((x) => x!.module),
				);
				router.push("/exercises");
			}
		});
	};

	return (
		<>
			<Head>
				<title>Training | 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}>
				{loading ? (
					<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>
				) : (
					trainingContent && (
						<div className="flex flex-col gap-8">
							<div className="flex flex-row items-center">
								<span className="bg-gray-200 text-gray-800 px-3 py-0.5 rounded-full font-semibold text-lg mr-2">
									{trainingContent.exams.length}
								</span>
								<span>Exams Selected</span>
							</div>
							<div className="h-[15vh] mb-4">
								<InfiniteCarousel
									height="150px"
									overlay={<LuExternalLink size={20} />}
									overlayFunc={goToExam}
									overlayClassName="bottom-6 right-5 cursor-pointer">
									{trainingContent.exams.map((exam, examIndex) => (
										<StatsGridItem
											key={`exam-${examIndex}`}
											width="380px"
											height="150px"
											examNumber={examIndex + 1}
											stats={exam.stats || []}
											timestamp={exam.date}
											user={user}
											assignments={assignments}
											users={users}
											setExams={setExams}
											setShowSolutions={setShowSolutions}
											setUserSolutions={setUserSolutions}
											setSelectedModules={setSelectedModules}
											setInactivity={setInactivity}
											setTimeSpent={setTimeSpent}
											renderPdfIcon={renderPdfIcon}
										/>
									))}
								</InfiniteCarousel>
							</div>
							<div className="flex flex-col">
								<div className="flex flex-row gap-10 -md:flex-col h-full">
									<div className="flex flex-col rounded-3xl p-6 w-1/2 shadow-training-inset -md:w-full max-h-full">
										<div className="flex flex-row items-center mb-6 gap-1">
											<MdOutlinePlaylistAddCheckCircle color={"#40A1EA"} size={26} />
											<h2 className={`text-xl font-semibold text-[#40A1EA]`}>General Evaluation</h2>
										</div>
										<TrainingScore trainingContent={trainingContent} gridView={false} />
										<div className="w-full h-px bg-[#D9D9D929] my-6"></div>
										<div className="flex flex-row gap-2 items-center mb-6">
											<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
												<mask id="mask0_112_168" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
													<rect width="24" height="24" fill="#D9D9D9" />
												</mask>
												<g mask="url(#mask0_112_168)">
													<path
														d="M4 21C3.45 21 2.97917 20.8042 2.5875 20.4125C2.19583 20.0208 2 19.55 2 19V7H4V19H19V21H4ZM8 17C7.45 17 6.97917 16.8042 6.5875 16.4125C6.19583 16.0208 6 15.55 6 15V3H23V15C23 15.55 22.8042 16.0208 22.4125 16.4125C22.0208 16.8042 21.55 17 21 17H8ZM8 15H21V5H8V15ZM10 12H14V7H10V12ZM15 12H19V10H15V12ZM15 9H19V7H15V9Z"
														fill="#53B2F9"
													/>
												</g>
											</svg>
											<h3 className="text-xl font-semibold text-[#40A1EA]">Performance Breakdown by Exam:</h3>
										</div>
										<ul className="overflow-auto scrollbar-hide flex-grow">
											{trainingContent.exams.flatMap((exam, index) => (
												<li key={index} className="flex flex-col mb-2 bg-[#22E1B30F] p-4 rounded-xl border">
													<div className="flex flex-row font-semibold border-b-2 border-[#D9D9D929] text-[#22E1B3] mb-2">
														<div className="flex items-center border-r-2 border-[#D9D9D929] pr-2">
															<span className="mr-1">Exam</span>
															<span className="font-semibold bg-gray-200 text-gray-800 px-2 rounded-full text-sm">
																{index + 1}
															</span>
														</div>
														<span className="pl-2">{exam.score}%</span>
													</div>
													<div className="flex flex-row items-center gap-2">
														<BsChatLeftDots size={16} />
														<p className="text-sm">{exam.performance_comment}</p>
													</div>
												</li>
											))}
										</ul>
									</div>
									<div className="flex flex-col rounded-3xl p-6 w-1/2 shadow-training-inset -md:w-full">
										<div className="flex flex-col">
											<div className="flex flex-row items-center mb-4 gap-1">
												<AiOutlineFileSearch color="#40A1EA" size={24} />
												<h3 className="text-xl font-semibold text-[#40A1EA]">Identified Weak Areas</h3>
											</div>
											<Tab.Group>
												<div className="flex flex-col gap-4">
													<Tab.List>
														<div className="flex flex-row gap-6 overflow-x-auto pb-1 training-scrollbar">
															{trainingContent.weak_areas.map((x, index) => (
																<Tab
																	key={index}
																	className={({selected}) =>
																		clsx(
																			"text-[#53B2F9] pb-2 border-b-2",
																			"focus:outline-none",
																			selected ? "border-[#1B78BE]" : "border-[#1B78BE0F]",
																		)
																	}>
																	{x.area}
																</Tab>
															))}
														</div>
													</Tab.List>
													<Tab.Panels>
														{trainingContent.weak_areas.map((x, index) => (
															<Tab.Panel key={index} className="p-3 bg-[#FBFBFB] rounded-lg border border-[#0000000F]">
																<p>{x.comment}</p>
															</Tab.Panel>
														))}
													</Tab.Panels>
												</div>
											</Tab.Group>
										</div>
										<div className="w-full h-px bg-[#D9D9D929] my-6"></div>
										<div className="flex flex-row items-center mb-4 gap-1">
											<MdOutlineSelfImprovement color={"#40A1EA"} size={24} />
											<h2 className={`text-xl font-semibold text-[#40A1EA]`}>Subjects that Need Improvement</h2>
										</div>

										<div className="flex flex-grow bg-[#FBFBFB] border rounded-xl p-4">
											<div className="flex flex-col">
												<div className="flex flex-row items-center gap-1 mb-4">
													<div className="flex items-center justify-center w-[48px] h-[48px]">
														<svg
															width="24"
															height="24"
															viewBox="0 0 24 24"
															fill="none"
															xmlns="http://www.w3.org/2000/svg">
															<mask id="mask0_112_445" maskUnits="userSpaceOnUse" x="0" y="0" width="24" height="24">
																<rect width="24" height="24" fill="#D9D9D9" />
															</mask>
															<g mask="url(#mask0_112_445)">
																<path
																	d="M6 17H11V15H6V17ZM16 17H18V15H16V17ZM6 13H11V11H6V13ZM16 13H18V7H16V13ZM6 9H11V7H6V9ZM4 21C3.45 21 2.97917 20.8042 2.5875 20.4125C2.19583 20.0208 2 19.55 2 19V5C2 4.45 2.19583 3.97917 2.5875 3.5875C2.97917 3.19583 3.45 3 4 3H20C20.55 3 21.0208 3.19583 21.4125 3.5875C21.8042 3.97917 22 4.45 22 5V19C22 19.55 21.8042 20.0208 21.4125 20.4125C21.0208 20.8042 20.55 21 20 21H4ZM4 19H20V5H4V19Z"
																	fill="#1C1B1F"
																/>
															</g>
														</svg>
													</div>
													<h3 className="text-lg font-semibold">Detailed Breakdown</h3>
												</div>
												<ul className="flex flex-col flex-grow space-y-4 pb-2 overflow-y-auto scrollbar-hide">
													{trainingContent.exams.map((exam, index) => (
														<li key={index} className="border rounded-lg bg-white">
															<Dropdown
																title={
																	<div className="flex flex-row items-center">
																		<span className="mr-1">Exam</span>
																		<span className="font-semibold bg-gray-200 text-gray-800 px-2 rounded-full text-sm mt-0.5">
																			{index + 1}
																		</span>
																	</div>
																}
																open={index == 0}>
																<span>{exam.detailed_summary}</span>
															</Dropdown>
														</li>
													))}
												</ul>
											</div>
										</div>
									</div>
								</div>
							</div>
							<div className="flex -md:hidden">
								<div className="rounded-3xl p-6 shadow-training-inset w-full">
									<div className="flex flex-col p-10">
										<Exercise key={currentTipIndex} {...trainingTips[currentTipIndex]} />
									</div>
									<div className="self-end flex justify-between w-full gap-8  bottom-8 left-0 px-8">
										<Button
											color="purple"
											variant="outline"
											onClick={handlePrevious}
											disabled={currentTipIndex == 0}
											className="max-w-[200px] self-end w-full">
											Previous
										</Button>
										<Button
											color="purple"
											disabled={currentTipIndex == trainingTips.length - 1}
											onClick={handleNext}
											className="max-w-[200px] self-end w-full">
											Next
										</Button>
									</div>
								</div>
							</div>
						</div>
					)
				)}
			</Layout>
		</>
	);
};

export default TrainingContent;
