import { readFileSync } from "node:fs"
import { basename } from "node:path"

export interface TelegramResult {
  ok: true
  message_id: number
  chat_id: string
}

type ParseMode = "MarkdownV2" | "HTML" | "plain"

const API_BASE = "https://api.telegram.org/bot"

async function telegramFetch(
  token: string,
  method: string,
  body: BodyInit,
  headers?: Record<string, string>,
): Promise<TelegramResult> {
  const url = `${API_BASE}${token}/${method}`
  const res = await fetch(url, { method: "POST", body, headers })
  const data = await res.json() as { ok: boolean; description?: string; result?: { message_id: number; chat: { id: number | string } } }
  if (!data.ok) {
    throw new Error(data.description ?? `Telegram API error (HTTP ${res.status})`)
  }
  if (!data.result) {
    throw new Error("Telegram API returned no result")
  }
  return {
    ok: true,
    message_id: data.result.message_id,
    chat_id: String(data.result.chat.id),
  }
}

function shouldIncludeParseMode(parseMode?: ParseMode): parseMode is "MarkdownV2" | "HTML" {
  return parseMode === "MarkdownV2" || parseMode === "HTML"
}

export async function sendMessage(
  token: string,
  chatId: string,
  text: string,
  parseMode?: ParseMode,
): Promise<TelegramResult> {
  const body: Record<string, string> = { chat_id: chatId, text }
  if (shouldIncludeParseMode(parseMode)) {
    body.parse_mode = parseMode
  }
  return telegramFetch(token, "sendMessage", JSON.stringify(body), {
    "Content-Type": "application/json",
  })
}

export async function sendDocument(
  token: string,
  chatId: string,
  filePath: string,
  caption?: string,
  parseMode?: ParseMode,
): Promise<TelegramResult> {
  const buf = readFileSync(filePath)
  const blob = new Blob([buf])
  const form = new FormData()
  form.append("chat_id", chatId)
  form.append("document", blob, basename(filePath))
  if (caption) form.append("caption", caption)
  if (shouldIncludeParseMode(parseMode)) form.append("parse_mode", parseMode)
  return telegramFetch(token, "sendDocument", form)
}

export async function sendPhoto(
  token: string,
  chatId: string,
  filePath: string,
  caption?: string,
  parseMode?: ParseMode,
): Promise<TelegramResult> {
  const buf = readFileSync(filePath)
  const blob = new Blob([buf])
  const form = new FormData()
  form.append("chat_id", chatId)
  form.append("photo", blob, basename(filePath))
  if (caption) form.append("caption", caption)
  if (shouldIncludeParseMode(parseMode)) form.append("parse_mode", parseMode)
  return telegramFetch(token, "sendPhoto", form)
}