/* eslint-disable @next/next/no-img-element */
import {SpeakingExercise} from "@/interfaces/exam";
import {CommonProps} from ".";
import {Fragment, useEffect, useState} from "react";
import Button from "../Low/Button";
import dynamic from "next/dynamic";
import axios from "axios";
import {speakingReverseMarking} from "@/utils/score";
import {Tab} from "@headlessui/react";
import clsx from "clsx";
import Modal from "../Modal";
import {BsQuestionCircleFill} from "react-icons/bs";
import ReactDiffViewer, {DiffMethod} from "react-diff-viewer";

const Waveform = dynamic(() => import("../Waveform"), {ssr: false});

export default function Speaking({id, type, title, video_url, text, prompts, userSolutions, onNext, onBack}: SpeakingExercise & CommonProps) {
	const [solutionURL, setSolutionURL] = useState<string>();
	const [showDiff, setShowDiff] = useState(false);

	useEffect(() => {
		if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) {
			const solution = userSolutions[0].solution;

			if (solution.startsWith("https://")) return setSolutionURL(solution);
			axios.post(`/api/speaking`, {path: userSolutions[0].solution}, {responseType: "arraybuffer"}).then(({data}) => {
				const blob = new Blob([data], {type: "audio/wav"});
				const url = URL.createObjectURL(blob);

				setSolutionURL(url);
			});
		}
	}, [userSolutions]);

	const tooltips: {[key: string]: string} = {
		"Grammatical Range and Accuracy":
			"Assesses the variety and correctness of grammatical structures used. A higher score indicates a wide range of complex and accurate grammar; a lower score suggests the need for more basic grammar practice.",
		"Fluency and Coherence":
			"Evaluates smoothness and logical flow of speech. A higher score means natural, effortless speech and clear idea progression; a lower score indicates frequent pauses and difficulty in maintaining coherence.",
		Pronunciation:
			"Measures clarity and accuracy of spoken words. A higher score reflects clear, well-articulated speech with correct intonation; a lower score shows challenges in being understood.",
		"Lexical Resource":
			"Looks at the range and appropriateness of vocabulary. A higher score demonstrates a rich and precise vocabulary; a lower score suggests limited vocabulary usage and appropriateness.",
	};

	return (
		<div className="flex flex-col gap-4 mt-4 w-full">
			<div className="flex justify-between w-full gap-8">
				<Button
					color="purple"
					variant="outline"
					onClick={() =>
						onBack({
							exercise: id,
							solutions: userSolutions,
							score: {total: 100, missing: 0, correct: speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0},
							type,
						})
					}
					className="max-w-[200px] self-end w-full">
					Back
				</Button>
				<Button
					color="purple"
					onClick={() =>
						onNext({
							exercise: id,
							solutions: userSolutions,
							score: {
								total: 100,
								missing: 0,
								correct: userSolutions[0]?.evaluation ? speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0 : 0,
							},
							type,
						})
					}
					className="max-w-[200px] self-end w-full">
					Next
				</Button>
			</div>

			<Modal title="Correction" isOpen={showDiff} onClose={() => setShowDiff(false)}>
				<>
					{userSolutions &&
						userSolutions.length > 0 &&
						userSolutions[0].evaluation?.transcript_1 &&
						userSolutions[0].evaluation?.fixed_text_1 && (
							<div className="w-full h-full rounded-xl overflow-hidden flex flex-col mt-4">
								<div className="w-full grid grid-cols-2 bg-neutral-100">
									<span className="p-3 font-medium text-lg border-r border-r-neutral-200">Transcript</span>
									<span className="p-3 font-medium text-lg border-l border-l-neutral-200">Recommended Improvements</span>
								</div>
								<ReactDiffViewer
									styles={{
										contentText: {
											fontFamily: '"Open Sans", system-ui, -apple-system, "Helvetica Neue", sans-serif',
											padding: "32px 28px",
										},
										marker: {display: "none"},
										diffRemoved: {padding: "32px 28px"},
										diffAdded: {padding: "32px 28px"},

										wordRemoved: {padding: "0px", display: "initial"},
										wordAdded: {padding: "0px", display: "initial"},
										wordDiff: {padding: "0px", display: "initial"},
									}}
									oldValue={userSolutions[0].evaluation.transcript_1.replaceAll("\\n", "\n")}
									newValue={userSolutions[0].evaluation.fixed_text_1.replaceAll("\\n", "\n")}
									splitView
									hideLineNumbers
									showDiffOnly={false}
								/>
							</div>
						)}
				</>
			</Modal>

			<div className="flex flex-col h-full w-full gap-8 mb-20">
				<div className="flex flex-col w-full gap-2 bg-mti-gray-smoke rounded-xl py-8 px-16">
					<div className="flex flex-col gap-3">
						<span className="font-semibold">{title}</span>
						{!video_url && (
							<span className="font-regular">
								{text.split("\\n").map((line, index) => (
									<Fragment key={index}>
										<span>{line}</span>
										<br />
									</Fragment>
								))}
							</span>
						)}
					</div>
					<div className="flex gap-6">
						{video_url && (
							<div className="flex flex-col gap-4 w-full items-center">
								<video key={id} autoPlay controls className="max-w-3xl rounded-xl">
									<source src={video_url} />
								</video>
							</div>
						)}
						{prompts && prompts.length > 0 && (
							<div className="flex flex-col gap-4">
								<span className="font-bold">You should talk about the following things:</span>
								<div className="flex flex-col gap-1 ml-4">
									{prompts.map((x, index) => (
										<li className="italic" key={index}>
											{x}
										</li>
									))}
								</div>
							</div>
						)}
					</div>
				</div>

				<div className="w-full h-full flex flex-col gap-8 relative">
					<div className="w-full p-4 px-8 bg-transparent border-2 border-mti-gray-platinum rounded-2xl flex-col gap-8 items-center relative">
						<div className="flex gap-8 items-center justify-center py-8">
							{solutionURL && <Waveform audio={solutionURL} waveColor="#FCDDEC" progressColor="#EF5DA8" />}

							{userSolutions &&
								userSolutions.length > 0 &&
								userSolutions[0].evaluation?.transcript_1 &&
								userSolutions[0].evaluation?.fixed_text_1 && (
									<Button className="w-full max-w-[180px] !py-2" color="pink" variant="outline" onClick={() => setShowDiff(true)}>
										View Correction
									</Button>
								)}
						</div>
					</div>
					{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
						<div className="flex flex-col gap-4 w-full">
							<div className="flex gap-4 px-1">
								{Object.keys(userSolutions[0].evaluation!.task_response).map((key, index) => {
									const taskResponse = userSolutions[0].evaluation!.task_response[key];
									const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade;

									return (
										<div
											className={clsx(
												"bg-ielts-speaking text-ielts-speaking-light rounded-xl px-4 py-2 tooltip tooltip-bottom",
												index === 0 && "tooltip-right",
											)}
											key={key}
											data-tip={tooltips[key] || "No additional information available"}>
											{key}: Level {grade}
										</div>
									);
								})}
							</div>
							{userSolutions[0].evaluation &&
							(userSolutions[0].evaluation.perfect_answer || userSolutions[0].evaluation.perfect_answer_1) ? (
								<Tab.Group>
									<Tab.List className="flex space-x-1 rounded-xl bg-ielts-speaking/20 p-1">
										<Tab
											className={({selected}) =>
												clsx(
													"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
													"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
													"transition duration-300 ease-in-out",
													selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
												)
											}>
											General Feedback
										</Tab>
										<Tab
											className={({selected}) =>
												clsx(
													"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
													"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
													"transition duration-300 ease-in-out",
													selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
												)
											}>
											Evaluation
										</Tab>
										<Tab
											className={({selected}) =>
												clsx(
													"w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80",
													"ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2",
													"transition duration-300 ease-in-out",
													selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking",
												)
											}>
											Recommended Answer
										</Tab>
									</Tab.List>
									<Tab.Panels>
										{/* General Feedback */}
										<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
											<div className="flex flex-col gap-4">
												{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => {
													const taskResponse = userSolutions[0].evaluation!.task_response[key];
													const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade;

													return (
														<div key={key} className="flex flex-col gap-2">
															<div
																className={clsx(
																	"bg-ielts-speaking text-ielts-speaking-light rounded-xl px-4 py-2 w-fit",
																)}
																key={key}>
																{key}: Level {grade}
															</div>
															{typeof taskResponse !== "number" && (
																<span className="px-2 py-2">{taskResponse.comment}</span>
															)}
														</div>
													);
												})}
											</div>
										</Tab.Panel>
										{/* Evaluation */}
										<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
											<span className="w-full h-full min-h-fit cursor-text">{userSolutions[0].evaluation!.comment}</span>
										</Tab.Panel>
										{/* Recommended Answer */}
										<Tab.Panel className="w-full bg-ielts-speaking/10 h-fit rounded-xl p-6 flex flex-col gap-4">
											<span className="w-full h-full min-h-fit cursor-text whitespace-pre-wrap">
												{userSolutions[0].evaluation!.perfect_answer &&
													userSolutions[0].evaluation!.perfect_answer.replaceAll(/\s{2,}/g, "\n\n")}
												{userSolutions[0].evaluation!.perfect_answer_1 &&
													userSolutions[0].evaluation!.perfect_answer_1.replaceAll(/\s{2,}/g, "\n\n")}
											</span>
										</Tab.Panel>
									</Tab.Panels>
								</Tab.Group>
							) : (
								<div className="w-full h-full min-h-fit cursor-text px-7 py-8 bg-ielts-speaking/10 rounded-3xl">
									{userSolutions[0].evaluation!.comment}
								</div>
							)}
						</div>
					)}
				</div>
			</div>

			<div className="self-end flex justify-between w-full gap-8 absolute bottom-8 left-0 px-8">
				<Button
					color="purple"
					variant="outline"
					onClick={() =>
						onBack({
							exercise: id,
							solutions: userSolutions,
							score: {total: 100, missing: 0, correct: speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0},
							type,
						})
					}
					className="max-w-[200px] self-end w-full">
					Back
				</Button>
				<Button
					color="purple"
					onClick={() =>
						onNext({
							exercise: id,
							solutions: userSolutions,
							score: {
								total: 100,
								missing: 0,
								correct: userSolutions[0]?.evaluation ? speakingReverseMarking[userSolutions[0]!.evaluation!.overall] || 0 : 0,
							},
							type,
						})
					}
					className="max-w-[200px] self-end w-full">
					Next
				</Button>
			</div>
		</div>
	);
}
