/** Pure channel -> bot resolution against the botmaster D1 `bots` table. No I/O. */

export type BotRow = {
  id: string;
  project_name: string | null;
  bot_name: string | null;
  telegram_token: string | null;
  allowed_chat_ids: string | null;
};

export class ResolveError extends Error {}

export type ResolvedTarget = {
  botId: string;
  botName: string;
  token: string;
  chatId: string;
};

/**
 * Resolve a channel name to a Telegram bot token + chat id.
 * A channel matches a bot row by project_name or bot_name (case-insensitive).
 * Fails closed on: no match, ambiguous match (>1 distinct bot id), missing
 * token, or missing chat id.
 */
export function resolveChannel(rows: BotRow[], channel: string): ResolvedTarget {
  const needle = channel.trim().toLowerCase();
  if (!needle) throw new ResolveError("channel name is empty");

  const matches = rows.filter(
    (r) => (r.project_name ?? "").toLowerCase() === needle || (r.bot_name ?? "").toLowerCase() === needle,
  );

  const distinctIds = new Set(matches.map((r) => r.id));
  if (distinctIds.size === 0) {
    throw new ResolveError(`unknown channel "${channel}" — no bot in botmaster has that project or bot name`);
  }
  if (distinctIds.size > 1) {
    throw new ResolveError(
      `ambiguous channel "${channel}" — matches ${distinctIds.size} bots (${[...distinctIds].join(", ")})`,
    );
  }

  const bot = matches[0]!;
  const token = (bot.telegram_token ?? "").trim();
  if (!token) {
    throw new ResolveError(`missing telegram token for channel "${channel}" (bot ${bot.bot_name ?? bot.id})`);
  }

  const chatId = (bot.allowed_chat_ids ?? "")
    .split(",")
    .map((s) => s.trim())
    .filter(Boolean)[0];
  if (!chatId) {
    throw new ResolveError(`missing chat id for channel "${channel}" (bot ${bot.bot_name ?? bot.id})`);
  }

  return { botId: bot.id, botName: bot.bot_name ?? bot.id, token, chatId };
}
