import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { NextRequest } from "next/server";

const mockAdminSession = { user: { id: "admin-1", role: "admin" } };

vi.mock("@/lib/api-auth", () => ({
  requireAdmin: vi.fn(),
}));

vi.mock("@/lib/email", () => ({
  sendEmail: vi.fn().mockResolvedValue(undefined),
  verifyEmailHtml: vi.fn((url: string) => `<a href="${url}">verify</a>`),
}));

const { requireAdmin } = await import("@/lib/api-auth");
const { sendEmail } = await import("@/lib/email");
import { POST } from "../route";

function makeRequest(body: unknown) {
  return new NextRequest("http://localhost/api/v1/admin/test-email", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body),
  });
}

const ORIGINAL_ENV = process.env["BETTER_AUTH_URL"];

beforeEach(() => {
  vi.clearAllMocks();
  vi.mocked(requireAdmin).mockResolvedValue({ session: mockAdminSession as never, response: null });
  process.env["BETTER_AUTH_URL"] = "https://epicure.example.com";
});

afterEach(() => {
  if (ORIGINAL_ENV === undefined) delete process.env["BETTER_AUTH_URL"];
  else process.env["BETTER_AUTH_URL"] = ORIGINAL_ENV;
});

describe("POST /api/v1/admin/test-email", () => {
  it("returns 403 when caller is not an admin", async () => {
    vi.mocked(requireAdmin).mockResolvedValue({
      session: null,
      response: new Response(JSON.stringify({ error: "Forbidden" }), { status: 403 }),
    } as never);

    const res = await POST(makeRequest({ to: "user@example.com" }));
    expect(res.status).toBe(403);
  });

  it("returns 400 when 'to' is missing", async () => {
    const res = await POST(makeRequest({}));
    expect(res.status).toBe(400);
  });

  it("returns 500 when BETTER_AUTH_URL is not configured", async () => {
    delete process.env["BETTER_AUTH_URL"];
    const res = await POST(makeRequest({ to: "user@example.com" }));
    expect(res.status).toBe(500);
    expect(sendEmail).not.toHaveBeenCalled();
  });

  it("sends the test email using the configured base URL", async () => {
    const res = await POST(makeRequest({ to: "user@example.com" }));
    expect(res.status).toBe(200);
    expect(sendEmail).toHaveBeenCalledWith(
      expect.objectContaining({ to: "user@example.com" })
    );
  });
});
