// Path: Frontend/src/components/assignment/teacher/assignment-teacher-review.tsx

import type { Component } from "solid-js";
import { createEffect, createMemo, createSignal, For, Show } from "solid-js";
import { useNavigate } from "@solidjs/router";
import type { TeacherAssignmentReviewPageData, TeacherReviewDraftFields, TeacherReviewNotice, TeacherReviewQuestion } from "./assignment-teacher-review.types";
import { closeTeacherAssignment, updateTeacherAnswerReview } from "./assignment-teacher-review.data";
import {
	applyReviewDrafts,
	type AssignmentReviewDraftStore,
	countPendingQuestionDrafts,
	EMPTY_DRAFT_STORE,
	type StudentReviewDraft,
	readDraftStore,
	reviewFieldsEqual,
	reviewFieldsFromQuestion,
	sanitizeReviewFields,
	writeDraftStore,
} from "./assignment-teacher-review.drafts";
import styles from "./assignment-teacher-review.module.scss";
import { TeacherReviewQuestionCard, TeacherReviewSaveProgressCard, TeacherReviewSidebar } from "./assignment-teacher-review.sections";
import { getTeacherAssignmentNextStepHref } from "../../../lib/routes";

type Props = {
	data: TeacherAssignmentReviewPageData;
	onSelectStudent: (studentId: number) => void;
	onRefresh: () => Promise<unknown> | unknown;
};

