/* eslint-disable @next/next/no-img-element */
import {CorporateUser, Group, Stat, User} from "@/interfaces/user";
import {useState} from "react";
import {BsFilter} from "react-icons/bs";

import {averageLevelCalculator, calculateBandScore} from "@/utils/score";
import {groupByExam} from "@/utils/stats";
import {createColumnHelper} from "@tanstack/react-table";
import List from "@/components/List";
import {getUserCompanyName} from "@/resources/user";
import Checkbox from "@/components/Low/Checkbox";
import {uniqBy} from "lodash";
import Select from "@/components/Low/Select";
import {Popover, PopoverContent, PopoverTrigger} from "@/components/ui/popover";

type StudentPerformanceItem = User & {
	corporate?: CorporateUser;
	group?: Group;
};

const StudentPerformanceList = ({items, stats, users, groups}: {items: StudentPerformanceItem[]; stats: Stat[]; users: User[]; groups: Group[]}) => {
	const [isShowingAmount, setIsShowingAmount] = useState(false);
	const [availableCorporates] = useState(
		uniqBy(
			items.map((x) => x.corporate),
			"id",
		),
	);
	const [availableGroups] = useState(
		uniqBy(
			items.map((x) => x.group),
			"id",
		),
	);

	const [selectedCorporate, setSelectedCorporate] = useState<CorporateUser | null | undefined>(null);
	const [selectedGroup, setSelectedGroup] = useState<Group | null | undefined>(null);

	const columnHelper = createColumnHelper<StudentPerformanceItem>();

	const columns = [
		columnHelper.accessor("name", {
			header: "Student Name",
			cell: (info) => info.getValue(),
		}),
		columnHelper.accessor("email", {
			header: "E-mail",
			cell: (info) => info.getValue(),
		}),
		columnHelper.accessor("demographicInformation.passport_id", {
			header: "ID",
			cell: (info) => info.getValue() || "N/A",
		}),
		columnHelper.accessor("group", {
			header: "Group",
			cell: (info) => info.getValue()?.name || "N/A",
		}),
		columnHelper.accessor("corporate", {
			header: "Corporate",
			cell: (info) => (!!info.getValue() ? getUserCompanyName(info.getValue() as User, users, groups) : "N/A"),
		}),
		columnHelper.accessor("levels.reading", {
			header: "Reading",
			cell: (info) =>
				!isShowingAmount
					? calculateBandScore(
							stats
								.filter((x) => x.module === "reading" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.correct, 0),
							stats
								.filter((x) => x.module === "reading" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.total, 0),
							"level",
							info.row.original.focus || "academic",
					  ) || 0
					: `${Object.keys(groupByExam(stats.filter((x) => x.module === "reading" && x.user === info.row.original.id))).length} exams`,
		}),
		columnHelper.accessor("levels.listening", {
			header: "Listening",
			cell: (info) =>
				!isShowingAmount
					? calculateBandScore(
							stats
								.filter((x) => x.module === "listening" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.correct, 0),
							stats
								.filter((x) => x.module === "listening" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.total, 0),
							"level",
							info.row.original.focus || "academic",
					  ) || 0
					: `${Object.keys(groupByExam(stats.filter((x) => x.module === "listening" && x.user === info.row.original.id))).length} exams`,
		}),
		columnHelper.accessor("levels.writing", {
			header: "Writing",
			cell: (info) =>
				!isShowingAmount
					? calculateBandScore(
							stats
								.filter((x) => x.module === "writing" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.correct, 0),
							stats
								.filter((x) => x.module === "writing" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.total, 0),
							"level",
							info.row.original.focus || "academic",
					  ) || 0
					: `${Object.keys(groupByExam(stats.filter((x) => x.module === "writing" && x.user === info.row.original.id))).length} exams`,
		}),
		columnHelper.accessor("levels.speaking", {
			header: "Speaking",
			cell: (info) =>
				!isShowingAmount
					? calculateBandScore(
							stats
								.filter((x) => x.module === "speaking" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.correct, 0),
							stats
								.filter((x) => x.module === "speaking" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.total, 0),
							"level",
							info.row.original.focus || "academic",
					  ) || 0
					: `${Object.keys(groupByExam(stats.filter((x) => x.module === "speaking" && x.user === info.row.original.id))).length} exams`,
		}),
		columnHelper.accessor("levels.level", {
			header: "Level",
			cell: (info) =>
				!isShowingAmount
					? calculateBandScore(
							stats
								.filter((x) => x.module === "level" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.correct, 0),
							stats
								.filter((x) => x.module === "level" && x.user === info.row.original.id)
								.reduce((acc, curr) => acc + curr.score.total, 0),
							"level",
							info.row.original.focus || "academic",
					  ) || 0
					: `${Object.keys(groupByExam(stats.filter((x) => x.module === "level" && x.user === info.row.original.id))).length} exams`,
		}),
		columnHelper.accessor("levels", {
			id: "overall_level",
			header: "Overall",
			cell: (info) =>
				!isShowingAmount
					? averageLevelCalculator(
							users,
							stats.filter((x) => x.user === info.row.original.id),
					  ).toFixed(1)
					: `${Object.keys(groupByExam(stats.filter((x) => x.user === info.row.original.id))).length} exams`,
		}),
	];

	const filterUsers = (data: StudentPerformanceItem[]) => {
		const filterByCorporate = (item: StudentPerformanceItem) => item.corporate?.id === selectedCorporate?.id;
		const filterByGroup = (item: StudentPerformanceItem) => item.group?.id === selectedGroup?.id;

		const filters: ((item: StudentPerformanceItem) => boolean)[] = [];
		if (selectedCorporate !== null) filters.push(filterByCorporate);
		if (selectedGroup !== null) filters.push(filterByGroup);

		return filters.reduce((d, f) => d.filter(f), data);
	};

	return (
		<div className="flex flex-col gap-4 w-full h-full">
			<div className="w-full flex gap-4 justify-between items-center">
				<Checkbox isChecked={isShowingAmount} onChange={setIsShowingAmount}>
					Show Utilization
				</Checkbox>
				<Popover>
					<PopoverTrigger>
						<div className="flex items-center justify-center p-2 hover:bg-neutral-300/50 rounded-full transition ease-in-out duration-300">
							<BsFilter size={20} />
						</div>
					</PopoverTrigger>
					<PopoverContent className="w-96">
						<div className="flex flex-col gap-4">
							<span className="font-bold text-lg">Filters</span>
							<Select
								options={availableCorporates.map((x) => ({
									value: x?.id || "N/A",
									label: x?.corporateInformation?.companyInformation?.name || x?.name || "N/A",
								}))}
								isClearable
								value={
									selectedCorporate === null
										? null
										: {
												value: selectedCorporate?.id || "N/A",
												label:
													selectedCorporate?.corporateInformation?.companyInformation?.name ||
													selectedCorporate?.name ||
													"N/A",
										  }
								}
								placeholder="Select a Corporate..."
								onChange={(value) =>
									!value
										? setSelectedCorporate(null)
										: setSelectedCorporate(
												value.value === "N/A" ? undefined : availableCorporates.find((x) => x?.id === value.value),
										  )
								}
							/>
							<Select
								options={availableGroups.map((x) => ({
									value: x?.id || "N/A",
									label: x?.name || "N/A",
								}))}
								isClearable
								value={
									selectedGroup === null
										? null
										: {
												value: selectedGroup?.id || "N/A",
												label: selectedGroup?.name || "N/A",
										  }
								}
								placeholder="Select a Group..."
								onChange={(value) =>
									!value
										? setSelectedGroup(null)
										: setSelectedGroup(value.value === "N/A" ? undefined : availableGroups.find((x) => x?.id === value.value))
								}
							/>
						</div>
					</PopoverContent>
				</Popover>
			</div>
			<List<StudentPerformanceItem>
				data={filterUsers(
					items.sort(
						(a, b) =>
							averageLevelCalculator(
								users,
								stats.filter((x) => x.user === b.id),
							) -
							averageLevelCalculator(
								users,
								stats.filter((x) => x.user === a.id),
							),
					),
				)}
				columns={columns}
			/>
		</div>
	);
};

export default StudentPerformanceList;
