import { InteractiveSpeakingExercise } from "@/interfaces/exam";
import { CommonProps } from "../types";
import { useCallback, useEffect, useRef, useState } from "react";
import { BsCheckCircleFill, BsMicFill, BsPauseCircle, BsPlayCircle, BsTrashFill } from "react-icons/bs";
import dynamic from "next/dynamic";
import useExamStore, { usePersistentExamStore } from "@/stores/exam";
import useAnswers, { Answer } from "./useAnswers";

const Waveform = dynamic(() => import("../../Waveform"), { ssr: false });
const ReactMediaRecorder = dynamic(() => import("react-media-recorder").then((mod) => mod.ReactMediaRecorder), {
	ssr: false,
});

const InteractiveSpeaking: React.FC<InteractiveSpeakingExercise & CommonProps> = ({
	id,
	title,
	first_title,
	second_title,
	prompts,
	userSolutions,
	isPractice = false,
	registerSolution,
	headerButtons,
	footerButtons,
	type,
	preview,
}) => {
	const [isRecording, setIsRecording] = useState(false);
	const [recordingDuration, setRecordingDuration] = useState(0);
	const timerRef = useRef<NodeJS.Timeout>();

	const { answers, setAnswers, updateAnswers } = useAnswers(
		id,
		type,
		isPractice,
		prompts,
		registerSolution,
		preview
	);

	const examState = useExamStore((state) => state);
	const persistentExamState = usePersistentExamStore((state) => state);

	const { questionIndex } = !preview ? examState : persistentExamState;

	useEffect(() => {
		if (isRecording) {
			timerRef.current = setInterval(() => {
				setRecordingDuration(prev => prev + 1);
			}, 1000);
		}

		return () => {
			if (timerRef.current) {
				clearInterval(timerRef.current);
			}
		};
	}, [isRecording]);

	useEffect(() => {
		if (userSolutions.length > 0 && answers.length === 0) {
			setAnswers(userSolutions.flatMap(solution =>
				solution.solution.map(s => ({
					questionIndex: s.questionIndex,
					prompt: s.question,
					blob: s.answer
				}))
			));
		}
	}, [userSolutions, answers.length, setAnswers]);

	const resetRecording = useCallback(() => {
		setRecordingDuration(0);
		setIsRecording(false);
	}, []);

	const handleStartRecording = useCallback((startRecording: () => void) => {
		resetRecording();
		startRecording();
		setIsRecording(true);
	}, [resetRecording]);

	return (
		<div className="flex flex-col gap-4 mt-4 w-full">
			{headerButtons}
			<div className="flex flex-col h-full w-full gap-9">
				<div className="flex flex-col w-full gap-8 bg-mti-gray-smoke rounded-xl py-8 pb-12 px-16">
					<div className="flex flex-col gap-3">
						<span className="font-semibold">
							{!!first_title && !!second_title ? `${first_title} & ${second_title}` : title}
						</span>
					</div>
					{prompts && prompts.length > 0 && (
						<div className="flex flex-col gap-4 w-full items-center">
							<video key={questionIndex} autoPlay controls className="max-w-3xl rounded-xl">
								<source src={prompts[questionIndex].video_url} />
							</video>
						</div>
					)}
				</div>

				<ReactMediaRecorder
					audio
					key={questionIndex}
					onStop={updateAnswers}
					render={({ status, startRecording, stopRecording, pauseRecording, resumeRecording, mediaBlobUrl }) => (
						<div className="w-full p-4 px-8 bg-transparent border-2 border-mti-gray-platinum rounded-2xl flex-col gap-8 items-center">
							<p className="text-base font-normal">Record your answer:</p>
							<div className="flex gap-8 items-center justify-center py-8">
								{status === "idle" && (
									<>
										<div className="w-full h-2 max-w-4xl bg-mti-gray-smoke rounded-full" />
										<BsMicFill
											onClick={() => handleStartRecording(startRecording)}
											className="h-5 w-5 text-mti-gray-cool cursor-pointer"
										/>
									</>
								)}
								{status === "recording" && (
									<>
										<div className="flex gap-4 items-center">
											<span className="text-xs w-9">
												{`${Math.floor(recordingDuration / 60).toString().padStart(2, "0")}:${Math.floor(recordingDuration % 60).toString().padStart(2, "0")}`}
											</span>
										</div>
										<div className="w-full h-2 max-w-4xl bg-mti-gray-smoke rounded-full" />
										<div className="flex gap-4 items-center">
											<BsPauseCircle
												onClick={() => {
													setIsRecording(false);
													pauseRecording();
												}}
												className="text-red-500 w-8 h-8 cursor-pointer"
											/>
											<BsCheckCircleFill
												onClick={() => {
													setIsRecording(false);
													stopRecording();
												}}
												className="text-mti-purple-light w-8 h-8 cursor-pointer"
											/>
										</div>
									</>
								)}
								{status === "paused" && (
									<>
										<div className="flex gap-4 items-center">
											<span className="text-xs w-9">
												{`${Math.floor(recordingDuration / 60).toString().padStart(2, "0")}:${Math.floor(recordingDuration % 60).toString().padStart(2, "0")}`}
											</span>
										</div>
										<div className="w-full h-2 max-w-4xl bg-mti-gray-smoke rounded-full" />
										<div className="flex gap-4 items-center">
											<BsPlayCircle
												onClick={() => {
													setIsRecording(true);
													resumeRecording();
												}}
												className="text-mti-purple-light w-8 h-8 cursor-pointer"
											/>
											<BsCheckCircleFill
												onClick={() => {
													setIsRecording(false);
													stopRecording();
												}}
												className="text-mti-purple-light w-8 h-8 cursor-pointer"
											/>
										</div>
									</>
								)}
								{status === "stopped" && mediaBlobUrl && (
									<>
										<Waveform audio={mediaBlobUrl} waveColor="#FCDDEC" progressColor="#EF5DA8" />
										<div className="flex gap-4 items-center">
											<BsTrashFill
												className="text-mti-gray-cool cursor-pointer w-5 h-5"
												onClick={() => {
													resetRecording();
													setAnswers(prev => prev.filter(x => x.questionIndex !== questionIndex));
												}}
											/>
											<BsMicFill
												onClick={() => {
													resetRecording();
													startRecording();
													setIsRecording(true);
												}}
												className="h-5 w-5 text-mti-gray-cool cursor-pointer"
											/>
										</div>
									</>
								)}
							</div>
						</div>
					)}
				/>
			</div>
			{footerButtons}
		</div>
	);
};

export default InteractiveSpeaking;