import { A, useParams } from "@solidjs/router";
import type { Component } from "solid-js";
import { For, Show, createEffect, createMemo, createSignal, onCleanup } from "solid-js";
import { getAssignmentPageData } from "../../../components/assignment/assignment.data";
import AssignmentTabs from "../../../components/assignment/assignment-tabs";
import styles from "./assignment-work.module.scss";

type DraftState = Record<
	number,
	{
		answer: string;
		steps: string;
		solveMode: "just_answer" | "step_by_step" | "solve_together" | "handwritten";
	}
>;

type PersistedWorkspaceState = {
	drafts: DraftState;
	activeQuestionId: number | null;
	isSubmitted: boolean;
	submittedAt: string | null;
	lastSavedAt: string | null;
};

const solveModeOptions = [
	{ value: "just_answer", label: "Just answer" },
	{ value: "step_by_step", label: "Step by step" },
	{ value: "solve_together", label: "Solve together" },
	{ value: "handwritten", label: "Handwritten" },
] as const;

const isClient = typeof window !== "undefined";

const AssignmentWorkPage: Component = () => {
	const params = useParams();
	const assignmentData = createMemo(() => getAssignmentPageData(Number(params.id)));
	const storageKey = createMemo(() => `boostai-assignment-work-${params.id}`);

	const initialDrafts = createMemo<DraftState>(() => {
		const data = assignmentData();
		if (!data) return {};

		return Object.fromEntries(
			data.questions.map((question) => [
				question.id,
				{
					answer: question.initialAnswer ?? "",
					steps: "",
					solveMode: question.initialSolveMode ?? "just_answer",
				},
			]),
		) as DraftState;
	});

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

	const readPersistedState = (): PersistedWorkspaceState | null => {
		if (!isClient) return null;

		const raw = window.localStorage.getItem(storageKey());
		if (!raw) return null;

		try {
			return JSON.parse(raw) as PersistedWorkspaceState;
		} catch {
			return null;
		}
	};

	const writePersistedState = (overrideSavedAt?: string) => {
		if (!isClient || !assignmentData()) return;

		const savedAt = overrideSavedAt ?? new Date().toISOString();
		window.localStorage.setItem(
			storageKey(),
			JSON.stringify({
				drafts: drafts(),
				activeQuestionId: activeQuestionId(),
				isSubmitted: isSubmitted(),
				submittedAt: submittedAt(),
				lastSavedAt: savedAt,
			}),
		);
		setLastSavedAt(savedAt);
		setSaveState("saved");
	};

	createEffect(() => {
		const data = assignmentData();
		if (!data) return;

		const persisted = readPersistedState();
		setDrafts({
			...initialDrafts(),
			...(persisted?.drafts ?? {}),
		});
		setActiveQuestionId(persisted?.activeQuestionId ?? data.questions[0]?.id ?? null);
		setIsSubmitted(persisted?.isSubmitted ?? false);
		setSubmittedAt(persisted?.submittedAt ?? null);
		setLastSavedAt(persisted?.lastSavedAt ?? null);
		setSaveState("idle");
	});

	const questions = createMemo(() => assignmentData()?.questions ?? []);
	const currentQuestion = createMemo(() => questions().find((question) => question.id === activeQuestionId()) ?? questions()[0]);
	const activeDraft = createMemo(() => (currentQuestion() ? drafts()[currentQuestion()!.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 (saveState() === "saving") return "Saving draft...";
		if (saveState() === "saved" && lastSavedAt()) {
			return `Saved ${new Intl.DateTimeFormat("en-GB", {
				hour: "numeric",
				minute: "2-digit",
			}).format(new Date(lastSavedAt()!))}`;
		}

		return "Draft stored on this device";
	});

	let saveTimer: ReturnType<typeof setTimeout> | undefined;

	createEffect(() => {
		if (!isClient || !assignmentData()) return;

		drafts();
		activeQuestionId();
		isSubmitted();
		submittedAt();

		setSaveState("saving");
		if (saveTimer) clearTimeout(saveTimer);

		saveTimer = setTimeout(() => {
			writePersistedState();
		}, 350);
	});

	onCleanup(() => {
		if (saveTimer) clearTimeout(saveTimer);
	});

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

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

	const saveNow = () => {
		if (saveTimer) clearTimeout(saveTimer);
		writePersistedState();
	};

	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 = () => {
		saveNow();
		if (!isLastQuestion()) moveQuestion(1);
	};

	const handleSubmit = () => {
		const savedAt = new Date().toISOString();
		setIsSubmitted(true);
		setSubmittedAt(savedAt);
		writePersistedState(savedAt);
	};

	return (
		<main class={styles.page}>
			<div class={styles.shell}>
				<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="/dashboard" class={styles.backButton}>
								Back to dashboard
							</A>
						</section>
					}
				>
					{(data) => (
						<>
							<Show when={isSubmitted()}>
								<section class={styles.submitBanner}>
									<div>
										<p class={styles.bannerEyebrow}>Practice submitted</p>
										<h2>
											You answered {answeredCount()} of {data().questions.length} questions.
										</h2>
										<p>Your latest draft is saved locally. You can review the assignment or keep refining any answer.</p>
									</div>
									<A href={`/assignment/${data().id}`} class={styles.bannerLink}>
										Open review page
									</A>
								</section>
							</Show>

							<section class={styles.headerCard}>
								<div class={styles.headerTop}>
									<A href={`/assignment/${data().id}`} class={styles.backLink}>
										Back to review
									</A>
									<span class={styles.statusPill}>{data().statusLabel}</span>
								</div>

								<div class={styles.headerCopy}>
									<p class={styles.eyebrow}>{data().classroomName}</p>
									<h1>Work through {data().title}</h1>
									<p>Answer each question, show your working, and move at a steady pace. Your draft autosaves on this device while you work.</p>
								</div>

								<div class={styles.headerMeta}>
									<p class={styles.saveState}>{saveLabel()}</p>
									<button type="button" class={styles.submitButton} onClick={handleSubmit}>
										{remainingCount() > 0 ? `Submit ${answeredCount()}/${data().questions.length}` : "Submit assignment"}
									</button>
								</div>
							</section>

							<AssignmentTabs />

							<div class={styles.contentGrid}>
								<aside class={styles.navigator}>
									<div class={styles.navigatorHeader}>
										<h2>Question list</h2>
										<p>
											{answeredCount()} of {data().questions.length} answered
										</p>
									</div>

									<div class={styles.progressMeta}>
										<span>{remainingCount()} left</span>
										<span>{saveLabel()}</span>
									</div>

									<div class={styles.questionButtons}>
										<For each={data().questions}>
											{(question) => {
												const hasDraft = () => (drafts()[question.id]?.answer ?? "").trim().length > 0;

												return (
													<button
														type="button"
														classList={{
															[styles.questionButton]: true,
															[styles.activeQuestion]: activeQuestionId() === question.id,
															[styles.completedQuestion]: hasDraft(),
														}}
														onClick={() => setActiveQuestionId(question.id)}
													>
														<span>Q{question.order}</span>
														<small>{hasDraft() ? "Draft ready" : question.statusLabel}</small>
													</button>
												);
											}}
										</For>
									</div>
								</aside>

								<section class={styles.workspace}>
									<Show when={currentQuestion() && activeDraft()}>
										{() => (
											<>
												<div class={styles.workspaceHeader}>
													<div>
														<p class={styles.questionEyebrow}>Question {currentQuestion()!.order}</p>
														<h2>{currentQuestion()!.prompt}</h2>
														<p class={styles.questionStatus}>{currentQuestion()!.statusLabel}</p>
													</div>
													<div class={styles.questionMeta}>
														<span>{currentQuestion()!.topic}</span>
														<Show when={currentQuestion()!.subTopic}>
															<span>{currentQuestion()!.subTopic}</span>
														</Show>
														<span>{currentQuestion()!.difficulty}</span>
													</div>
												</div>

												<label class={styles.fieldGroup}>
													<span>Solve mode</span>
													<select value={activeDraft()!.solveMode} onInput={(event) => updateDraft("solveMode", event.currentTarget.value)}>
														<For each={solveModeOptions}>{(option) => <option value={option.value}>{option.label}</option>}</For>
													</select>
													<small class={styles.fieldHint}>Pick the mode that best matches how you want to think through this question.</small>
												</label>

												<label class={styles.fieldGroup}>
													<span>Your answer</span>
													<input
														type="text"
														value={activeDraft()!.answer}
														onInput={(event) => updateDraft("answer", event.currentTarget.value)}
														placeholder="Type your final answer"
													/>
													<small class={styles.fieldHint}>Keep this short — your final number, fraction, or expression.</small>
												</label>

												<label class={styles.fieldGroup}>
													<span>Working / steps</span>
													<textarea
														rows={8}
														value={activeDraft()!.steps}
														onInput={(event) => updateDraft("steps", event.currentTarget.value)}
														placeholder="Write your method here. For example: find a common denominator, simplify, then check your final answer."
													/>
													<small class={styles.fieldHint}>Show enough working that you could explain it back to your teacher later.</small>
												</label>

												<div class={styles.helperCard}>
													<p class={styles.helperEyebrow}>Helpful prompt</p>
													<p>Try to explain why each step makes sense, not just what number you wrote next.</p>
													<Show when={currentQuestion()!.showAnswerKey}>
														<div class={styles.answerReveal}>
															<span>Answer key</span>
															<strong>{currentQuestion()!.correctAnswer}</strong>
														</div>
													</Show>
												</div>

												<div class={styles.actionRow}>
													<button type="button" class={styles.secondaryButton} onClick={() => moveQuestion(-1)}>
														Previous
													</button>
													<div class={styles.primaryActions}>
														<button type="button" class={styles.secondaryButton} onClick={saveNow}>
															Save draft
														</button>
														<button type="button" class={styles.primaryButton} onClick={handleSaveAndContinue}>
															{isLastQuestion() ? "Save this question" : "Save and continue"}
														</button>
													</div>
												</div>

												<div class={styles.questionFooter}>
													<p>{saveLabel()}</p>
													<Show when={submittedAt()}>
														<p>
															Last submitted {new Intl.DateTimeFormat("en-GB", { hour: "numeric", minute: "2-digit" }).format(new Date(submittedAt()!))}
														</p>
													</Show>
												</div>
											</>
										)}
									</Show>
								</section>
							</div>
						</>
					)}
				</Show>
			</div>
		</main>
	);
};

export default AssignmentWorkPage;
