// ── The Discord announce leg ───────────────────────────────────────────────
//
// CORE content — the Discord bot has no game logic (MODULE_SYSTEM.md §1.10), so
// this leg stays in core when module-uo leaves with the town crier. It is written
// in the same shape as a module's leg and registered through the same function
// (modules/registries.js registerAnnounceLeg), because a registry only core's
// hardcoded base bypasses is not exercised until a module arrives.

const botInternalClient = require('./botInternalClient')
const { articleUrl, baseUrl, legError } = require('../model/announceJobs/announceJobs.logic')

// Deliver. Returns the raw client result ({ ok, status, data, error }) — the
// client never throws, and classification is `classify`'s job.
async function dispatch(post) {
  const base = baseUrl()
  // Stored image paths are relative ("/uploads/x.png"); Discord embeds need an
  // absolute URL.
  const imageUrl = post.image_url ? new URL(post.image_url, base).toString() : null
  return botInternalClient.announce({
    title: post.title,
    excerpt: post.excerpt,
    url: articleUrl(base),
    imageUrl,
  })
}

// The bot's /internal/announce collapses failures (503 = not connected,
// 400 = no news channel configured) without surfacing Discord's own retry_after,
// so there is no reliable terminal signal to key on here. Retry every failure on
// the shared backoff; a genuine config problem simply exhausts its attempts and
// lands as `failed` in the admin panel, where the per-leg retry button re-runs it
// after the channel is set.
function classify(result) {
  if (result && result.ok) return { outcome: 'done' }
  return { outcome: 'retry', error: legError(result) }
}

const leg = {
  leg: 'discord',
  label: 'Discord #news',
  dispatch,
  classify,
}

module.exports = { leg, dispatch, classify }
