import type {
	ApiAssignment,
	ApiAssignmentStudentQuestionDetail,
	ApiRedoPlan,
	ApiRedoPlanQuestion,
	ApiReviewQueueItem,
	ApiStudentWeaknessSummary,
} from "../../../lib/api-types";
import type {
	TeacherAssignmentCloseSummary,
	TeacherNextStepOutcome,
	TeacherRedoPlanQuestion,
	TeacherReviewQueueItem,
} from "./assignment-teacher-review.types";
import { assignmentUiCopy } from "~/content/ui-copy";

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

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

export const formatRelativeLabel = (value: string | null | undefined, fallback = "No recent update") => {
	if (!value) return fallback;

	const timestamp = new Date(value).getTime();
	if (Number.isNaN(timestamp)) return fallback;

	const diffMinutes = Math.max(0, Math.round((Date.now() - timestamp) / 60000));
	if (diffMinutes < 1) return "Just now";
	if (diffMinutes < 60) return `${diffMinutes} min ago`;
	const diffHours = Math.round(diffMinutes / 60);
	if (diffHours < 24) return `${diffHours} hr ago`;
	const diffDays = Math.round(diffHours / 24);
	return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
};

export const formatSolveMode = (value: ApiAssignmentStudentQuestionDetail["solve_mode"]) => {
	switch (value) {
		case "step_by_step":
			return "Step by step";
		case "solve_together":
			return "Solve together";
		case "handwritten":
			return "Handwritten";
		case "just_answer":
			return "Just answer";
		default:
			return null;
	}
};

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

export const queueTone = (item: ApiReviewQueueItem): TeacherReviewQueueItem["statusTone"] => {
	if (item.review_status === "submitted") return "review";
	if (item.review_status === "in_progress" || item.reviewed_questions > 0 || item.answered_questions > 0) return "progress";
	if (item.next_step_outcome === "accept") return "success";
	if (item.next_step_outcome === "redo" || item.next_step_outcome === "support") return "review";
	return "muted";
};

export const queueStatusLabel = (item: ApiReviewQueueItem) => {
	if (item.review_status === "submitted") return "Submitted";
	if (item.review_status === "in_progress" || item.reviewed_questions > 0 || item.answered_questions > 0) return "In progress";
	if (item.next_step_outcome === "redo") return "Redo";
	if (item.next_step_outcome === "accept") return "Accept";
	if (item.next_step_outcome === "support") return "Support";
	return "Not started";
};

export const buildCloseSummary = (assignmentStatus: ApiAssignment["status"], queue: ApiReviewQueueItem[]): TeacherAssignmentCloseSummary => {
	if (assignmentStatus === "closed") {
		return {
			state: "closed",
			canClose: false,
			blockers: [],
			summary: "This assignment is already closed.",
		};
	}

	if (queue.length === 0) {
		return {
			state: "blocked",
			canClose: false,
			blockers: ["No students have been assigned yet."],
			summary: "Assign at least one student before closing this assignment.",
		};
	}

	const blockers = queue.flatMap((item) => {
		if (item.submitted_questions > 0 || item.review_status === "submitted") {
			return [`${item.student_name} still has submitted work waiting for review.`];
		}

		if (item.in_progress_questions > 0 || item.review_status === "in_progress") {
			return [`${item.student_name} still has work in progress.`];
		}

		if (item.answered_questions === 0 || item.review_status === "not_started") {
			return [`${item.student_name} has not started this assignment yet.`];
		}

		if (!item.next_step_outcome) {
			return [`${item.student_name} still needs a next-step decision.`];
		}

		return [] as string[];
	});

	if (blockers.length > 0) {
		return {
			state: "blocked",
			canClose: false,
			blockers,
			summary: `${blockers.length} blocker${blockers.length === 1 ? "" : "s"} still need attention before this assignment can be closed.`,
		};
	}

	return {
		state: "ready",
		canClose: true,
		blockers: [],
		summary: "All assigned students have been reviewed and given a next-step decision. This assignment is ready to close.",
	};
};

export const questionStatus = (question: ApiAssignmentStudentQuestionDetail) => {
	if (question.review_needs_attention) {
		return { statusLabel: assignmentUiCopy.teacherReview.status.needsAttention, statusTone: "review" as const };
	}
	if (question.answer_status === "reviewed") {
		return { statusLabel: assignmentUiCopy.teacherReview.status.reviewed, statusTone: "success" as const };
	}
	if (question.answer_status === "submitted") {
		return { statusLabel: assignmentUiCopy.teacherReview.status.submitted, statusTone: "review" as const };
	}
	if (question.answer_status === "in_progress") {
		return { statusLabel: assignmentUiCopy.teacherReview.status.inProgress, statusTone: "progress" as const };
	}
	return { statusLabel: assignmentUiCopy.teacherReview.status.noAnswerYet, statusTone: "muted" as const };
};

export const normalizeScore = (value: number | null | undefined) => (typeof value === "number" && Number.isFinite(value) ? value : null);

export const normalizeTags = (value: string[] | null | undefined) =>
	Array.isArray(value)
		? value.map((tag) => tag.trim()).filter(Boolean)
		: [];

export const buildQuestionTags = (question: ApiAssignmentStudentQuestionDetail) => {
	const tags = [...normalizeTags(question.question_tags), question.subject?.trim() || "", formatSolveMode(question.solve_mode) || ""].filter(Boolean);
	return Array.from(new Set(tags));
};

export const formatTopicLabel = (value: string) =>
	value
		.split("_")
		.map((part) => (part ? part[0]!.toUpperCase() + part.slice(1) : part))
		.join(" ");

export const formatDifficultyLabel = (value: string) => (value ? value[0]!.toUpperCase() + value.slice(1).toLowerCase() : value);

export const mapTopicScores = (summary: ApiStudentWeaknessSummary) =>
	Object.entries(summary.topic_scores ?? {})
		.map(([topic, score]) => ({ topic: formatTopicLabel(topic), score }))
		.sort((left, right) => left.score - right.score || left.topic.localeCompare(right.topic));

export const mapRedoPlanQuestion = (item: ApiRedoPlanQuestion): TeacherRedoPlanQuestion => ({
	topic: formatTopicLabel(item.topic),
	topicKey: item.topic,
	difficulty: formatDifficultyLabel(item.difficulty),
	difficultyKey: item.difficulty,
	tags: Array.isArray(item.tags) ? item.tags.filter(Boolean) : [],
	reason: item.reason?.trim() || "No reason provided.",
});

export const mapRedoPlan = (plan: ApiRedoPlan | null | undefined) => {
	if (!plan) return null;
	return {
		rationale: plan.rationale?.trim() || "No rationale provided.",
		questionSet: Array.isArray(plan.questionSet) ? plan.questionSet.map(mapRedoPlanQuestion) : [],
	};
};

export const mapQueueReviewStatus = (value: ApiReviewQueueItem["next_step_outcome"]): TeacherNextStepOutcome | null => value ?? null;
