/**
 * Unit tests for the email service's structured `{ ok, error? }` return.
 *
 * The shared `sendEmail` helper is private, but `sendWelcomeEmail`
 * calls it and is exported, so we exercise the happy path + the two
 * new error paths (no API key, Resend 4xx/5xx with JSON body) through
 * the public surface.
 */
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";

const originalFetch = global.fetch;
const originalKey = process.env.RESEND_API_KEY;

beforeEach(() => {
  vi.clearAllMocks();
});

afterEach(() => {
  global.fetch = originalFetch;
  if (originalKey === undefined) {
    delete process.env.RESEND_API_KEY;
  } else {
    process.env.RESEND_API_KEY = originalKey;
  }
});

async function importFresh() {
  // Re-import the module after toggling RESEND_API_KEY / mocking fetch
  // so the module-level constants pick up the new env.
  vi.resetModules();
  return await import("@/lib/email-service");
}

describe("sendWelcomeEmail — structured error reporting", () => {
  it("returns ok=true when Resend accepts the message", async () => {
    process.env.RESEND_API_KEY = "re_test_key";
    global.fetch = vi.fn().mockResolvedValue({
      ok: true,
      status: 200,
      json: async () => ({ id: "email-abc" }),
    } as Response);
    const { sendWelcomeEmail } = await importFresh();
    const r = await sendWelcomeEmail({
      to: "u@example.com",
      name: "U",
      role: "brand_admin",
      brandName: "Tuxedo",
      tempPassword: "TempPass123!",
    });
    expect(r.ok).toBe(true);
  });

  it("returns a clear error when RESEND_API_KEY is missing", async () => {
    delete process.env.RESEND_API_KEY;
    const { sendWelcomeEmail } = await importFresh();
    const r = await sendWelcomeEmail({
      to: "u@example.com",
      name: "U",
      role: "brand_admin",
      brandName: "Tuxedo",
      tempPassword: "TempPass123!",
    });
    expect(r.ok).toBe(false);
    if (!r.ok) {
      expect(r.error).toMatch(/RESEND_API_KEY is not set/i);
    }
  });

  it("surfaces Resend's actual error message on 4xx/5xx", async () => {
    process.env.RESEND_API_KEY = "re_test_key";
    global.fetch = vi.fn().mockResolvedValue({
      ok: false,
      status: 422,
      json: async () => ({
        name: "validation_error",
        message: "The gmail.com domain is not verified",
      }),
    } as Response);
    const { sendWelcomeEmail } = await importFresh();
    const r = await sendWelcomeEmail({
      to: "u@gmail.com",
      name: "U",
      role: "brand_admin",
      brandName: "Tuxedo",
      tempPassword: "TempPass123!",
    });
    expect(r.ok).toBe(false);
    if (!r.ok) {
      expect(r.error).toContain("Resend 422");
      expect(r.error).toContain("validation_error");
      expect(r.error).toContain("gmail.com domain is not verified");
    }
  });

  it("surfaces the Resend message even when the response body is not JSON", async () => {
    process.env.RESEND_API_KEY = "re_test_key";
    global.fetch = vi.fn().mockResolvedValue({
      ok: false,
      status: 500,
      json: async () => {
        throw new Error("not json");
      },
    } as unknown as Response);
    const { sendWelcomeEmail } = await importFresh();
    const r = await sendWelcomeEmail({
      to: "u@example.com",
      name: "U",
      role: "brand_admin",
      brandName: "Tuxedo",
      tempPassword: "TempPass123!",
    });
    expect(r.ok).toBe(false);
    if (!r.ok) {
      expect(r.error).toBe("Resend 500");
    }
  });

  it("surfaces network errors verbatim", async () => {
    process.env.RESEND_API_KEY = "re_test_key";
    global.fetch = vi.fn().mockRejectedValue(new Error("fetch failed: ECONNREFUSED"));
    const { sendWelcomeEmail } = await importFresh();
    const r = await sendWelcomeEmail({
      to: "u@example.com",
      name: "U",
      role: "brand_admin",
      brandName: "Tuxedo",
      tempPassword: "TempPass123!",
    });
    expect(r.ok).toBe(false);
    if (!r.ok) {
      expect(r.error).toBe("fetch failed: ECONNREFUSED");
    }
  });
});
