import type { ReactionGroup } from "$lib/components/reaction/reactions";

export interface CommentView {
	uri: string;
	cid?: string;
	rkey: string;
	authorDid: string;
	authorHandle: string;
	createdAt: string;
	body: string;
	bodyHtml: string | null;
	reactions?: ReactionGroup[];
	deleted?: boolean;
}

export interface CommentThread {
	self: CommentView;
	replies: CommentView[];
}

export interface ThreadInput {
	comment: CommentView;
	replyTo: string | null;
	// lets us reply to a parent even after it's deleted
	replyToCid?: string;
}

const byCreatedAt = (a: CommentView, b: CommentView) => a.createdAt.localeCompare(b.createdAt);

// stand-in for a deleted parent
export function deletedComment(uri: string, createdAt: string, cid?: string): CommentView {
	return {
		uri,
		cid,
		rkey: uri.split("/").pop() ?? "",
		authorDid: "",
		authorHandle: "",
		createdAt,
		body: "",
		bodyHtml: null,
		deleted: true
	};
}

export function buildCommentThreads(inputs: ThreadInput[]): CommentThread[] {
	const threads = new Map<string, CommentThread>();

	for (const { comment, replyTo } of inputs) {
		if (replyTo === null) {
			threads.set(comment.uri, { self: comment, replies: [] });
		}
	}

	for (const { comment, replyTo, replyToCid } of inputs) {
		if (replyTo === null) continue;
		let parent = threads.get(replyTo);
		if (!parent) {
			parent = { self: deletedComment(replyTo, comment.createdAt), replies: [] };
			threads.set(replyTo, parent);
		}
		if (parent.self.deleted && replyToCid && !parent.self.cid) {
			parent.self.cid = replyToCid;
		}
		parent.replies.push(comment);
	}

	const list = [...threads.values()].sort((a, b) => byCreatedAt(a.self, b.self));
	for (const thread of list) thread.replies.sort(byCreatedAt);
	return list;
}
