import { runCommand } from "./orchestrator";

export interface ThreadSummary {
	threadId: string;
	subject: string;
	authors: string;
	totalMessages: number;
	tags: string[];
	timestamp: number;
}

export interface Message {
	messageId: string;
	from: string;
	to: string;
	subject: string;
	date: string;
	inReplyTo: string;
	references: string;
	body: string;
	tags: string[];
	timestamp: number;
}

export function parseSearchResults(raw: unknown[]): ThreadSummary[] {
	return (raw as Array<Record<string, unknown>>).map((entry) => ({
		threadId: entry.thread as string,
		subject: entry.subject as string,
		authors: entry.authors as string,
		totalMessages: entry.total as number,
		tags: entry.tags as string[],
		timestamp: entry.timestamp as number,
	}));
}

export function parseThreadMessages(raw: unknown[]): Message[] {
	const messages: Message[] = [];
	flattenThread(raw, messages);
	return messages.sort((a, b) => a.timestamp - b.timestamp);
}

function flattenThread(node: unknown, messages: Message[]): void {
	if (!Array.isArray(node)) return;

	for (const item of node) {
		if (isMessageNode(item)) {
			const headers = item.headers as Record<string, string>;
			const bodyParts = item.body as Array<Record<string, unknown>>;
			const plainPart = bodyParts.find((p) => p["content-type"] === "text/plain");

			messages.push({
				messageId: item.id as string,
				from: headers.From ?? "",
				to: headers.To ?? "",
				subject: headers.Subject ?? "",
				date: headers.Date ?? "",
				inReplyTo: headers["In-Reply-To"] ?? "",
				references: headers.References ?? "",
				body: (plainPart?.content as string) ?? "",
				tags: item.tags as string[],
				timestamp: item.timestamp as number,
			});
		} else if (Array.isArray(item)) {
			flattenThread(item, messages);
		}
	}
}

function isMessageNode(item: unknown): item is Record<string, unknown> {
	return typeof item === "object" && item !== null && "id" in item && "headers" in item;
}

const notmuchEnv = process.env.NOTMUCH_CONFIG
	? { NOTMUCH_CONFIG: process.env.NOTMUCH_CONFIG }
	: undefined;

export async function searchThreads(query: string): Promise<ThreadSummary[]> {
	const result = await runCommand("notmuch", ["search", "--format=json", query], notmuchEnv);
	if (result.exitCode !== 0) {
		throw new Error(`notmuch search failed: ${result.stderr}`);
	}
	return parseSearchResults(JSON.parse(result.stdout));
}

export async function getThread(threadId: string): Promise<Message[]> {
	const result = await runCommand("notmuch", ["show", "--format=json", `thread:${threadId}`], notmuchEnv);
	if (result.exitCode !== 0) {
		throw new Error(`notmuch show failed: ${result.stderr}`);
	}
	return parseThreadMessages(JSON.parse(result.stdout));
}
