// Hostinger Email API transport (https://api.mail.hostinger.com).
//
// Send endpoint: POST /api/v1/mailboxes/{mailboxResourceId}/send
// Auth: Authorization: Bearer <token>  (token + mailbox are scoped to one order)
// The From identity is implicit — it is the mailbox the token is authorized for,
// so the body carries no `from` field.
//
// `sendViaHostingerMail` throws on any non-2xx so the caller can fall back to
// SMTP and/or let the queue retry. The thrown Error carries `.status` so HTTP
// 429 can be mapped to the dispatcher's existing rate-limit backoff.

export type HostingerMailConfig = {
  token: string;
  mailboxResourceId: string;
};

export type HostingerMessage = {
  to: string;
  subject: string;
  html: string;
  text?: string;
};

const BASE_URL = 'https://api.mail.hostinger.com';

export class HostingerMailError extends Error {
  status: number;
  constructor(message: string, status: number) {
    super(message);
    this.name = 'HostingerMailError';
    this.status = status;
  }
}

export async function sendViaHostingerMail(
  cfg: HostingerMailConfig,
  msg: HostingerMessage,
): Promise<void> {
  if (!cfg.token || !cfg.mailboxResourceId) {
    throw new Error('Hostinger mail config incomplete (token and mailboxResourceId required)');
  }

  const url = `${BASE_URL}/api/v1/mailboxes/${encodeURIComponent(cfg.mailboxResourceId)}/send`;
  const body = {
    to: [msg.to],
    subject: msg.subject,
    html: msg.html,
    text: msg.text && msg.text.trim() ? msg.text : undefined,
  };

  const resp = await fetch(url, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${cfg.token}`,
      'Content-Type': 'application/json',
      Accept: 'application/json',
    },
    body: JSON.stringify(body),
  });

  if (!resp.ok) {
    let detail = '';
    try { detail = (await resp.text()).slice(0, 500); } catch { /* ignore */ }
    throw new HostingerMailError(
      `Hostinger mail API ${resp.status} ${resp.statusText}: ${detail}`,
      resp.status,
    );
  }
  // Drain the body so the connection can be reused.
  try { await resp.text(); } catch { /* ignore */ }
}
