import type { Component } from "solid-js";
import { createMemo, createResource, createSignal, onMount } from "solid-js";
import { createStore } from "solid-js/store";
import { useAuth } from "~/context/auth/context";
import styles from "./dashboard-teacher-assignments.module.scss";
import { createTeacherAssignment, generateTeacherQuestions, getTeacherAssignmentSetupData } from "./dashboard-teacher-assignments.data";
import { defaultGenerationForm, emptySetupForm } from "./dashboard-teacher-assignment-create.constants";
import { buildGenerationSuccessMessage, buildMixedGenerationInput, mergeSelectedQuestionIds, parseOptionalInteger } from "./dashboard-teacher-assignment-create.helpers";
import {
	AssignmentCreateHero,
	AssignmentDetailsSection,
	PersonalizedGenerationSection,
	QuestionBankSection,
	SetupSummarySection,
	SharedGenerationSection,
	SubmissionSection,
} from "./dashboard-teacher-assignment-create.sections";
import type { AssignmentSetupForm, QuestionGenerationForm } from "./dashboard-teacher-assignment-create.types";

const DashboardTeacherAssignmentCreate: Component = () => {
	const auth = useAuth();
	const [teacherId, setTeacherId] = createSignal<number | null>(null);
	const [setupData, { mutate: mutateSetupData }] = createResource(teacherId, getTeacherAssignmentSetupData);
	const [form, setForm] = createStore<AssignmentSetupForm>(emptySetupForm);
	const [generationForm, setGenerationForm] = createStore<QuestionGenerationForm>(defaultGenerationForm);
	const [isSubmitting, setIsSubmitting] = createSignal(false);
	const [isGenerating, setIsGenerating] = createSignal(false);
	const [errorMessage, setErrorMessage] = createSignal<string | null>(null);
	const [successMessage, setSuccessMessage] = createSignal<string | null>(null);

	onMount(() => {
		if (auth.user()?.role === "teacher") {
			setTeacherId(auth.user()!.id);
		}
	});

	const selectedClassroom = createMemo(() => setupData()?.classrooms.find((classroom) => `${classroom.id}` === form.classroomId));
	const selectedQuestionCount = createMemo(() => form.selectedQuestionIds.length);
	const mixedGenerationEnabled = createMemo(() => form.useMixedGeneration);
	const mixedGenerationQuestionCount = createMemo(() => Number(form.totalQuestions) || 0);
	const mixedGenerationRatioLabel = createMemo(() => {
		const parsed = Number(form.personalizedRatio);
		if (!Number.isFinite(parsed) || parsed <= 0) return "30% personalized";
		return `${parsed}% personalized`;
	});

	const handleTextInput =
		(
			field:
				| "classroomId"
				| "title"
				| "instructions"
				| "dueAt"
				| "primaryTopic"
				| "primaryDifficulty"
				| "totalQuestions"
				| "personalizedRatio"
				| "seed"
				| "personalizedDifficulty"
				| "subject",
		) =>
		(event: Event) => {
		const target = event.currentTarget as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
		setForm(field, target.value);
		setSuccessMessage(null);
	};

	const handleMixedGenerationToggle = (event: Event) => {
		const target = event.currentTarget as HTMLInputElement;
		setForm("useMixedGeneration", target.checked);
		setSuccessMessage(null);
	};

	const handleGenerationInput = (field: keyof QuestionGenerationForm) => (event: Event) => {
		const target = event.currentTarget as HTMLInputElement | HTMLSelectElement;
		setGenerationForm(field, target.value as QuestionGenerationForm[keyof QuestionGenerationForm]);
		setSuccessMessage(null);
	};

	const handleQuestionToggle = (questionId: number) => (event: Event) => {
		const target = event.currentTarget as HTMLInputElement;
		setForm("selectedQuestionIds", target.checked ? [...form.selectedQuestionIds, questionId] : form.selectedQuestionIds.filter((id) => id !== questionId));
		setSuccessMessage(null);
	};

	const resetForm = () => {
		setForm({ ...emptySetupForm, classroomId: form.classroomId });
	};

	const mergeGeneratedQuestions = (generatedQuestionIds: number[], questions: Awaited<ReturnType<typeof generateTeacherQuestions>>["questions"]) => {
		mutateSetupData((current) => {
			if (!current) return current;
			const existingQuestions = current.questions.filter((question) => !generatedQuestionIds.includes(question.id));
			return {
				...current,
				questions: [...questions, ...existingQuestions],
			};
		});

		setForm("selectedQuestionIds", mergeSelectedQuestionIds(form.selectedQuestionIds, generatedQuestionIds));
	};

	const handleGenerateQuestions = async (event: Event) => {
		event.preventDefault();
		const currentTeacherId = teacherId();
		if (!currentTeacherId) {
			setErrorMessage("Your teacher session is still loading.");
			return;
		}

		const parsedCount = Number(generationForm.count);
		const parsedSeed = parseOptionalInteger(generationForm.seed);

		if (!Number.isInteger(parsedCount) || parsedCount < 1 || parsedCount > 25) {
			setErrorMessage("Choose a question count between 1 and 25.");
			return;
		}

		if (generationForm.seed.trim() && (!Number.isInteger(parsedSeed) || Number.isNaN(parsedSeed))) {
			setErrorMessage("Seed must be a whole number when provided.");
			return;
		}

		setIsGenerating(true);
		setErrorMessage(null);
		setSuccessMessage(null);

		try {
			const result = await generateTeacherQuestions({
				topic: generationForm.topic,
				difficulty: generationForm.difficulty,
				count: parsedCount,
				seed: parsedSeed,
			});

			mergeGeneratedQuestions(result.generatedQuestionIds, result.questions);
			setSuccessMessage(buildGenerationSuccessMessage(generationForm, result.count, result.seed));
		} catch (error) {
			setErrorMessage(error instanceof Error ? error.message : "Unable to generate questions right now.");
		} finally {
			setIsGenerating(false);
		}
	};

	const handleSubmit = async (event: Event) => {
		event.preventDefault();
		const currentTeacherId = teacherId();
		if (!currentTeacherId) {
			setErrorMessage("Your teacher session is still loading.");
			return;
		}

		setIsSubmitting(true);
		setErrorMessage(null);
		setSuccessMessage(null);

		try {
			const mixedGeneration = buildMixedGenerationInput(form);

			await createTeacherAssignment({
				teacherId: currentTeacherId,
				classroomId: Number(form.classroomId),
				title: form.title,
				instructions: form.instructions,
				dueAt: form.dueAt,
				selectedQuestionIds: form.selectedQuestionIds,
				mixedGeneration,
			});
			setSuccessMessage(
				mixedGenerationEnabled()
					? "Personalized homework created and assigned. Each student now has a mixed generated question set."
					: "Homework created and assigned to the selected class.",
			);
			resetForm();
		} catch (error) {
			setErrorMessage(error instanceof Error ? error.message : "Unable to create homework right now.");
		} finally {
			setIsSubmitting(false);
		}
	};

	return (
		<section class={styles.section}>
			<AssignmentCreateHero />

			<form class={styles.setupGrid} onSubmit={(event) => void handleSubmit(event)}>
				<article class={styles.setupCard}>
					<AssignmentDetailsSection
						form={form}
						classrooms={setupData()?.classrooms ?? []}
						selectedQuestionCount={selectedQuestionCount()}
						onInput={handleTextInput}
					/>

					<PersonalizedGenerationSection
						form={form}
						mixedGenerationEnabled={mixedGenerationEnabled()}
						mixedGenerationQuestionCount={mixedGenerationQuestionCount()}
						mixedGenerationRatioLabel={mixedGenerationRatioLabel()}
						onInput={handleTextInput}
						onToggle={handleMixedGenerationToggle}
					/>

					<SharedGenerationSection
						form={generationForm}
						isGenerating={isGenerating()}
						isSubmitting={isSubmitting()}
						onInput={handleGenerationInput}
						onGenerate={(event) => void handleGenerateQuestions(event)}
					/>

					<QuestionBankSection
						questions={setupData()?.questions ?? []}
						loading={setupData.loading}
						mixedGenerationEnabled={mixedGenerationEnabled()}
						selectedQuestionIds={form.selectedQuestionIds}
						onToggle={handleQuestionToggle}
					/>

					<SubmissionSection
						isSubmitting={isSubmitting()}
						errorMessage={errorMessage()}
						successMessage={successMessage()}
						onReset={resetForm}
					/>
				</article>

				<SetupSummarySection
					classroomName={selectedClassroom()?.name ?? ""}
					rosterLabel={selectedClassroom()?.studentCountLabel ?? ""}
					mixedGenerationEnabled={mixedGenerationEnabled()}
					mixedGenerationQuestionCount={mixedGenerationQuestionCount()}
					selectedQuestionCount={selectedQuestionCount()}
				/>
			</form>
		</section>
	);
};

export default DashboardTeacherAssignmentCreate;
