// Path: Frontend/src/components/dashboard/messages/dashboard-messages.data.ts

import { apiFetchJson } from "../../../lib/api";
import type { ApiListResponse } from "../../../lib/api-types";
import type { AppRole } from "../../../lib/routes";
import { getDashboardMessageThreadHref } from "../../../lib/routes";
import type { TopbarMessageItem } from "../shared/dashboard-types";

type MessageRecipient = {
	id: number;
	email: string;
	role: "student" | "teacher";
	full_name: string;
	preferred_name: string | null;
	profile_icon_url: string | null;
	headline: string | null;
};

export type MessageParticipant = {
	id: number;
	email: string;
	role: "student" | "teacher";
	full_name: string;
	preferred_name: string | null;
	profile_icon_url: string | null;
	headline: string | null;
	joined_at: string | null;
	last_read_at: string | null;
	archived_at: string | null;
};

type MessageSender = {
	id: number;
	email: string;
	role: string;
	full_name: string;
	preferred_name: string | null;
	profile_icon_url: string | null;
	headline?: string | null;
};

type MessageItem = {
	id: number;
	thread_id: number;
	body: string;
	created_at: string | null;
	updated_at: string | null;
	mine: boolean;
	sender: MessageSender;
};

type MessageThreadSummary = {
	id: number;
	subject: string;
	created_by_user_id: number;
	created_at: string | null;
	updated_at: string | null;
	unread_count: number;
	last_message_id: number;
	last_message_body: string | null;
	last_message_created_at: string | null;
	last_message_sender?: MessageSender | null;
	participants: MessageParticipant[];
};

type MessageThreadDetail = {
	id: number;
	subject: string;
	created_by_user_id: number;
	created_at: string | null;
	updated_at: string | null;
	unread_count: number;
	last_read_at: string | null;
	participants: MessageParticipant[];
	messages: MessageItem[];
};

type DashboardMessagesInboxData = {
	stats: Array<{ label: string; value: string }>;
	threads: MessageThreadSummary[];
	recipients: MessageRecipient[];
};

type DashboardTopbarMessagesData = {
	messageCount: number;
	unreadThreadCount: number;
	topbarMessages: TopbarMessageItem[];
};

export const getDashboardMessagesInboxData = async (_currentUserId: number): Promise<DashboardMessagesInboxData> => {
	const [threadsResponse, recipientsResponse] = await Promise.all([
		apiFetchJson<ApiListResponse<MessageThreadSummary>>("/api/messages/threads", { parseErrorMessage: true }),
		apiFetchJson<ApiListResponse<MessageRecipient>>("/api/messages/recipients", { parseErrorMessage: true }),
	]);

	const unreadThreads = threadsResponse.data.filter((thread) => thread.unread_count > 0).length;
	const unreadMessages = threadsResponse.data.reduce((sum, thread) => sum + thread.unread_count, 0);

	return {
		stats: [
			{ label: "Open threads", value: String(threadsResponse.data.length) },
			{ label: "Unread threads", value: String(unreadThreads) },
			{ label: "Unread messages", value: String(unreadMessages) },
			{ label: "Available contacts", value: String(recipientsResponse.data.length) },
		],
		threads: threadsResponse.data,
		recipients: recipientsResponse.data,
	};
};

export const getDashboardTopbarMessagesData = async (currentUserId: number, role: AppRole): Promise<DashboardTopbarMessagesData> => {
	const threadsResponse = await apiFetchJson<ApiListResponse<MessageThreadSummary>>("/api/messages/threads", { parseErrorMessage: true });
	const unreadThreadCount = threadsResponse.data.filter((thread) => thread.unread_count > 0).length;
	const unreadMessageCount = threadsResponse.data.reduce((sum, thread) => sum + thread.unread_count, 0);

	return {
		messageCount: unreadThreadCount,
		unreadThreadCount,
		topbarMessages: threadsResponse.data.slice(0, 5).map((thread) => {
			const peer = thread.participants.find((participant) => participant.id !== currentUserId) ?? thread.participants[0];
			const sender = peer ? displayName(peer) : thread.subject;
			const preview = thread.last_message_body?.trim() || `Subject: ${thread.subject}`;

			return {
				sender,
				initials: initialsFor(peer ?? { full_name: sender }),
				preview,
				timestamp: formatShortTimestamp(thread.last_message_created_at ?? thread.updated_at),
				actionHref: getDashboardMessageThreadHref(role, thread.id),
			};
		}),
	};
};

export const getMessageThreadDetail = (threadId: number) => apiFetchJson<MessageThreadDetail>(`/api/messages/threads/${threadId}`, { parseErrorMessage: true });

export const createMessageThread = (input: { subject: string; recipientId: number }) =>
	apiFetchJson<{ thread_id: number }>("/api/messages/threads", {
		method: "POST",
		parseErrorMessage: true,
		body: JSON.stringify({
			subject: input.subject,
			recipient_ids: [input.recipientId],
		}),
	});

export const createThreadReply = (threadId: number, input: { body: string }) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}/messages`, {
		method: "POST",
		parseErrorMessage: true,
		body: JSON.stringify(input),
	});

export const updateThreadSubject = (threadId: number, input: { subject: string }) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}`, {
		method: "PATCH",
		parseErrorMessage: true,
		body: JSON.stringify(input),
	});

export const deleteThread = (threadId: number) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}`, {
		method: "DELETE",
		parseErrorMessage: true,
	});

export const updateThreadMessage = (threadId: number, messageId: number, input: { body: string }) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}/messages/${messageId}`, {
		method: "PATCH",
		parseErrorMessage: true,
		body: JSON.stringify(input),
	});

export const deleteThreadMessage = (threadId: number, messageId: number) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}/messages/${messageId}`, {
		method: "DELETE",
		parseErrorMessage: true,
	});

export const markThreadRead = (threadId: number) =>
	apiFetchJson<{ status: string }>(`/api/messages/threads/${threadId}/read`, {
		method: "PATCH",
		parseErrorMessage: true,
	});

export const displayName = (person: { preferred_name?: string | null; full_name: string }) => person.preferred_name?.trim() || person.full_name;

export const initialsFor = (person: { preferred_name?: string | null; full_name: string }) => {
	const value = displayName(person).trim();
	if (!value) return "U";

	const parts = value.split(/\s+/).filter(Boolean);
	if (parts.length === 1) return parts[0]!.slice(0, 2).toUpperCase();
	return `${parts[0]?.[0] ?? ""}${parts[1]?.[0] ?? ""}`.toUpperCase();
};

export const roleLabel = (role: string) => (role === "teacher" ? "Teacher" : role === "student" ? "Student" : role);

export const formatShortTimestamp = (value: string | null) => {
	if (!value) return "Just now";

	const date = new Date(value);
	const now = Date.now();
	const diffMs = now - date.getTime();
	const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
	const diffDays = Math.floor(diffHours / 24);

	if (diffHours < 1) return "Now";
	if (diffHours < 24) return `${diffHours}h ago`;
	if (diffDays < 7) return `${diffDays}d ago`;

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

export const formatMessageTimestamp = (value: string | null) => {
	if (!value) return "Just now";

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

export const wasMessageEdited = (createdAt: string | null, updatedAt: string | null) => {
	if (!createdAt || !updatedAt) return false;
	return new Date(updatedAt).getTime() - new Date(createdAt).getTime() > 1000;
};
