import { getAssignmentReviewHref } from "../../../lib/routes";
import type { ApiAssignment, ApiClassroom, ApiQuestion, ApiReviewSummary } from "../../../lib/api-types";
import type {
	TeacherAssignmentSetupQuestion,
	TeacherAssignmentsFocusItem,
	TeacherAssignmentTone,
} from "./dashboard-teacher-assignments.types";

export const FIXED_PASS_THRESHOLD = 6.0;

export const buildEmptyReviewSummary = (assignmentId: number): ApiReviewSummary => ({
	assignment_id: assignmentId,
	total_questions: 0,
	total_assigned: 0,
	not_started: 0,
	in_progress: 0,
	submitted: 0,
	reviewed: 0,
});

const statusLabelForQuestion = (status: string) => {
	if (status === "draft") return "Draft question";
	if (status === "published") return "Published question";
	return status.replace(/_/g, " ").replace(/\b\w/g, (match) => match.toUpperCase());
};

const difficultyLabelForQuestion = (difficulty: string | null | undefined) => {
	if (!difficulty) return "Mixed difficulty";
	return difficulty.replace(/_/g, " ").replace(/\b\w/g, (match) => match.toUpperCase());
};

const sourceLabelForQuestion = (source: string | null | undefined) => {
	const normalized = source?.trim();
	if (!normalized) return "Question bank";
	if (normalized === "rng_generated") return "RNG generated";
	return normalized.replace(/_/g, " ").replace(/\b\w/g, (match) => match.toUpperCase());
};

const promptPreviewForQuestion = (prompt: string) => {
	const cleaned = prompt.replace(/\s+/g, " ").trim();
	if (cleaned.length <= 150) return cleaned;
	return `${cleaned.slice(0, 147).trimEnd()}…`;
};

export const mapSetupQuestion = (question: ApiQuestion): TeacherAssignmentSetupQuestion => ({
	id: question.id,
	title: question.title,
	promptPreview: promptPreviewForQuestion(question.prompt),
	subjectLabel: question.subject?.trim() || "General",
	difficultyLabel: difficultyLabelForQuestion(question.difficulty),
	sourceLabel: sourceLabelForQuestion(question.source),
	statusLabel: statusLabelForQuestion(question.status),
});

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

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

export const formatDetailedDate = (value: string | null | undefined, fallback = "Not scheduled yet") => {
	if (!value) return fallback;

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

export const formatDateTimeLocalInput = (value: string | null | undefined) => {
	if (!value) return "";

	const date = new Date(value);
	if (Number.isNaN(date.getTime())) return "";

	const localDate = new Date(date.getTime() - date.getTimezoneOffset() * 60_000);
	return localDate.toISOString().slice(0, 16);
};

const statusLabelForAssignment = (assignment: ApiAssignment, summary: ApiReviewSummary) => {
	if (assignment.status === "closed") return "Closed";
	if (summary.submitted > 0) return "Needs review";
	if (summary.in_progress > 0) return "In progress";
	return "Live";
};

const toneForAssignment = (assignment: ApiAssignment, summary: ApiReviewSummary): TeacherAssignmentTone => {
	if (assignment.status === "closed") return "closed";
	if (summary.submitted > 0) return "review";
	return "live";
};

export const sortDueSoonest = (left: ApiAssignment, right: ApiAssignment) => {
	const leftTime = left.due_at ? new Date(left.due_at).getTime() : Number.POSITIVE_INFINITY;
	const rightTime = right.due_at ? new Date(right.due_at).getTime() : Number.POSITIVE_INFINITY;
	return leftTime - rightTime;
};

export const sortNeedsAttention = (
	left: ApiAssignment,
	right: ApiAssignment,
	summaries: Map<number, ApiReviewSummary>,
) => {
	const leftSummary = summaries.get(left.id) ?? buildEmptyReviewSummary(left.id);
	const rightSummary = summaries.get(right.id) ?? buildEmptyReviewSummary(right.id);
	const leftPriority = leftSummary.submitted > 0 ? 0 : left.status === "assigned" ? 1 : 2;
	const rightPriority = rightSummary.submitted > 0 ? 0 : right.status === "assigned" ? 1 : 2;
	return leftPriority - rightPriority || sortDueSoonest(left, right);
};

export const isIndividualRedoAssignment = (assignment: ApiAssignment) => {
	const normalizedTitle = assignment.title.trim().toLowerCase();

	// Current student-specific redo assignments are created from the redo-plan page
	// with the deterministic title shape: "{studentName} redo • {originalTitle}".
	// Once we add a first-class assignment type or source field, replace this
	// heuristic with that canonical backend signal.
	return normalizedTitle.includes(" redo • ");
};

export const buildAssignmentItem = (
	assignment: ApiAssignment,
	classroom: ApiClassroom | undefined,
	summary: ApiReviewSummary,
	studentCount: number,
): TeacherAssignmentsFocusItem => {
	const canOpenTeacherReview = assignment.status === "closed" || summary.submitted > 0 || summary.in_progress > 0;

	const reviewedCoverage = summary.total_assigned > 0 ? Math.round((summary.reviewed / summary.total_assigned) * 100) : 0;
	const note =
		summary.submitted > 0
			? `${summary.submitted} submission${summary.submitted === 1 ? " is" : "s are"} waiting for feedback right now.`
			: summary.in_progress > 0
				? `${summary.in_progress} student${summary.in_progress === 1 ? " is" : "s are"} actively working through this assignment.`
				: "Students can start this assignment as soon as they are ready.";

	return {
		id: assignment.id,
		title: assignment.title,
		classroomName: classroom?.name ?? "Classroom",
		statusLabel: statusLabelForAssignment(assignment, summary),
		tone: toneForAssignment(assignment, summary),
		dueLabel: `Due ${formatShortDate(assignment.due_at)}`,
		queueLabel: summary.submitted > 0 ? `${summary.submitted} waiting for review` : summary.in_progress > 0 ? `${summary.in_progress} in progress` : `${summary.not_started} not started`,
		coverageLabel: summary.total_assigned > 0 ? `${reviewedCoverage}% reviewed` : "No student work yet",
		workloadLabel: `${summary.total_questions} question${summary.total_questions === 1 ? "" : "s"} · ${studentCount} student${studentCount === 1 ? "" : "s"}`,
		note,
		primaryHref: canOpenTeacherReview ? getAssignmentReviewHref("teacher", assignment.id) : null,
	};
};
