// Path: Frontend/src/components/assignment/work/assignment-work.data.ts

import { apiFetchJson } from "../../../lib/api";
import type { ApiAssignment, ApiAssignmentStudentQuestionDetail, ApiClassroom, ApiListResponse, ApiUser } from "../../../lib/api-types";
import { getAssignmentReviewHref } from "../../../lib/routes";
import type { AssignmentPageData } from "../shared/assignment-types";

export type AssignmentWorkQuestion = AssignmentPageData["questions"][number] & {
	answerId: number | null;
	answerStatus: "not_started" | "in_progress" | "submitted" | "reviewed";
	submittedAt: string | null;
	updatedAt: string | null;
	workingSteps: string;
	correctAnswer: string | null;
	isCorrect: boolean | null;
};

export type AssignmentWorkPageData = Omit<AssignmentPageData, "questions" | "description" | "headline" | "primaryAction"> & {
	headline: string;
	description: string;
	primaryAction: string;
	questions: AssignmentWorkQuestion[];
};

type UpsertAssignmentAnswerInput = {
	assignmentId: number;
	questionId: number;
	answerText: string | null;
	solveMode: "just_answer" | "step_by_step" | "solve_together" | "handwritten";
	workingSteps: string | null;
	status: "not_started" | "in_progress" | "submitted" | "reviewed";
	submittedAt?: string | null;
};

const formatDateLabel = (value: string | null) => {
	if (!value) return "No due date";

	return new Intl.DateTimeFormat("en-GB", {
		weekday: "short",
		month: "short",
		day: "numeric",
	}).format(new Date(value));
};

const extractTopic = (assignment: ApiAssignment, questions: ApiAssignmentStudentQuestionDetail[]) => {
	const fromInstructions = assignment.instructions?.match(/^Topic:\s*(.+)$/i)?.[1]?.trim();
	if (fromInstructions) return fromInstructions;

	return questions[0]?.subject ?? "Assignment";
};

const deriveStudentStatus = (questions: ApiAssignmentStudentQuestionDetail[], assignmentStatus: ApiAssignment["status"]) => {
	const total = questions.length;
	const answered = questions.filter((question) => question.answer_id).length;
	const submitted = questions.filter((question) => question.answer_status === "submitted" || question.answer_status === "reviewed").length;

	if (answered === 0) return "NOT_STARTED" as const;
	if (submitted === total || assignmentStatus === "closed") return "SUBMITTED" as const;
	return "IN_PROGRESS" as const;
};

const deriveStatusLabel = (status: AssignmentPageData["status"]) => {
	switch (status) {
		case "SUBMITTED":
			return "Submitted";
		case "IN_PROGRESS":
			return "In progress";
		default:
			return "Not started";
	}
};

const mapQuestionStatus = (question: ApiAssignmentStudentQuestionDetail) => {
	if (question.answer_status === "reviewed") {
		return {
			statusLabel: "Reviewed",
			statusTone: "success" as const,
			answerStatus: "reviewed" as const,
		};
	}

	if (question.answer_status === "submitted") {
		return {
			statusLabel: "Submitted",
			statusTone: "warning" as const,
			answerStatus: "submitted" as const,
		};
	}

	if (question.answer_status === "in_progress") {
		return {
			statusLabel: "Draft saved",
			statusTone: "warning" as const,
			answerStatus: "in_progress" as const,
		};
	}

	return {
		statusLabel: "Not started",
		statusTone: "muted" as const,
		answerStatus: "not_started" as const,
	};
};

