import type { Channel, Notification } from './types';
import { renderTitle } from './text';

// Discord notifications, via a channel webhook.
//
// Moved here from src/servers/notify/discord.ts when the notify sidecar took over outbound notification:
// one surface, several channels, rather than a Discord path and a push path that do not know about each
// other. Officer used to run a full Discord bot — gateway, commands, pairing, an admin screen and a token
// in the database — and all of that is gone; what survives is the one useful piece, pushing a message out.
//
// Configured by env, so there is no UI, no pairing and no stored credential:
//   DISCORD_WEBHOOK_URL   unset = channel skipped entirely.
//
// The same payload discipline applies here as to APNs and FCM. A Discord webhook is a third party too,
// and its history is searchable and permanent in a way a push banner is not — arguably it deserves the
// rule more, not less.

const WEBHOOK_URL = process.env.DISCORD_WEBHOOK_URL;

export const discordChannel: Channel = {
  name: 'discord',

  isConfigured: () => Boolean(WEBHOOK_URL),

  async send(n: Notification) {
    if (!WEBHOOK_URL) return { channel: 'discord', sent: 0, failed: 0 };

    // Discord rejects anything over 2000 characters outright.
    const content = renderTitle(n).slice(0, 2000);

    try {
      const res = await fetch(WEBHOOK_URL, {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ content }),
        signal: AbortSignal.timeout(10_000),
      });
      if (!res.ok) {
        console.error(`[notify:discord] webhook returned ${res.status}`);
        return { channel: 'discord', sent: 0, failed: 1 };
      }
      return { channel: 'discord', sent: 1, failed: 0 };
    } catch (err) {
      console.error('[notify:discord] failed to send:', err instanceof Error ? err.message : err);
      return { channel: 'discord', sent: 0, failed: 1 };
    }
  },
};
