import { Resend } from "resend";
import { Webhook } from "svix";

import { env } from "../../config.js";
import type { EmailEvent, EmailProvider, SendEmailInput, SendEmailResult } from "./provider.js";

export class ResendProvider implements EmailProvider {
  private client = env.RESEND_API_KEY ? new Resend(env.RESEND_API_KEY) : null;

  private extractRecipient(data: Record<string, unknown>) {
    if (typeof data.to === "string") {
      return data.to;
    }

    if (Array.isArray(data.to)) {
      const firstRecipient = data.to.find((value) => typeof value === "string" && value.trim());
      if (typeof firstRecipient === "string") {
        return firstRecipient;
      }
    }

    if (typeof data.recipient === "string" && data.recipient.trim()) {
      return data.recipient;
    }

    if (typeof data.email === "string" && data.email.trim()) {
      return data.email;
    }

    return null;
  }

  async sendTestEmail(input: SendEmailInput): Promise<SendEmailResult> {
    return this.send(input);
  }

  async sendCampaignBatch(input: SendEmailInput): Promise<SendEmailResult> {
    return this.send(input);
  }

  async parseWebhookEvent(headers: Record<string, string | undefined>, body: string): Promise<EmailEvent | null> {
    if (!body) {
      return null;
    }

    let payload: Record<string, unknown>;

    if (env.RESEND_WEBHOOK_SECRET) {
      const webhook = new Webhook(env.RESEND_WEBHOOK_SECRET);
      payload = webhook.verify(body, {
        "svix-id": headers["svix-id"] ?? "",
        "svix-timestamp": headers["svix-timestamp"] ?? "",
        "svix-signature": headers["svix-signature"] ?? ""
      }) as Record<string, unknown>;
    } else {
      payload = JSON.parse(body) as Record<string, unknown>;
    }

    const type = typeof payload.type === "string" ? payload.type : "unknown";
    const data = (payload.data ?? {}) as Record<string, unknown>;

    return {
      provider: "resend",
      eventType: type,
      externalId: typeof data.email_id === "string" ? data.email_id : null,
      recipient: this.extractRecipient(data),
      payload
    };
  }

  private async send(input: SendEmailInput): Promise<SendEmailResult> {
    if (!this.client) {
      return {
        provider: "resend",
        messageIds: [`mock-${Date.now()}`],
        raw: { mocked: true }
      };
    }

    const result = await this.client.emails.send({
      from: input.from,
      to: input.to,
      replyTo: input.replyTo,
      subject: input.subject,
      html: input.html,
      text: input.text,
      tags: input.tags,
      headers: input.headers,
    });

    if (result.error) {
      throw new Error(result.error.message);
    }

    return {
      provider: "resend",
      messageIds: result.data?.id ? [result.data.id] : [],
      raw: result.data
    };
  }
}