const AssignmentTeacherReview: Component<Props> = (props) => {
	const navigate = useNavigate();
	let questionReviewSectionRef: HTMLElement | undefined;
	const [draftStore, setDraftStore] = createSignal<AssignmentReviewDraftStore>(EMPTY_DRAFT_STORE);
	const [savingAll, setSavingAll] = createSignal(false);
	const [closingAssignment, setClosingAssignment] = createSignal(false);
	const [notice, setNotice] = createSignal<TeacherReviewNotice>(null);
	const [closeNotice, setCloseNotice] = createSignal<TeacherReviewNotice>(null);
	const [questionNavExpanded, setQuestionNavExpanded] = createSignal(false);

	const currentStudentKey = createMemo(() => (props.data.selectedStudentId ? String(props.data.selectedStudentId) : null));
	const currentStudentDraft = createMemo(() => {
		const studentKey = currentStudentKey();
		if (!studentKey) return null;
		return draftStore().students[studentKey] ?? null;
	});
	const displayQuestions = createMemo(() => applyReviewDrafts(props.data.questions, currentStudentDraft()));
	const pendingChangeCount = createMemo(() => countPendingQuestionDrafts(draftStore()));
	createEffect(() => {
		setDraftStore(readDraftStore(props.data.assignmentId));
	});

	createEffect(() => {
		writeDraftStore(props.data.assignmentId, draftStore());
	});

	createEffect(() => {
		setNotice(null);
	});

	createEffect(() => {
		setCloseNotice(null);
	});

	const hasQueue = createMemo(() => props.data.reviewQueue.length > 0);
	const canMoveToNextStep = createMemo(() => {
		return props.data.selectedStudentSubmittedQuestions > 0 || props.data.selectedStudentReviewedQuestions > 0;
	});
	const getBaseQuestion = (questionId: number) => props.data.questions.find((entry) => entry.id === questionId);
	const getSelectedStudentQuestions = () => props.data.questions.filter((question) => question.answerId);
	const getQuestionCardId = (questionId: number) => `teacher-review-question-${questionId}`;
	const handleSelectQuestion = (questionId: number) => {
		const element = document.getElementById(getQuestionCardId(questionId));
		element?.scrollIntoView({ behavior: "smooth", block: "start" });
		setQuestionNavExpanded(false);
	};
	const handleScrollToTop = () => {
		questionReviewSectionRef?.scrollIntoView({ behavior: "smooth", block: "start" });
	};

	const updateStudentDraft = (studentId: number, updater: (draft: StudentReviewDraft) => StudentReviewDraft | null) => {
		const studentKey = String(studentId);
		setDraftStore((current) => {
			const nextStudents = { ...current.students };
			const nextDraft = updater(nextStudents[studentKey] ?? {});
			if (!nextDraft) {
				delete nextStudents[studentKey];
			} else {
				nextStudents[studentKey] = nextDraft;
			}

			return {
				students: nextStudents,
			};
		});
	};

	const updateQuestionReviewDraft = (question: TeacherReviewQuestion, patch: Partial<TeacherReviewDraftFields>) => {
		if (!question.answerId || !props.data.selectedStudentId) return;
		setNotice(null);
		const baseQuestion = getBaseQuestion(question.id) ?? question;
		const baseFields = sanitizeReviewFields(reviewFieldsFromQuestion(baseQuestion));

		updateStudentDraft(props.data.selectedStudentId, (draft) => {
			const questionReviews = { ...(draft.questionReviews ?? {}) };
			const currentFields = sanitizeReviewFields(
				questionReviews[String(question.id)]
					? {
						...baseFields,
						...questionReviews[String(question.id)],
					  }
					: baseFields
			);
			const nextFields = sanitizeReviewFields({
				...currentFields,
				...patch,
			});

			if (reviewFieldsEqual(nextFields, baseFields)) {
				delete questionReviews[String(question.id)];
			} else {
				questionReviews[String(question.id)] = {
					answerId: question.answerId,
					...nextFields,
				};
			}

			const nextDraft: StudentReviewDraft = {
				...draft,
			};
			if (Object.keys(questionReviews).length > 0) {
				nextDraft.questionReviews = questionReviews;
			} else {
				delete nextDraft.questionReviews;
			}

			if (Object.keys(nextDraft.questionReviews ?? {}).length === 0) {
				return null;
			}

			return nextDraft;
		});
	};

	const resetQuestionDraft = (question: TeacherReviewQuestion) => {
		const selectedStudentId = props.data.selectedStudentId;
		if (!selectedStudentId) return;
		setNotice(null);
		updateStudentDraft(selectedStudentId, (draft) => {
			const questionReviews = { ...(draft.questionReviews ?? {}) };
			delete questionReviews[String(question.id)];

			if (Object.keys(questionReviews).length === 0) {
				return null;
			}

			return {
				...draft,
				questionReviews,
			};
		});
	};
	const markQuestionNeedsAttention = (question: TeacherReviewQuestion) => {
		updateQuestionReviewDraft(question, {
			reviewNeedsAttention: true,
		});
	};

	const saveAllAndNextStep = async () => {
		setNotice(null);
		const selectedStudentId = props.data.selectedStudentId;
		if (!selectedStudentId) return;
		if (!canMoveToNextStep()) {
			setNotice({
				scope: "global",
				tone: "error",
				text: "Students need a submitted review before you can move them to the next step.",
			});
			return;
		}

		const operations: Array<() => Promise<unknown>> = [];
		const selectedStudentDraft = draftStore().students[String(selectedStudentId)] ?? null;
		const questionDrafts = selectedStudentDraft?.questionReviews ?? {};

		for (const question of getSelectedStudentQuestions()) {
			const draft = questionDrafts[String(question.id)];
			if (!question.answerId) continue;
			const baseFields = sanitizeReviewFields(reviewFieldsFromQuestion(question));
			const effectiveReview = sanitizeReviewFields(
				draft
					? {
						...baseFields,
						...draft,
					  }
					: baseFields
			);
			const nextStatus = effectiveReview.reviewNeedsAttention ? "submitted" : "reviewed";
			const hasReviewFieldChanges = !reviewFieldsEqual(effectiveReview, baseFields);
			if (question.answerStatus === nextStatus && !hasReviewFieldChanges) continue;

			operations.push(() =>
				updateTeacherAnswerReview(question.answerId!, {
					status: nextStatus,
					reviewTags: [...question.questionTags],
					...effectiveReview,
				})
			);
		}

		setSavingAll(true);
		try {
			for (const operation of operations) {
				await operation();
			}
			updateStudentDraft(selectedStudentId, () => null);
			navigate(getTeacherAssignmentNextStepHref(props.data.assignmentId, selectedStudentId));
		} catch (error) {
			setNotice({
				scope: "global",
				tone: "error",
				text: error instanceof Error ? error.message : "Could not save all review changes right now.",
			});
		} finally {
			setSavingAll(false);
		}
	};

	const handleCloseAssignment = async () => {
		setCloseNotice(null);
		if (!props.data.closeSummary.canClose) {
			setCloseNotice({
				scope: "assignment",
				tone: "error",
				text: props.data.closeSummary.summary,
			});
			return;
		}

		setClosingAssignment(true);
		try {
			await closeTeacherAssignment(props.data.assignmentId);
			await props.onRefresh();
			setCloseNotice({
				scope: "assignment",
				tone: "success",
				text: "Assignment closed.",
			});
		} catch (error) {
			setCloseNotice({
				scope: "assignment",
				tone: "error",
				text: error instanceof Error ? error.message : "Could not close this assignment right now.",
			});
		} finally {
			setClosingAssignment(false);
		}
	};

	return (
		<>
			<div class={styles.contentGrid}>
				<div class={styles.mainColumn}>
					<section ref={questionReviewSectionRef} class={styles.section}>
						<div class={styles.sectionHeader}>
							<h2>Question review</h2>
							<p>
								<Show when={props.data.selectedStudentName} fallback={hasQueue() ? "Choose a student to begin reviewing." : "This assignment has no student review queue yet."}>
									{props.data.selectedStudentName} · {props.data.questions.length} questions
								</Show>
							</p>
						</div>

						<Show when={props.data.selectedStudentId !== null && displayQuestions().length > 0}>
							<section class={styles.mobileStickyNav}>
								<div class={styles.mobileStickyNavHeader}>
									<div>
										<h3>Questions</h3>
										<p>{displayQuestions().length} questions in this review</p>
									</div>
									<div class={styles.mobileStickyNavActions}>
										<button type="button" class={styles.mobileStickyNavBackToTop} onClick={handleScrollToTop}>
											Back to top
										</button>
										<button
											type="button"
											class={styles.mobileStickyNavToggle}
											aria-expanded={questionNavExpanded()}
											onClick={() => setQuestionNavExpanded((value) => !value)}
										>
											{questionNavExpanded() ? "Hide list" : "Open list"}
										</button>
									</div>
								</div>
								<div
									classList={{
										[styles.mobileStickyNavContent]: true,
										[styles.mobileStickyNavContentExpanded]: questionNavExpanded(),
									}}
								>
									<div class={styles.mobileQuestionNavList}>
										<For each={displayQuestions()}>
											{(question) => (
												<button
													type="button"
													class={`${styles.mobileQuestionNavButton} ${question.answerId ? styles.mobileQuestionNavAnswered : ""}`.trim()}
													onClick={() => handleSelectQuestion(question.id)}
												>
													<strong>Q{question.order}</strong>
													<small>{question.statusLabel}</small>
												</button>
											)}
										</For>
									</div>
								</div>
							</section>
						</Show>

				<Show when={props.data.selectedStudentId !== null} fallback={<div class={styles.emptyState}>Select a student from the review queue to inspect answers and leave feedback.</div>}>
							<div class={styles.questionList}>
							<For each={displayQuestions()}>
								{(question) => (
									<TeacherReviewQuestionCard
										cardId={getQuestionCardId(question.id)}
										question={question}
										notice={notice()}
										hasPendingDraft={Boolean(currentStudentDraft()?.questionReviews?.[String(question.id)])}
										savingAll={savingAll()}
										onResetDraft={resetQuestionDraft}
										onNeedsAttention={markQuestionNeedsAttention}
										onReviewFieldChange={updateQuestionReviewDraft}
									/>
								)}
							</For>
							</div>

							<TeacherReviewSaveProgressCard
								canMoveToNextStep={canMoveToNextStep()}
								pendingChangeCount={pendingChangeCount()}
								savingAll={savingAll()}
								closeState={props.data.closeSummary.state}
								notice={notice()}
								onSave={saveAllAndNextStep}
							/>
						</Show>
					</section>
				</div>

				<TeacherReviewSidebar data={props.data} hasQueue={hasQueue()} closingAssignment={closingAssignment()} closeNotice={closeNotice()} onSelectStudent={props.onSelectStudent} onCloseAssignment={handleCloseAssignment} />
			</div>
		</>
	);
};

export default AssignmentTeacherReview;
