// Path: Frontend/src/components/dashboard/messages/dashboard-messages.page.tsx

import type { Component } from "solid-js";
import { createEffect, createMemo, createResource, createSignal } from "solid-js";
import { createMessageThread, createThreadReply, deleteThread, deleteThreadMessage, getDashboardMessagesInboxData, getMessageThreadDetail, markThreadRead, updateThreadMessage, updateThreadSubject } from "./dashboard-messages.data";
import styles from "./dashboard-messages.module.scss";
import { DashboardMessagesMailbox, DashboardMessagesThreadPanel } from "./dashboard-messages.sections";

type DashboardMessagesPageProps = {
	currentUserId: number;
	initialThreadId?: number | null;
};

const DashboardMessagesPage: Component<DashboardMessagesPageProps> = (props) => {
	const [inboxData, { refetch: refetchInbox }] = createResource(() => props.currentUserId, getDashboardMessagesInboxData);
	const [selectedThreadId, setSelectedThreadId] = createSignal<number | null>(props.initialThreadId ?? null);
	const [lastSyncedInitialThreadId, setLastSyncedInitialThreadId] = createSignal<number | null>(null);
	const [threadDetail, { refetch: refetchThreadDetail }] = createResource(selectedThreadId, getMessageThreadDetail);
	const [railMode, setRailMode] = createSignal<"inbox" | "compose">("inbox");
	const [mailboxCollapsed, setMailboxCollapsed] = createSignal(false);
	const [searchQuery, setSearchQuery] = createSignal("");
	const [recipientId, setRecipientId] = createSignal("");
	const [subject, setSubject] = createSignal("");
	const [threadSubjectDraft, setThreadSubjectDraft] = createSignal("");
	const [replyBody, setReplyBody] = createSignal("");
	const [editingThreadTitle, setEditingThreadTitle] = createSignal(false);
	const [editingMessageId, setEditingMessageId] = createSignal<number | null>(null);
	const [editingMessageBody, setEditingMessageBody] = createSignal("");
	const [composeError, setComposeError] = createSignal<string | null>(null);
	const [composeSuccess, setComposeSuccess] = createSignal<string | null>(null);
	const [replyError, setReplyError] = createSignal<string | null>(null);
	const [replySuccess, setReplySuccess] = createSignal<string | null>(null);
	const [threadActionError, setThreadActionError] = createSignal<string | null>(null);
	const [threadActionSuccess, setThreadActionSuccess] = createSignal<string | null>(null);
	const [messageActionError, setMessageActionError] = createSignal<string | null>(null);
	const [messageActionSuccess, setMessageActionSuccess] = createSignal<string | null>(null);
	const [creatingThread, setCreatingThread] = createSignal(false);
	const [sendingReply, setSendingReply] = createSignal(false);
	const [savingThreadTitle, setSavingThreadTitle] = createSignal(false);
	const [deletingThreadId, setDeletingThreadId] = createSignal<number | null>(null);
	const [savingMessageId, setSavingMessageId] = createSignal<number | null>(null);
	const [deletingMessageId, setDeletingMessageId] = createSignal<number | null>(null);
	const [markingThreadId, setMarkingThreadId] = createSignal<number | null>(null);

	const threads = createMemo(() => inboxData()?.threads ?? []);
	const recipients = createMemo(() => inboxData()?.recipients ?? []);
	const normalizedSearch = createMemo(() => searchQuery().trim().toLowerCase());
	const filteredThreads = createMemo(() => {
		const query = normalizedSearch();
		if (!query) return threads();

		return threads().filter((thread) => {
			const haystack = [thread.subject, thread.participants.map((participant) => participant.full_name).join(" "), thread.last_message_body ?? ""].join(" ").toLowerCase();
			return haystack.includes(query);
		});
	});
	const selectedThread = createMemo(() => threadDetail() ?? null);
	const threadCanManage = createMemo(() => selectedThread()?.created_by_user_id === props.currentUserId);

	createEffect(() => {
		const availableThreads = threads();
		const requestedThreadId = props.initialThreadId ?? null;
		const selected = selectedThreadId();
		const lastSynced = lastSyncedInitialThreadId();

		if (!availableThreads.length) {
			if (selected !== null) setSelectedThreadId(null);
			return;
		}

		if (requestedThreadId !== null && requestedThreadId !== lastSynced && availableThreads.some((thread) => thread.id === requestedThreadId)) {
			setSelectedThreadId(requestedThreadId);
			setLastSyncedInitialThreadId(requestedThreadId);
			return;
		}

		if (requestedThreadId === null && lastSynced !== null) {
			setLastSyncedInitialThreadId(null);
		}

		if (selected === null || !availableThreads.some((thread) => thread.id === selected)) {
			setSelectedThreadId(availableThreads[0]!.id);
		}
	});

	createEffect(() => {
		const detail = selectedThread();
		if (!detail || detail.unread_count <= 0) return;
		if (markingThreadId() === detail.id) return;

		setMarkingThreadId(detail.id);
		void markThreadRead(detail.id)
			.then(async () => {
				await Promise.all([refetchInbox(), refetchThreadDetail()]);
			})
			.catch(() => {
				// silent; the detail pane still renders
			})
			.finally(() => {
				setMarkingThreadId((current) => (current === detail.id ? null : current));
			});
	});

	createEffect(() => {
		const detail = selectedThread();
		setThreadSubjectDraft(detail?.subject ?? "");
		setEditingThreadTitle(false);
		setEditingMessageId(null);
		setEditingMessageBody("");
		setThreadActionError(null);
		setThreadActionSuccess(null);
		setMessageActionError(null);
		setMessageActionSuccess(null);
	});

	const submitNewThread = async (event: SubmitEvent) => {
		event.preventDefault();
		setComposeError(null);
		setComposeSuccess(null);

		const nextRecipientId = Number(recipientId());
		if (!nextRecipientId || !subject().trim()) {
			setComposeError("Pick a contact and add a subject to start the thread.");
			return;
		}

		setCreatingThread(true);
		try {
			const created = await createMessageThread({ recipientId: nextRecipientId, subject: subject().trim() });
			setRecipientId("");
			setSubject("");
			setComposeSuccess("Thread started. Open it to send the first message.");
			setRailMode("inbox");
			await refetchInbox();
			setSelectedThreadId(created.thread_id);
			await refetchThreadDetail();
		} catch (error) {
			setComposeError((error as Error).message || "We could not start that conversation right now.");
		} finally {
			setCreatingThread(false);
		}
	};

	const submitReply = async (event: SubmitEvent) => {
		event.preventDefault();
		setReplyError(null);
		setReplySuccess(null);

		const threadId = selectedThreadId();
		if (!threadId || !replyBody().trim()) {
			setReplyError("Write a message before sending your reply.");
			return;
		}

		setSendingReply(true);
		try {
			await createThreadReply(threadId, { body: replyBody().trim() });
			setReplyBody("");
			setReplySuccess("Reply sent.");
			await Promise.all([refetchInbox(), refetchThreadDetail()]);
		} catch (error) {
			setReplyError((error as Error).message || "We could not send your reply right now.");
		} finally {
			setSendingReply(false);
		}
	};

	const submitThreadTitle = async (event: SubmitEvent) => {
		event.preventDefault();
		const thread = selectedThread();
		if (!thread) return;

		const nextSubject = threadSubjectDraft().trim();
		setThreadActionError(null);
		setThreadActionSuccess(null);

		if (!nextSubject) {
			setThreadActionError("Add a title before saving the conversation subject.");
			return;
		}

		setSavingThreadTitle(true);
		try {
			await updateThreadSubject(thread.id, { subject: nextSubject });
			setEditingThreadTitle(false);
			setThreadActionSuccess("Conversation title updated.");
			await Promise.all([refetchInbox(), refetchThreadDetail()]);
		} catch (error) {
			setThreadActionError((error as Error).message || "We could not update the conversation title right now.");
		} finally {
			setSavingThreadTitle(false);
		}
	};

	const removeThread = async () => {
		const thread = selectedThread();
		if (!thread) return;

		const confirmed = globalThis.confirm?.(`Delete the conversation “${thread.subject}” for everyone? This cannot be undone.`) ?? false;
		if (!confirmed) return;

		setThreadActionError(null);
		setThreadActionSuccess(null);
		setDeletingThreadId(thread.id);
		try {
			await deleteThread(thread.id);
			const refreshed = await refetchInbox();
			const nextThreads = refreshed?.threads ?? [];
			setSelectedThreadId(nextThreads[0]?.id ?? null);
		} catch (error) {
			setThreadActionError((error as Error).message || "We could not delete this conversation right now.");
		} finally {
			setDeletingThreadId(null);
		}
	};

	const beginMessageEdit = (messageId: number, body: string) => {
		setEditingMessageId(messageId);
		setEditingMessageBody(body);
		setMessageActionError(null);
		setMessageActionSuccess(null);
	};

	const cancelMessageEdit = () => {
		setEditingMessageId(null);
		setEditingMessageBody("");
	};

	const submitMessageEdit = async (event: SubmitEvent, messageId: number) => {
		event.preventDefault();
		const threadId = selectedThreadId();
		if (!threadId) return;

		const nextBody = editingMessageBody().trim();
		setMessageActionError(null);
		setMessageActionSuccess(null);

		if (!nextBody) {
			setMessageActionError("Write something before saving your message.");
			return;
		}

		setSavingMessageId(messageId);
		try {
			await updateThreadMessage(threadId, messageId, { body: nextBody });
			setEditingMessageId(null);
			setEditingMessageBody("");
			setMessageActionSuccess("Message updated.");
			await Promise.all([refetchInbox(), refetchThreadDetail()]);
		} catch (error) {
			setMessageActionError((error as Error).message || "We could not update that message right now.");
		} finally {
			setSavingMessageId(null);
		}
	};

	const removeMessage = async (messageId: number) => {
		const threadId = selectedThreadId();
		if (!threadId) return;

		const confirmed = globalThis.confirm?.("Delete this message? This cannot be undone.") ?? false;
		if (!confirmed) return;

		setMessageActionError(null);
		setMessageActionSuccess(null);
		setDeletingMessageId(messageId);
		try {
			await deleteThreadMessage(threadId, messageId);
			if (editingMessageId() === messageId) {
				setEditingMessageId(null);
				setEditingMessageBody("");
			}
			setMessageActionSuccess("Message deleted.");
			await Promise.all([refetchInbox(), refetchThreadDetail()]);
		} catch (error) {
			setMessageActionError((error as Error).message || "We could not delete that message right now.");
		} finally {
			setDeletingMessageId(null);
		}
	};

	return (
		<section class={styles.section}>
			<div classList={{ [styles.workspaceGrid]: true, [styles.workspaceGridMailboxCollapsed]: mailboxCollapsed() }}>
				<DashboardMessagesMailbox
					railMode={railMode()}
					recipients={recipients()}
					threads={threads()}
					filteredThreads={filteredThreads()}
					selectedThreadId={selectedThreadId()}
					currentUserId={props.currentUserId}
					searchQuery={searchQuery()}
					recipientId={recipientId()}
					subject={subject()}
					composeError={composeError()}
					composeSuccess={composeSuccess()}
					creatingThread={creatingThread()}
					inboxLoading={Boolean(inboxData.loading)}
					inboxError={Boolean(inboxData.error)}
					onSetRailMode={setRailMode}
					onRecipientInput={setRecipientId}
					onSubjectInput={setSubject}
					onSearchInput={setSearchQuery}
					onSelectThread={setSelectedThreadId}
					onSubmitNewThread={submitNewThread}
				/>

				<DashboardMessagesThreadPanel
					selectedThreadId={selectedThreadId()}
					threadLoading={Boolean(threadDetail.loading)}
					threadError={Boolean(threadDetail.error)}
					thread={selectedThread()}
					currentUserId={props.currentUserId}
					editingThreadTitle={editingThreadTitle()}
					threadSubjectDraft={threadSubjectDraft()}
					threadActionError={threadActionError()}
					threadActionSuccess={threadActionSuccess()}
					messageActionError={messageActionError() || replyError()}
					messageActionSuccess={messageActionSuccess() || replySuccess()}
					replyBody={replyBody()}
					threadCanManage={Boolean(threadCanManage())}
					mailboxCollapsed={mailboxCollapsed()}
					markingThreadId={markingThreadId()}
					deletingThreadId={deletingThreadId()}
					savingThreadTitle={savingThreadTitle()}
					editingMessageId={editingMessageId()}
					editingMessageBody={editingMessageBody()}
					savingMessageId={savingMessageId()}
					deletingMessageId={deletingMessageId()}
					sendingReply={sendingReply()}
					onThreadSubjectDraftInput={setThreadSubjectDraft}
					onReplyBodyInput={setReplyBody}
					onEditingMessageBodyInput={setEditingMessageBody}
					onToggleMailbox={() => setMailboxCollapsed((value) => !value)}
					onBeginEditThreadTitle={() => setEditingThreadTitle(true)}
					onCancelEditThreadTitle={() => {
						setEditingThreadTitle(false);
						setThreadSubjectDraft(selectedThread()?.subject ?? "");
					}}
					onSubmitThreadTitle={submitThreadTitle}
					onRemoveThread={removeThread}
					onBeginMessageEdit={beginMessageEdit}
					onCancelMessageEdit={cancelMessageEdit}
					onSubmitMessageEdit={submitMessageEdit}
					onRemoveMessage={removeMessage}
					onSubmitReply={submitReply}
				/>
			</div>
		</section>
	);
};

export default DashboardMessagesPage;
