/**
 * Remote Questions — payload formatting and parsing helpers
 */
export const DISCORD_NUMBER_EMOJIS = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣"];
export const SLACK_NUMBER_REACTION_NAMES = ["one", "two", "three", "four", "five"];
const MAX_USER_NOTE_LENGTH = 500;
export function formatForSlack(prompt) {
    const blocks = [
        {
            type: "header",
            text: { type: "plain_text", text: "NERF needs your input" },
        },
    ];
    if (prompt.questions.length > 1) {
        blocks.push({
            type: "context",
            elements: [{
                    type: "mrkdwn",
                    text: "Reply once in thread using one line per question or semicolons (`1; 2; custom note`).",
                }],
        });
    }
    for (const q of prompt.questions) {
        const supportsReactions = prompt.questions.length === 1;
        blocks.push({
            type: "section",
            text: { type: "mrkdwn", text: `*${q.header}*\n${q.question}` },
        });
        blocks.push({
            type: "section",
            text: {
                type: "mrkdwn",
                text: q.options.map((opt, i) => `${i + 1}. *${opt.label}* — ${opt.description}`).join("\n"),
            },
        });
        blocks.push({
            type: "context",
            elements: [{
                    type: "mrkdwn",
                    text: prompt.questions.length > 1
                        ? (q.allowMultiple
                            ? "For this question, use comma-separated numbers (`1,3`) or free text."
                            : "For this question, use one number (`1`) or free text.")
                        : (q.allowMultiple
                            ? (supportsReactions
                                ? "Reply in thread with comma-separated numbers (`1,3`) or react with matching number emoji."
                                : "Reply in thread with comma-separated numbers (`1,3`) or free text.")
                            : (supportsReactions
                                ? "Reply in thread with a number (`1`) or react with the matching number emoji."
                                : "Reply in thread with a number (`1`) or free text.")),
                }],
        });
        blocks.push({ type: "divider" });
    }
    if (prompt.context?.source) {
        blocks.push({
            type: "context",
            elements: [{
                    type: "mrkdwn",
                    text: `Source: \`${prompt.context.source}\``,
                }],
        });
    }
    return blocks;
}
export function formatForDiscord(prompt) {
    const reactionEmojis = [];
    const embeds = prompt.questions.map((q, questionIndex) => {
        const supportsReactions = prompt.questions.length === 1;
        const optionLines = q.options.map((opt, i) => {
            const emoji = DISCORD_NUMBER_EMOJIS[i] ?? `${i + 1}.`;
            if (supportsReactions && DISCORD_NUMBER_EMOJIS[i])
                reactionEmojis.push(DISCORD_NUMBER_EMOJIS[i]);
            return `${emoji} **${opt.label}** — ${opt.description}`;
        });
        const footerParts = [];
        if (supportsReactions) {
            footerParts.push(q.allowMultiple
                ? "Reply with comma-separated choices (`1,3`) or react with matching numbers"
                : "Reply with a number or react with the matching number");
        }
        else {
            footerParts.push(`Question ${questionIndex + 1}/${prompt.questions.length} — reply with one line per question or use semicolons`);
        }
        if (prompt.context?.source) {
            footerParts.push(`Source: ${prompt.context.source}`);
        }
        return {
            title: q.header,
            description: q.question,
            color: 0x7c3aed,
            fields: [{ name: "Options", value: optionLines.join("\n") }],
            footer: { text: footerParts.join(" · ") },
        };
    });
    return { embeds, reactionEmojis };
}
export function parseSlackReply(text, questions) {
    const answers = {};
    const trimmed = text.trim();
    if (questions.length === 1) {
        answers[questions[0].id] = parseAnswerForQuestion(trimmed, questions[0]);
        return { answers };
    }
    const parts = trimmed.includes(";")
        ? trimmed.split(";").map((s) => s.trim()).filter(Boolean)
        : trimmed.split("\n").map((s) => s.trim()).filter(Boolean);
    for (let i = 0; i < questions.length; i++) {
        answers[questions[i].id] = parseAnswerForQuestion(parts[i] ?? "", questions[i]);
    }
    return { answers };
}
export function parseDiscordResponse(reactions, replyText, questions) {
    if (replyText)
        return parseSlackReply(replyText, questions);
    const answers = {};
    if (questions.length !== 1) {
        for (const q of questions) {
            answers[q.id] = { answers: [], user_note: "Discord reactions are only supported for single-question prompts" };
        }
        return { answers };
    }
    const q = questions[0];
    const picked = reactions
        .filter((r) => DISCORD_NUMBER_EMOJIS.includes(r.emoji) && r.count > 0)
        .map((r) => q.options[DISCORD_NUMBER_EMOJIS.indexOf(r.emoji)]?.label)
        .filter(Boolean);
    answers[q.id] = picked.length > 0
        ? { answers: q.allowMultiple ? picked : [picked[0]] }
        : { answers: [], user_note: "No clear response via reactions" };
    return { answers };
}
export function parseSlackReactionResponse(reactionNames, questions) {
    const answers = {};
    if (questions.length !== 1) {
        for (const q of questions) {
            answers[q.id] = { answers: [], user_note: "Slack reactions are only supported for single-question prompts" };
        }
        return { answers };
    }
    const q = questions[0];
    const picked = reactionNames
        .filter((name) => SLACK_NUMBER_REACTION_NAMES.includes(name))
        .map((name) => q.options[SLACK_NUMBER_REACTION_NAMES.indexOf(name)]?.label)
        .filter(Boolean);
    answers[q.id] = picked.length > 0
        ? { answers: q.allowMultiple ? picked : [picked[0]] }
        : { answers: [], user_note: "No clear response via reactions" };
    return { answers };
}
function escapeHtml(s) {
    return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
export function formatForTelegram(prompt) {
    const lines = ["<b>NERF needs your input</b>", ""];
    for (let qi = 0; qi < prompt.questions.length; qi++) {
        const q = prompt.questions[qi];
        lines.push(`<b>${escapeHtml(q.header)}</b>`);
        lines.push(escapeHtml(q.question));
        lines.push("");
        for (let i = 0; i < q.options.length; i++) {
            lines.push(`${i + 1}. <b>${escapeHtml(q.options[i].label)}</b> — ${escapeHtml(q.options[i].description)}`);
        }
        lines.push("");
        if (prompt.questions.length === 1) {
            lines.push(q.allowMultiple
                ? "Reply with comma-separated numbers (1,3) or free text."
                : "Reply with a number or tap a button below.");
        }
        else {
            lines.push(`Question ${qi + 1}/${prompt.questions.length} — reply with one line per question or use semicolons.`);
        }
        if (qi < prompt.questions.length - 1)
            lines.push("");
    }
    const result = {
        text: lines.join("\n"),
        parse_mode: "HTML",
    };
    // Inline keyboard for single-question with <=5 options
    const isSingle = prompt.questions.length === 1;
    if (isSingle && prompt.questions[0].options.length <= 5) {
        result.reply_markup = {
            inline_keyboard: prompt.questions[0].options.map((opt, i) => [{
                    text: `${i + 1}. ${opt.label}`,
                    callback_data: `${prompt.id}:${i}`,
                }]),
        };
    }
    return result;
}
export function parseTelegramResponse(callbackData, replyText, questions, promptId) {
    // Handle callback_data from inline keyboard button press
    if (callbackData) {
        const match = callbackData.match(new RegExp(`^${promptId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}:(\\d+)$`));
        if (match && questions.length === 1) {
            const idx = parseInt(match[1], 10);
            const q = questions[0];
            if (idx >= 0 && idx < q.options.length) {
                return { answers: { [q.id]: { answers: [q.options[idx].label] } } };
            }
        }
    }
    // Handle text reply — delegate to parseSlackReply (text parsing is format-agnostic)
    if (replyText)
        return parseSlackReply(replyText, questions);
    const answers = {};
    for (const q of questions) {
        answers[q.id] = { answers: [], user_note: "No response provided" };
    }
    return { answers };
}
function parseAnswerForQuestion(text, q) {
    if (!text)
        return { answers: [], user_note: "No response provided" };
    if (/^[\d,\s]+$/.test(text)) {
        const nums = text
            .split(",")
            .map((s) => parseInt(s.trim(), 10))
            .filter((n) => !Number.isNaN(n) && n >= 1 && n <= q.options.length);
        if (nums.length > 0) {
            const selected = nums.map((n) => q.options[n - 1].label);
            return { answers: q.allowMultiple ? selected : [selected[0]] };
        }
    }
    const single = parseInt(text, 10);
    if (!Number.isNaN(single) && single >= 1 && single <= q.options.length) {
        return { answers: [q.options[single - 1].label] };
    }
    return { answers: [], user_note: truncateNote(text) };
}
function truncateNote(text) {
    return text.length > MAX_USER_NOTE_LENGTH ? text.slice(0, MAX_USER_NOTE_LENGTH) + "…" : text;
}
