/**
 * 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: "SF 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>SF 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;
}
