/**
 * Telegram CommsAdapter — system-communications-notifications (Task 7).
 *
 * Implements the `CommsAdapter` interface for Telegram bots.
 * Provides outbound message sending, inbound update parsing,
 * and webhook management helpers.
 */
import type { CommsAdapter, OutboundMessage, InboundMessage } from '@zync/types'

const TELEGRAM_API_BASE = 'https://api.telegram.org'

function apiUrl(token: string, method: string): string {
  return `${TELEGRAM_API_BASE}/bot${token}/${method}`
}

interface TelegramUpdate {
  update_id: number
  message?: {
    message_id: number
    from?: { id: number; username?: string; first_name?: string }
    chat: { id: number; type: string }
    text?: string
    document?: { file_id: string; file_name?: string; mime_type?: string }
    photo?: Array<{ file_id: string }>
    caption?: string
  }
}

/**
 * Create a Telegram CommsAdapter for a specific bot token.
 * Token is the per-tenant decrypted secret (not stored here).
 */
export function createTelegramAdapter(token: string): CommsAdapter {
  return {
    id: 'telegram',
    name: 'Telegram',

    async send(message: OutboundMessage): Promise<void> {
      const res = await fetch(apiUrl(token, 'sendMessage'), {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          chat_id: message.to,
          text: message.body,
          parse_mode: 'HTML',
        }),
      })
      if (!res.ok) {
        const text = await res.text()
        throw new Error(`Telegram send failed: ${res.status} ${text}`)
      }
    },

    receive(payload: unknown): InboundMessage | null {
      if (!payload || typeof payload !== 'object') return null
      const update = payload as TelegramUpdate
      const msg = update.message
      if (!msg) return null

      const text = msg.text ?? msg.caption ?? ''
      const photoFileId = msg.photo?.length ? msg.photo[msg.photo.length - 1]?.file_id : undefined
      return {
        from: String(msg.from?.id ?? msg.chat.id),
        text,
        chatId: String(msg.chat.id),
        metadata: {
          updateId: update.update_id,
          messageId: msg.message_id,
          chatType: msg.chat.type,
          username: msg.from?.username,
          firstName: msg.from?.first_name,
          hasDocument: !!msg.document,
          documentFileId: msg.document?.file_id,
          documentMimeType: msg.document?.mime_type,
          photoFileId,
        },
      }
    },
  }
}

/**
 * Register a webhook for a tenant's Telegram bot.
 * The endpoint is `https://zync.is/api/webhooks/telegram/{tenantId}`.
 */
export async function setTelegramWebhook(token: string, tenantId: string): Promise<void> {
  const webhookUrl = `https://zync.is/api/webhooks/telegram/${tenantId}`
  const secretToken = generateWebhookSecret(token, tenantId)

  const res = await fetch(apiUrl(token, 'setWebhook'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      url: webhookUrl,
      secret_token: secretToken,
      allowed_updates: ['message', 'callback_query'],
    }),
  })

  if (!res.ok) {
    const text = await res.text()
    throw new Error(`Failed to set Telegram webhook: ${res.status} ${text}`)
  }
}

/**
 * Remove the webhook for a tenant's Telegram bot.
 */
export async function deleteTelegramWebhook(token: string): Promise<void> {
  const res = await fetch(apiUrl(token, 'deleteWebhook'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ drop_pending_updates: false }),
  })

  if (!res.ok) {
    const text = await res.text()
    throw new Error(`Failed to delete Telegram webhook: ${res.status} ${text}`)
  }
}

interface BotIdentity {
  id: number
  username: string
  first_name: string
  can_join_groups: boolean
  can_read_all_group_messages: boolean
}

/**
 * Validate a bot token by calling getMe.
 * Returns the bot identity on success, throws on invalid token.
 */
export async function validateBotToken(token: string): Promise<BotIdentity> {
  const res = await fetch(apiUrl(token, 'getMe'))
  if (!res.ok) {
    const text = await res.text()
    throw new Error(`Invalid Telegram bot token: ${res.status} ${text}`)
  }
  const data = (await res.json()) as { ok: boolean; result?: BotIdentity; description?: string }
  if (!data.ok || !data.result) {
    throw new Error(`Telegram getMe failed: ${data.description ?? 'unknown error'}`)
  }
  return data.result
}

/**
 * Generate a deterministic secret token for webhook verification.
 * Used as the `X-Telegram-Bot-Api-Secret-Token` header value.
 * This is NOT a crypto secret — it's a per-tenant webhook discriminator.
 */
function generateWebhookSecret(token: string, tenantId: string): string {
  // Simple concat hash for webhook discriminator — not used as crypto secret
  return `${token.slice(0, 8)}_${tenantId.replace(/-/g, '').slice(0, 16)}`
}
