// Path: Frontend/src/components/assignment/teacher/assignment-teacher-review.data.ts

import { apiFetchJson } from "../../../lib/api";
import type {
	ApiAssignment,
	ApiAssignmentRedoPlanResponse,
	ApiAssignmentStudentQuestionDetail,
	ApiClassroom,
	ApiListResponse,
	ApiReviewQueueItem,
	ApiReviewSummary,
} from "../../../lib/api-types";
import {
	buildCloseSummary,
	buildQuestionTags,
	extractTopic,
	formatDateLabel,
	formatRelativeLabel,
	formatSolveMode,
	mapQueueReviewStatus,
	mapRedoPlan,
	mapTopicScores,
	normalizeScore,
	questionStatus,
	queueStatusLabel,
	queueTone,
} from "./assignment-teacher-review.formatters";
import type {
	TeacherAssignmentPassStatus,
	TeacherAssignmentReviewPageData,
	TeacherNextStepOutcome,
	TeacherRedoPlanData,
	TeacherReviewDraftFields,
	TeacherReviewQuestion,
} from "./assignment-teacher-review.types";

type UpdateTeacherAnswerReviewInput = TeacherReviewDraftFields & {
	status: "not_started" | "in_progress" | "submitted" | "reviewed";
	reviewTags: string[];
};

type UpdateAssignmentTeacherFeedbackInput = {
	teacherFeedback: string;
	passStatusOverride: TeacherAssignmentPassStatus | null;
	nextStepOutcome: TeacherNextStepOutcome | null;
};

