import { createGmailClient, createRawEmail, getHeader, fetchReplyHeaders, buildReplySubject, } from "./gmail-utils.js";
function decodeBase64Url(data) {
    return Buffer.from(data, "base64url").toString("utf-8");
}
function extractTextFromPayload(payload) {
    if (!payload)
        return "";
    if (payload.mimeType === "text/plain" && payload.body?.data) {
        return decodeBase64Url(payload.body.data);
    }
    const parts = payload.parts ?? [];
    for (const p of parts) {
        const t = extractTextFromPayload(p);
        if (t)
            return t;
    }
    if (payload.body?.data) {
        return decodeBase64Url(payload.body.data);
    }
    return "";
}
/**
 * Gmail email client wrapper (separate from the Gmail channel adapter).
 * Provides programmatic email operations for agent tools.
 */
export class GmailEmailClient {
    gmail;
    config;
    constructor(config) {
        this.config = config;
        this.gmail = createGmailClient(config);
    }
    async listEmails(options = {}) {
        const label = options.label ?? "INBOX";
        const maxResults = options.maxResults ?? 10;
        const unreadOnly = options.unreadOnly ?? false;
        const qParts = [];
        if (options.query)
            qParts.push(options.query);
        if (unreadOnly)
            qParts.push("is:unread");
        const res = await this.gmail.users.messages.list({
            userId: "me",
            labelIds: [label],
            q: qParts.length ? qParts.join(" ") : undefined,
            maxResults,
        });
        const ids = (res.data.messages ?? []).map((m) => m.id).filter(Boolean);
        if (ids.length === 0)
            return [];
        // Fetch metadata for each id (parallel, but keep it bounded by maxResults)
        const msgs = await Promise.all(ids.map((id) => this.gmail.users.messages.get({
            userId: "me",
            id,
            format: "metadata",
            metadataHeaders: ["From", "To", "Subject", "Date"],
        })));
        return msgs.map((m) => {
            const payload = m.data.payload;
            const headers = payload?.headers ?? [];
            return {
                id: m.data.id ?? "",
                threadId: m.data.threadId ?? undefined,
                from: getHeader(headers, "From"),
                to: getHeader(headers, "To"),
                subject: getHeader(headers, "Subject"),
                date: getHeader(headers, "Date"),
                snippet: m.data.snippet ?? undefined,
                labels: m.data.labelIds ?? undefined,
            };
        });
    }
    async getEmail(messageId) {
        const res = await this.gmail.users.messages.get({
            userId: "me",
            id: messageId,
            format: "full",
        });
        const payload = res.data.payload;
        const headers = payload?.headers ?? [];
        const bodyText = extractTextFromPayload(payload);
        return {
            id: res.data.id ?? messageId,
            threadId: res.data.threadId ?? undefined,
            from: getHeader(headers, "From"),
            to: getHeader(headers, "To"),
            subject: getHeader(headers, "Subject"),
            date: getHeader(headers, "Date"),
            snippet: res.data.snippet ?? undefined,
            labels: res.data.labelIds ?? undefined,
            bodyText: bodyText || undefined,
        };
    }
    async markRead(messageId) {
        await this.gmail.users.messages.modify({
            userId: "me",
            id: messageId,
            requestBody: { removeLabelIds: ["UNREAD"] },
        });
    }
    async markUnread(messageId) {
        await this.gmail.users.messages.modify({
            userId: "me",
            id: messageId,
            requestBody: { addLabelIds: ["UNREAD"] },
        });
    }
    async archive(messageId) {
        // Remove INBOX label; keeps message in "All Mail"
        await this.gmail.users.messages.modify({
            userId: "me",
            id: messageId,
            requestBody: { removeLabelIds: ["INBOX"] },
        });
    }
    async sendEmail(options) {
        const raw = createRawEmail({
            from: this.config.gmail,
            to: options.to,
            cc: options.cc,
            bcc: options.bcc,
            subject: options.subject,
            body: options.body,
            htmlBody: options.htmlBody,
            attachments: options.attachments,
        });
        const res = await this.gmail.users.messages.send({
            userId: "me",
            requestBody: { raw },
        });
        return { id: res.data.id ?? undefined, threadId: res.data.threadId ?? undefined };
    }
    async reply(options) {
        const original = await this.gmail.users.messages.get({
            userId: "me",
            id: options.messageId,
            format: "metadata",
            metadataHeaders: ["From", "To", "Subject", "Message-Id", "References"],
        });
        const headers = original.data.payload?.headers ?? [];
        const from = getHeader(headers, "From");
        const to = options.to ?? from ?? "";
        const subject = getHeader(headers, "Subject") ?? "";
        const replyHeaders = await fetchReplyHeaders(this.gmail, options.messageId);
        const raw = createRawEmail({
            from: this.config.gmail,
            to,
            cc: options.cc,
            bcc: options.bcc,
            subject: buildReplySubject(subject),
            body: options.body,
            htmlBody: options.htmlBody,
            inReplyTo: replyHeaders.inReplyTo,
            references: replyHeaders.references,
            attachments: options.attachments,
        });
        const res = await this.gmail.users.messages.send({
            userId: "me",
            requestBody: {
                raw,
                threadId: original.data.threadId ?? undefined,
            },
        });
        return { id: res.data.id ?? undefined, threadId: res.data.threadId ?? undefined };
    }
}
//# sourceMappingURL=gmail-email.js.map