import {
	InteractiveSpeakingExercise,
	SpeakingExercise,
	UserSolution,
	WritingExercise,
} from "@/interfaces/exam";
import axios from "axios";
import { v4 } from "uuid";

export const evaluateWritingAnswer = async (
	userId: string,
	sessionId: string,
	exercise: WritingExercise,
	task: number,
	solution: UserSolution,
	attachment?: string,
): Promise<UserSolution> => {
	await axios.post("/api/evaluate/writing", {
		question: `${exercise.prompt}`.replaceAll("\n", ""),
		answer: solution.solutions[0].solution.trim().replaceAll("\n", " "),
		task,
		userId,
		sessionId,
		exerciseId: exercise.id,
		attachment,
	});

	return {
		...solution,
		id: v4(),
		score: {
			correct: 0,
			missing: 0,
			total: 100,
		},
		solutions: [{id: exercise.id, solution: solution.solutions[0].solution}],
		isDisabled: true,
	};
};

export const evaluateSpeakingAnswer = async (
	userId: string,
	sessionId: string,
	exercise: SpeakingExercise | InteractiveSpeakingExercise,
	solution: UserSolution,
	task: number,
): Promise<UserSolution> => {
	switch (exercise?.type) {
		case "speaking":
			return await evaluateSpeakingExercise(userId, sessionId, exercise, solution);
		case "interactiveSpeaking":
			return await evaluateInteractiveSpeakingExercise(userId, sessionId, exercise.id, solution, task);
	}
};

export const downloadBlob = async (url: string): Promise<Buffer> => {
	const blobResponse = await axios.get(url, { responseType: "arraybuffer" });
	return Buffer.from(blobResponse.data, "binary");
};

const evaluateSpeakingExercise = async (
	userId: string,
	sessionId: string,
	exercise: SpeakingExercise,
	solution: UserSolution,
): Promise<UserSolution> => {
	const formData = new FormData();

	const url = solution.solutions[0].solution.trim() as string;
	const audioBlob = await downloadBlob(url);
	const audioFile = new File([audioBlob], "audio.wav", { type: "audio/wav" });

	if (url && !url.startsWith("blob")) {
		await axios.post("/api/storage/delete", { path: url });
	}

	formData.append("userId", userId);
	formData.append("sessionId", sessionId);
	formData.append("exerciseId", exercise.id);

	const evaluationQuestion = `${exercise.text.replaceAll("\n", "")}` + (exercise.prompts.length > 0 ? `You should talk about: ${exercise.prompts.join(", ")}` : "");
	formData.append("question", evaluationQuestion);
	formData.append("audio", audioFile, "audio.wav");

	const config = {
		headers: {
			"Content-Type": "multipart/form-data",
		},
	};

	await axios.post(`/api/evaluate/speaking`, formData, config);
	return {
		...solution,
		id: v4(),
		score: {
			correct: 0,
			missing: 0,
			total: 100,
		},
		solutions: [{id: exercise.id, solution: null}],
		isDisabled: true,
	};
};

const evaluateInteractiveSpeakingExercise = async (
	userId: string,
	sessionId: string,
	exerciseId: string,
	solution: UserSolution,
	task: number,
): Promise<UserSolution> => {
	const formData = new FormData();
	formData.append("userId", userId);
	formData.append("sessionId", sessionId);
	formData.append("exerciseId", exerciseId);
	formData.append("task", task.toString());

	const promiseParts = solution.solutions.map(async (x: { prompt: string; blob: string }, index: number) => {
		const audioBlob = await downloadBlob(x.blob);
		if (!x.blob.startsWith("blob")) {
			await axios.post("/api/storage/delete", { path: x.blob });
		}
		const audioFile = new File([audioBlob], "audio.wav", { type: "audio/wav" });

		formData.append(`question_${index + 1}`, x.prompt);
		formData.append(`audio_${index + 1}`, audioFile, "audio.wav");
	});

	await Promise.all(promiseParts);

	const config = {
		headers: {
			"Content-Type": "multipart/form-data",
		},
	};

	await axios.post(`/api/evaluate/interactiveSpeaking`, formData, config);
	return {
		...solution,
		id: v4(),
		score: {
			correct: 0,
			missing: 0,
			total: 100,
		},
		solutions: [{id: exerciseId, solution: null}],
		isDisabled: true,
	};
};