export const getTeacherAssignmentReviewPageData = async (assignmentId: number, selectedStudentId?: number | null): Promise<TeacherAssignmentReviewPageData | null> => {
	if (!Number.isFinite(assignmentId) || assignmentId <= 0) return null;

	try {
		const assignment = await apiFetchJson<ApiAssignment>(`/api/assignments/${assignmentId}`);
		const [classrooms, summary, queueResponse] = await Promise.all([
			apiFetchJson<ApiListResponse<ApiClassroom>>(`/api/teachers/${assignment.teacher_id}/classrooms`),
			apiFetchJson<ApiReviewSummary>(`/api/assignments/${assignmentId}/review-summary`),
			apiFetchJson<ApiListResponse<ApiReviewQueueItem>>(`/api/assignments/${assignmentId}/review`),
		]);

		const classroom = classrooms.data.find((entry) => entry.id === assignment.classroom_id);
		const queue = queueResponse.data;
		const resolvedStudentId = selectedStudentId ?? queue[0]?.student_id ?? null;
		const selectedStudent = queue.find((item) => item.student_id === resolvedStudentId) ?? null;
		const questionDetails = resolvedStudentId
			? await apiFetchJson<ApiListResponse<ApiAssignmentStudentQuestionDetail>>(`/api/assignments/${assignmentId}/students/${resolvedStudentId}/questions`)
			: { data: [] as ApiAssignmentStudentQuestionDetail[] };
		const questions = questionDetails.data;
		const assignmentAiFeedback = questions[0]?.assignment_ai_feedback?.trim() || "";
		const assignmentTeacherFeedback = questions[0]?.assignment_teacher_feedback?.trim() || "";
		const overallScore = normalizeScore(questions[0]?.overall_score);
		const passThreshold =
			typeof assignment.pass_threshold === "number"
				? assignment.pass_threshold
				: typeof questions[0]?.pass_threshold === "number"
					? questions[0]!.pass_threshold!
					: 6;
		const nextStepOutcome = (questions[0]?.next_step_outcome as TeacherNextStepOutcome | undefined) ?? null;
		const passStatusOverride = (questions[0]?.pass_status_override as TeacherAssignmentPassStatus | undefined) ?? null;
		const passStatus = (questions[0]?.pass_status as TeacherAssignmentPassStatus | undefined) ?? "pending";
		const topic = extractTopic(assignment, questions);
		const reviewCoverage = summary.total_assigned > 0 ? Math.round((summary.reviewed / summary.total_assigned) * 100) : 0;

		return {
			assignmentId: assignment.id,
			title: assignment.title,
			classroomId: assignment.classroom_id,
			classroomName: classroom?.name ?? "Classroom",
			statusLabel: assignment.status === "draft" ? "Draft" : assignment.status === "closed" ? "Closed" : "Live",
			headline: selectedStudent ? `Review ${selectedStudent.student_name}'s responses for ${topic}` : `Review submissions for ${topic}`,
			description: selectedStudent
				? `${selectedStudent.student_name} has ${selectedStudent.answered_questions} answered question${selectedStudent.answered_questions === 1 ? "" : "s"}. Flag any response that still needs attention, then move to the next step when the rest is ready.`
				: "Choose a student from the review queue to inspect answers, working steps, and feedback status for this assignment.",
			dueLabel: formatDateLabel(assignment.due_at),
			stats: [
				{ label: "Assigned", value: `${summary.total_assigned}` },
				{ label: "Submitted", value: `${summary.submitted}` },
				{ label: "Reviewed", value: `${summary.reviewed}` },
				{ label: "Coverage", value: `${reviewCoverage}%` },
			],
			closeSummary: buildCloseSummary(assignment.status, queue),
			reviewQueue: queue.map((item) => ({
				studentId: item.student_id,
				studentName: item.student_name,
				email: item.student_email,
				reviewStatus: item.review_status,
				nextStepOutcome: mapQueueReviewStatus(item.next_step_outcome),
				submittedQuestions: item.submitted_questions,
				reviewedQuestions: item.reviewed_questions,
				progressLabel: `${item.reviewed_questions}/${item.total_questions} reviewed · ${item.answered_questions} answered`,
				statusLabel: queueStatusLabel(item),
				statusTone: queueTone(item),
				timestampLabel: formatRelativeLabel(item.latest_submitted_at ?? item.latest_reviewed_at, "No submission yet"),
			})),
			selectedStudentId: selectedStudent?.student_id ?? null,
			selectedStudentName: selectedStudent?.student_name ?? null,
			selectedStudentEmail: selectedStudent?.student_email ?? null,
			selectedStudentProgress: selectedStudent ? `${selectedStudent.reviewed_questions} of ${selectedStudent.total_questions} reviewed · ${selectedStudent.submitted_questions} waiting` : null,
			selectedStudentReviewStatus: selectedStudent?.review_status ?? null,
			selectedStudentSubmittedQuestions: selectedStudent?.submitted_questions ?? 0,
			selectedStudentReviewedQuestions: selectedStudent?.reviewed_questions ?? 0,
			assignmentAiFeedback,
			assignmentTeacherFeedback,
			overallScore,
			passThreshold,
			nextStepOutcome,
			passStatusOverride,
			passStatus,
			coachCard: {
				title: selectedStudent ? "Teacher review notes" : "Review queue guidance",
				description: selectedStudent
					? "Flag only the responses that still need attention. Moving to the next step will treat everything else as reviewed."
					: "Start with the freshest submitted work, then move through the queue in order of urgency.",
				items: [`${summary.submitted} submission${summary.submitted === 1 ? "" : "s"} waiting`, `${summary.in_progress} in progress`, `${summary.not_started} not started`],
			},
			questions: questions.map((question): TeacherReviewQuestion => {
				const status = questionStatus(question);
				return {
					id: question.question_id,
					order: question.position,
					prompt: question.prompt,
					subject: question.subject,
					source: question.source,
					questionTags: buildQuestionTags(question),
					answerId: question.answer_id ?? null,
					answerStatus: (question.answer_status as TeacherReviewQuestion["answerStatus"]) ?? null,
					statusLabel: status.statusLabel,
					statusTone: status.statusTone,
					answerText: question.answer_text?.trim() || "No answer has been submitted for this question yet.",
					solveModeLabel: formatSolveMode(question.solve_mode),
					workingSteps: question.working_steps?.trim() || "",
					correctAnswer: question.correct_answer?.trim() || null,
					isCorrect: typeof question.is_correct === "boolean" ? question.is_correct : null,
					reviewNeedsAttention: Boolean(question.review_needs_attention),
					reviewIssueReason: question.review_issue_reason?.trim() || "",
					reviewCorrectnessScore: normalizeScore(question.review_correctness_score),
					reviewUnderstandingScore: normalizeScore(question.review_understanding_score),
					reviewQuestionScore: normalizeScore(question.review_question_score),
					reviewConfidence: normalizeScore(question.review_confidence),
					correctnessLabel:
						typeof question.is_correct === "boolean"
							? question.is_correct
								? "Matches the saved correct answer"
								: "Does not match the saved correct answer yet"
							: question.correct_answer
								? "Correct answer is available for comparison"
								: "No correct answer saved yet",
					submittedLabel: formatDateLabel(question.submitted_at, "Not submitted"),
					reviewedLabel: formatDateLabel(question.reviewed_at, "Not reviewed yet"),
				};
			}),
		};
	} catch (error) {
		if (error instanceof Error && error.message === "not_found") {
			return null;
		}
		throw error;
	}
};

