// Path: Frontend/src/components/assignment/work/student-assignment-work.page.tsx

import { A, useParams } from "@solidjs/router";
import type { Component } from "solid-js";
import { Show, createEffect, createMemo, createResource, createSignal } from "solid-js";
import { useAuth } from "~/context/auth/context";
import { getAssignmentReviewHref, getDashboardHomeHref } from "../../../lib/routes";
import AssignmentTabs from "../shared/assignment-tabs";
import { getAssignmentWorkPageData, upsertAssignmentAnswer } from "./assignment-work.data";
import styles from "./assignment-work.module.scss";
import { AssignmentWorkBanner, AssignmentWorkHeader, AssignmentWorkNavigator, AssignmentWorkWorkspace, type DraftState } from "./student-assignment-work.sections";

const StudentAssignmentWorkPage: Component = () => {
	const params = useParams();
	const auth = useAuth();
	const assignmentId = createMemo(() => {
		const parsed = Number(params.id);
		return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
	});
	const studentSource = createMemo(() => {
		const id = assignmentId();
		const user = auth.user();
		if (!auth.isReady() || !id || !user || user.role !== "student") return null;
		return { assignmentId: id, studentId: user.id };
	});
	const [assignmentData, { refetch }] = createResource(studentSource, ({ assignmentId, studentId }) => getAssignmentWorkPageData(assignmentId, studentId));

	const [drafts, setDrafts] = createSignal<DraftState>({});
	const [activeQuestionId, setActiveQuestionId] = createSignal<number | null>(null);
	const [hydratedAssignmentId, setHydratedAssignmentId] = createSignal<number | null>(null);
	const [saveState, setSaveState] = createSignal<"idle" | "saving" | "saved" | "error">("idle");
	const [submitState, setSubmitState] = createSignal<"idle" | "submitting" | "error">("idle");
	const [lastSavedAt, setLastSavedAt] = createSignal<string | null>(null);
	const [isSubmitted, setIsSubmitted] = createSignal(false);
	const [submittedAt, setSubmittedAt] = createSignal<string | null>(null);

	createEffect(() => {
		const data = assignmentData();
		if (!data || hydratedAssignmentId() === data.id) return;

		setDrafts(
			Object.fromEntries(
				data.questions.map((question) => [
					question.id,
					{
						answer: question.initialAnswer ?? "",
						steps: question.workingSteps ?? "",
						solveMode: question.initialSolveMode ?? "just_answer",
					},
				]),
			) as DraftState,
		);
		setActiveQuestionId(data.questions[0]?.id ?? null);
		setHydratedAssignmentId(data.id);
		setIsSubmitted(data.status === "SUBMITTED");
		setSubmittedAt(null);
		setLastSavedAt(null);
		setSaveState("idle");
		setSubmitState("idle");
	});

	const questions = createMemo(() => assignmentData()?.questions ?? []);
	const currentQuestion = createMemo(() => questions().find((question) => question.id === activeQuestionId()) ?? questions()[0]);
	const activeDraft = createMemo(() => {
		const question = currentQuestion();
		return question ? drafts()[question.id] : undefined;
	});
	const answeredCount = createMemo(() => Object.values(drafts()).filter((draft) => draft.answer.trim().length > 0).length);
	const remainingCount = createMemo(() => Math.max(questions().length - answeredCount(), 0));
	const isLastQuestion = createMemo(() => {
		const current = currentQuestion();
		if (!current) return false;
		return questions()[questions().length - 1]?.id === current.id;
	});
	const saveLabel = createMemo(() => {
		if (submitState() === "submitting") return "Submitting assignment and preparing your AI draft…";
		if (submitState() === "error") return "We could not submit the assignment.";
		if (saveState() === "saving") return "Saving to the backend…";
		if (saveState() === "error") return "We could not save that answer.";
		if (saveState() === "saved" && lastSavedAt()) {
			return `Saved ${new Intl.DateTimeFormat("en-GB", {
				hour: "numeric",
				minute: "2-digit",
			}).format(new Date(lastSavedAt()!))}`;
		}

		return "Draft synced with the backend when you save";
	});

	const updateDraft = (field: "answer" | "steps" | "solveMode", value: string) => {
		if (submitState() === "submitting") return;
		const question = currentQuestion();
		if (!question) return;

		setDrafts((current) => ({
			...current,
			[question.id]: {
				...current[question.id],
				[field]: value,
			},
		}));
		setIsSubmitted(false);
	};

	const saveQuestion = async (statusOverride?: "in_progress" | "submitted") => {
		if (submitState() === "submitting") return;
		const data = assignmentData();
		const question = currentQuestion();
		const draft = activeDraft();
		if (!data || !question || !draft) return;

		const trimmedAnswer = draft.answer.trim();
		const trimmedSteps = draft.steps.trim();
		const nextStatus = statusOverride ?? (trimmedAnswer || trimmedSteps ? (question.answerStatus === "submitted" || question.answerStatus === "reviewed" ? "submitted" : "in_progress") : "not_started");

		setSaveState("saving");

		try {
			await upsertAssignmentAnswer({
				assignmentId: data.id,
				questionId: question.id,
				answerText: trimmedAnswer || null,
				workingSteps: trimmedSteps || null,
				solveMode: draft.solveMode,
				status: nextStatus,
				submittedAt: nextStatus === "submitted" ? new Date().toISOString() : null,
			});
			setLastSavedAt(new Date().toISOString());
			setSaveState("saved");
			await refetch();
		} catch {
			setSaveState("error");
		}
	};

	const moveQuestion = (direction: 1 | -1) => {
		const current = currentQuestion();
		if (!current) return;
		const index = questions().findIndex((question) => question.id === current.id);
		const target = questions()[index + direction];
		if (target) setActiveQuestionId(target.id);
	};

	const handleSaveAndContinue = async () => {
		if (submitState() === "submitting") return;
		await saveQuestion();
		if (!isLastQuestion()) moveQuestion(1);
	};

	const handleSubmit = async () => {
		const data = assignmentData();
		if (!data || submitState() === "submitting") return;

		setSubmitState("submitting");
		setSaveState("saving");
		const now = new Date().toISOString();

		try {
			await Promise.all(
				data.questions.map(async (question) => {
					const draft = drafts()[question.id] ?? {
						answer: question.initialAnswer ?? "",
						steps: question.workingSteps ?? "",
						solveMode: question.initialSolveMode ?? "just_answer",
					};
					const trimmedAnswer = draft.answer.trim();
					const trimmedSteps = draft.steps.trim();

					await upsertAssignmentAnswer({
						assignmentId: data.id,
						questionId: question.id,
						answerText: trimmedAnswer || null,
						workingSteps: trimmedSteps || null,
						solveMode: draft.solveMode,
						status: "submitted",
						submittedAt: now,
					});
				}),
			);

			setIsSubmitted(true);
			setSubmittedAt(now);
			setLastSavedAt(now);
			setSubmitState("idle");
			setSaveState("saved");
			await refetch();
		} catch {
			setSubmitState("error");
			setSaveState("error");
		}
	};

	return (
		<main class={styles.page}>
			<div class={styles.shell}>
				<Show
					when={!assignmentData.loading}
					fallback={
						<section class={styles.emptyState}>
							<p class={styles.emptyEyebrow}>Loading assignment</p>
							<h1>Pulling your live workspace from the backend.</h1>
						</section>
					}
				>
					<Show
						when={assignmentData()}
						fallback={
							<section class={styles.emptyState}>
								<p class={styles.emptyEyebrow}>Assignment not found</p>
								<h1>We could not find that assignment workspace.</h1>
								<A href={getDashboardHomeHref("student")} class={styles.backButton}>
									Back to dashboard
								</A>
							</section>
						}
					>
						{(data) => {
							const reviewHref = createMemo(() => getAssignmentReviewHref("student", data().id));

							return (
								<>
									<AssignmentWorkBanner data={data()} answeredCount={answeredCount()} isSubmitted={isSubmitted()} reviewHref={reviewHref()} />

									<AssignmentWorkHeader
										data={data()}
										answeredCount={answeredCount()}
										remainingCount={remainingCount()}
										saveLabel={saveLabel()}
										reviewHref={reviewHref()}
										isSubmitting={submitState() === "submitting"}
										onSubmit={() => void handleSubmit()}
									/>

									<AssignmentTabs role="student" />

									<div class={styles.contentGrid}>
									<AssignmentWorkNavigator
										questions={data().questions}
										drafts={drafts()}
										activeQuestionId={activeQuestionId()}
										answeredCount={answeredCount()}
										remainingCount={remainingCount()}
										saveLabel={saveLabel()}
										isSubmitting={submitState() === "submitting"}
										onSelectQuestion={setActiveQuestionId}
									/>

									<Show when={currentQuestion() && activeDraft()}>
											<AssignmentWorkWorkspace
												question={currentQuestion()!}
												draft={activeDraft()!}
											saveLabel={saveLabel()}
											submittedAt={submittedAt()}
											isLastQuestion={isLastQuestion()}
											isSubmitting={submitState() === "submitting"}
											onUpdateDraft={updateDraft}
											onMoveQuestion={moveQuestion}
												onSaveDraft={() => void saveQuestion()}
												onSaveAndContinue={() => void handleSaveAndContinue()}
											/>
									</Show>
									</div>
								</>
							);
						}}
					</Show>
				</Show>
			</div>
		</main>
	);
};

export default StudentAssignmentWorkPage;
