/**
 * Remote Questions — Discord adapter
 */
import { formatForDiscord, parseDiscordResponse, DISCORD_NUMBER_EMOJIS } from "./format.js";
import { apiRequest } from "./http-client.js";
const DISCORD_API = "https://discord.com/api/v10";
export class DiscordAdapter {
    name = "discord";
    botUserId = null;
    guildId = null;
    token;
    channelId;
    constructor(token, channelId) {
        this.token = token;
        this.channelId = channelId;
    }
    async validate() {
        const res = await this.discordApi("GET", "/users/@me");
        if (!res.id)
            throw new Error("Discord auth failed: invalid token");
        this.botUserId = String(res.id);
        // Resolve guild ID for message URL generation.
        // The channel belongs to a guild — fetch channel info to discover it.
        try {
            const channelInfo = await this.discordApi("GET", `/channels/${this.channelId}`);
            if (channelInfo.guild_id) {
                this.guildId = String(channelInfo.guild_id);
            }
        }
        catch {
            // Non-fatal — message URLs will be omitted if guild ID can't be resolved
        }
    }
    async sendPrompt(prompt) {
        const { embeds, reactionEmojis } = formatForDiscord(prompt);
        const res = await this.discordApi("POST", `/channels/${this.channelId}/messages`, {
            content: "**NERF needs your input** — reply to this message with your answer",
            embeds,
        });
        if (!res.id)
            throw new Error(`Discord send failed: ${JSON.stringify(res)}`);
        const messageId = String(res.id);
        if (prompt.questions.length === 1) {
            for (const emoji of reactionEmojis) {
                try {
                    await this.discordApi("PUT", `/channels/${this.channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`);
                }
                catch {
                    // Best-effort only
                }
            }
        }
        // Build message URL if guild ID is available
        const messageUrl = this.guildId
            ? `https://discord.com/channels/${this.guildId}/${this.channelId}/${messageId}`
            : undefined;
        return {
            ref: {
                id: prompt.id,
                channel: "discord",
                messageId,
                channelId: this.channelId,
                threadUrl: messageUrl,
            },
        };
    }
    async pollAnswer(prompt, ref) {
        if (!this.botUserId)
            await this.validate();
        if (prompt.questions.length === 1) {
            const reactionAnswer = await this.checkReactions(prompt, ref);
            if (reactionAnswer)
                return reactionAnswer;
        }
        return this.checkReplies(prompt, ref);
    }
    /**
     * Acknowledge that an answer was received by adding a ✅ reaction to the
     * original prompt message. Best-effort — failures are silently ignored.
     */
    async acknowledgeAnswer(ref) {
        try {
            await this.discordApi("PUT", `/channels/${ref.channelId}/messages/${ref.messageId}/reactions/${encodeURIComponent("✅")}/@me`);
        }
        catch {
            // Best-effort — don't let acknowledgement failures affect the flow
        }
    }
    async checkReactions(prompt, ref) {
        const reactions = [];
        for (const emoji of DISCORD_NUMBER_EMOJIS) {
            try {
                const users = await this.discordApi("GET", `/channels/${ref.channelId}/messages/${ref.messageId}/reactions/${encodeURIComponent(emoji)}`);
                if (Array.isArray(users)) {
                    const humanUsers = users.filter((u) => u.id !== this.botUserId);
                    if (humanUsers.length > 0)
                        reactions.push({ emoji, count: humanUsers.length });
                }
            }
            catch (err) {
                const msg = String(err.message ?? "");
                // 404 = no reactions for this emoji — expected, continue
                if (msg.includes("HTTP 404"))
                    continue;
                // 401/403 = auth failure — surface to caller so it can fail the poll
                if (msg.includes("HTTP 401") || msg.includes("HTTP 403"))
                    throw err;
                // Other errors (rate limit, network) — skip this emoji, best-effort
            }
        }
        if (reactions.length === 0)
            return null;
        return parseDiscordResponse(reactions, null, prompt.questions);
    }
    async checkReplies(prompt, ref) {
        const messages = await this.discordApi("GET", `/channels/${ref.channelId}/messages?after=${ref.messageId}&limit=10`);
        if (!Array.isArray(messages))
            return null;
        const replies = messages.filter((m) => m.author?.id &&
            m.author.id !== this.botUserId &&
            m.message_reference?.message_id === ref.messageId &&
            m.content);
        if (replies.length === 0)
            return null;
        return parseDiscordResponse([], String(replies[0].content), prompt.questions);
    }
    async discordApi(method, path, body) {
        return apiRequest(`${DISCORD_API}${path}`, method, body, {
            authScheme: "Bot",
            authToken: this.token,
            errorLabel: "Discord API",
        });
    }
}