export const updateTeacherAnswerReview = async (answerId: number, input: UpdateTeacherAnswerReviewInput) => {
	return await apiFetchJson(`/api/answers/${answerId}/review`, {
		method: "PATCH",
		allowNoContent: true,
		body: JSON.stringify({
			status: input.status,
			review_needs_attention: input.reviewNeedsAttention,
			review_issue_reason: input.reviewIssueReason || null,
			review_correctness_score: input.reviewCorrectnessScore,
			review_understanding_score: input.reviewUnderstandingScore,
			review_question_score: input.reviewQuestionScore,
			review_confidence: input.reviewConfidence,
			review_tags: input.reviewTags,
		}),
	});
};

export const updateAssignmentTeacherFeedback = async (assignmentId: number, studentId: number, input: UpdateAssignmentTeacherFeedbackInput) => {
	return await apiFetchJson(`/api/assignments/${assignmentId}/students/${studentId}/feedback`, {
		method: "PATCH",
		allowNoContent: true,
		body: JSON.stringify({
			teacher_feedback: input.teacherFeedback,
			pass_status_override: input.passStatusOverride,
			next_step_outcome: input.nextStepOutcome,
		}),
	});
};

export const closeTeacherAssignment = async (assignmentId: number) => {
	return await apiFetchJson<ApiAssignment>(`/api/assignments/${assignmentId}/close`, {
		method: "POST",
		parseErrorMessage: true,
	});
};

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

	const [reviewData, redoPlan] = await Promise.all([
		getTeacherAssignmentReviewPageData(assignmentId, studentId),
		apiFetchJson<ApiAssignmentRedoPlanResponse>(`/api/assignments/${assignmentId}/students/${studentId}/redo-plan`, { notFoundAsNull: true }),
	]);

	if (!reviewData || !redoPlan || !reviewData.selectedStudentId || !reviewData.selectedStudentName || !reviewData.selectedStudentEmail) {
		return null;
	}

	return {
		assignmentId: reviewData.assignmentId,
		title: reviewData.title,
		classroomId: reviewData.classroomId,
		classroomName: reviewData.classroomName,
		selectedStudentId: reviewData.selectedStudentId,
		selectedStudentName: reviewData.selectedStudentName,
		selectedStudentEmail: reviewData.selectedStudentEmail,
		teacherFeedback: redoPlan.teacher_feedback?.trim() || reviewData.assignmentTeacherFeedback,
		generatedAtLabel: redoPlan.redo_plan_generated_at ? formatRelativeLabel(redoPlan.redo_plan_generated_at) : null,
		weaknessSummary: {
			studentId: redoPlan.weakness_summary.student_id,
			topicScores: mapTopicScores(redoPlan.weakness_summary),
			weakTags: Array.isArray(redoPlan.weakness_summary.weak_tags) ? redoPlan.weakness_summary.weak_tags.filter(Boolean) : [],
			recentIssues: Array.isArray(redoPlan.weakness_summary.recent_issues) ? redoPlan.weakness_summary.recent_issues.filter(Boolean) : [],
		},
		plan: mapRedoPlan(redoPlan.plan),
		error: redoPlan.error?.trim() || null,
	};
};
