/**
 * Email provider abstraction.
 *
 * Resolution:
 *   - RESEND_API_KEY set + non-empty → ResendProvider
 *   - else → MockProvider (logs to stdout, swallows errors)
 *
 * Templates live in `lib/email/templates/*.tsx` (or .ts for plain HTML).
 * Each call goes through `sendEmail({ to, subject, html, text? })`.
 *
 * Security:
 *   - Caller must pre-render HTML; provider never accepts raw user input
 *     in subjects without truncation.
 *   - Reply-to defaults to EMAIL_FROM.
 */

export type SendInput = {
  to: string | string[];
  subject: string;
  html: string;
  text?: string;
  /** Override the default From header (rare — reminders, password reset use default). */
  from?: string;
  /** Optional Reply-To header. Defaults to from. */
  replyTo?: string;
  /** Tag for analytics / Resend dashboard filtering. */
  tag?: string;
};

export type SendResult = { ok: true; id: string } | { ok: false; error: string };

export interface EmailProvider {
  readonly name: string;
  send(input: SendInput): Promise<SendResult>;
}

const MAX_SUBJECT = 200;

function sanitizeSubject(s: string): string {
  // Strip CR/LF (header injection) and clamp length.
  return s
    .replace(/[\r\n]+/g, " ")
    .trim()
    .slice(0, MAX_SUBJECT);
}

class MockProvider implements EmailProvider {
  readonly name = "mock";
  async send(input: SendInput): Promise<SendResult> {
    const id = `mock_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
    const subject = sanitizeSubject(input.subject);
    // Print enough to debug locally without dumping full HTML.
     
    console.log(
      `[email:mock] → ${Array.isArray(input.to) ? input.to.join(",") : input.to} | ${subject} | tag=${input.tag ?? "-"} | id=${id}`
    );
    return { ok: true, id };
  }
}

class ResendProvider implements EmailProvider {
  readonly name = "resend";
  constructor(
    private apiKey: string,
    private defaultFrom: string
  ) {}

  async send(input: SendInput): Promise<SendResult> {
    const subject = sanitizeSubject(input.subject);
    const body: Record<string, unknown> = {
      from: input.from ?? this.defaultFrom,
      to: Array.isArray(input.to) ? input.to : [input.to],
      subject,
      html: input.html,
    };
    if (input.text) body.text = input.text;
    if (input.replyTo) body.reply_to = input.replyTo;
    if (input.tag) body.tags = [{ name: "category", value: input.tag }];

    try {
      const res = await fetch("https://api.resend.com/emails", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${this.apiKey}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify(body),
      });
      if (!res.ok) {
        const errText = await res.text().catch(() => "");
        return { ok: false, error: `resend ${res.status}: ${errText.slice(0, 200)}` };
      }
      const data = (await res.json().catch(() => ({}))) as { id?: string };
      return { ok: true, id: data.id ?? "resend_unknown" };
    } catch (e) {
      return { ok: false, error: e instanceof Error ? e.message : String(e) };
    }
  }
}

let cached: EmailProvider | null = null;

export function getEmailProvider(): EmailProvider {
  if (cached) return cached;
  const apiKey = process.env.RESEND_API_KEY?.trim();
  const defaultFrom = process.env.EMAIL_FROM?.trim() || "noreply@tuvi.local";
  if (apiKey) {
    cached = new ResendProvider(apiKey, defaultFrom);
  } else {
    cached = new MockProvider();
  }
  return cached;
}

/** Force re-resolution (tests). */
export function resetEmailProvider(): void {
  cached = null;
}

/** Ergonomic wrapper. Returns `{ ok, id?, error? }`. */
export async function sendEmail(input: SendInput): Promise<SendResult> {
  return getEmailProvider().send(input);
}