export const getAssignmentWorkPageData = async (assignmentId: number, studentId: number): Promise<AssignmentWorkPageData | null> => {
	if (!Number.isFinite(assignmentId) || assignmentId <= 0) return null;

	try {
		const assignment = await apiFetchJson<ApiAssignment>(`/api/assignments/${assignmentId}`);

		const [student, teacher, classrooms, questionDetails] = await Promise.all([
			apiFetchJson<ApiUser>(`/api/users/${studentId}`),
			apiFetchJson<ApiUser>(`/api/users/${assignment.teacher_id}`),
			apiFetchJson<ApiListResponse<ApiClassroom>>(`/api/teachers/${assignment.teacher_id}/classrooms`),
			apiFetchJson<ApiListResponse<ApiAssignmentStudentQuestionDetail>>(`/api/assignments/${assignmentId}/students/${studentId}/questions`),
		]);

		const classroom = classrooms.data.find((entry) => entry.id === assignment.classroom_id);
		const questions = questionDetails.data;
		const topic = extractTopic(assignment, questions);
		const answeredCount = questions.filter((question) => question.answer_id).length;
		const submittedCount = questions.filter((question) => question.answer_status === "submitted" || question.answer_status === "reviewed").length;
		const status = deriveStudentStatus(questions, assignment.status);
		const statusLabel = deriveStatusLabel(status);

		return {
			id: assignment.id,
			title: assignment.title,
			topic,
			status,
			statusLabel,
			dueLabel: formatDateLabel(assignment.due_at),
			studentName: student.full_name,
			classroomName: classroom?.name ?? "Classroom",
			tutorName: teacher.full_name,
			headline: `Work through ${assignment.title}`,
			description: `Write your final answer here, keep your working notes in sync, and save each question back to the live assignment as you go.`,
			primaryAction: status === "SUBMITTED" ? "Review submission" : "Keep working",
			primaryHref: getAssignmentReviewHref("student", assignment.id),
			stats: [
				{ label: "Status", value: statusLabel },
				{ label: "Due", value: formatDateLabel(assignment.due_at) },
				{ label: "Questions", value: `${questions.length}` },
				{ label: "Saved / submitted", value: `${submittedCount}/${questions.length}` },
			],
			coachCard: {
				title: "Workspace notes",
				description: `Your final answer, solve mode, and working notes all sync to the backend when you save.`,
				items: [`${answeredCount} questions have an answer saved`, `${submittedCount} questions are submitted`, `${Math.max(questions.length - answeredCount, 0)} questions still untouched`],
			},
			questions: questions.map((question) => {
				const questionStatus = mapQuestionStatus(question);

				return {
					id: question.question_id,
					order: question.position,
					prompt: question.prompt,
					topic: question.subject,
					subTopic: question.source,
					difficulty: "Backend",
					marks: null,
					statusLabel: questionStatus.statusLabel,
					statusTone: questionStatus.statusTone,
					responseLabel: question.answer_id ? "Your saved answer" : "Status",
					responseValue: question.answer_text?.trim() || "No saved answer yet",
					feedback: question.teacher_feedback?.trim() || question.ai_feedback?.trim() || "Save a draft to keep your latest workspace on the assignment.",
					solveModeLabel: undefined,
					initialAnswer: question.answer_text?.trim() || "",
					initialSolveMode: question.solve_mode ?? "just_answer",
					showAnswerKey: Boolean(question.correct_answer && question.answer_id),
					correctAnswer: question.correct_answer?.trim() || null,
					isCorrect: typeof question.is_correct === "boolean" ? question.is_correct : null,
					answerId: question.answer_id ?? null,
					answerStatus: questionStatus.answerStatus,
					submittedAt: question.submitted_at ?? null,
					updatedAt: question.answer_updated_at ?? null,
					workingSteps: question.working_steps ?? "",
				};
			}),
		};
	} catch (error) {
		if (error instanceof Error && error.message === "not_found") {
			return null;
		}

		throw error;
	}
};

export const upsertAssignmentAnswer = async (input: UpsertAssignmentAnswerInput) => {
	return apiFetchJson<{
		id: number;
		assignment_id: number;
		question_id: number;
		student_id: number;
		answer_text?: string;
		solve_mode: string;
		working_steps?: string;
		status: string;
		submitted_at?: string;
		updated_at?: string;
	}>("/api/answers", {
		method: "POST",
		parseErrorMessage: true,
		body: JSON.stringify({
			assignment_id: input.assignmentId,
			question_id: input.questionId,
			answer_text: input.answerText,
			solve_mode: input.solveMode,
			working_steps: input.workingSteps,
			status: input.status,
			submitted_at: input.submittedAt ?? null,
		}),
	});
};
