import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { sendMessage } from "./graph-mail.js";
import * as store from "./store.js";

describe("graphFetch — empty-body success responses", () => {
  let originalFetch: typeof fetch;

  beforeEach(() => {
    originalFetch = globalThis.fetch;
    vi.spyOn(store, "getAccessToken").mockResolvedValue("test-bearer-token");
  });

  afterEach(() => {
    globalThis.fetch = originalFetch;
    vi.restoreAllMocks();
  });

  it("resolves on HTTP 202 with empty body (the /me/sendMail success shape)", async () => {
    const fetchMock = vi.fn().mockResolvedValue(
      new Response("", {
        status: 202,
        statusText: "Accepted",
      }),
    );
    globalThis.fetch = fetchMock as unknown as typeof fetch;

    await expect(
      sendMessage({
        to: ["test@example.com"],
        subject: "test",
        body: "test body",
      }),
    ).resolves.toBeUndefined();

    expect(fetchMock).toHaveBeenCalledOnce();
    const [url, init] = fetchMock.mock.calls[0]!;
    expect(url).toBe("https://graph.microsoft.com/v1.0/me/sendMail");
    expect(init?.method).toBe("POST");
  });

  it("resolves on HTTP 204 with empty body (existing behavior preserved)", async () => {
    const fetchMock = vi.fn().mockResolvedValue(
      new Response(null, {
        status: 204,
        statusText: "No Content",
      }),
    );
    globalThis.fetch = fetchMock as unknown as typeof fetch;

    await expect(
      sendMessage({
        to: ["test@example.com"],
        subject: "test",
        body: "test body",
      }),
    ).resolves.toBeUndefined();
  });

  it("propagates 4xx errors with body text in the thrown message", async () => {
    const fetchMock = vi.fn().mockResolvedValue(
      new Response(JSON.stringify({ error: { message: "InvalidRecipient" } }), {
        status: 400,
        statusText: "Bad Request",
      }),
    );
    globalThis.fetch = fetchMock as unknown as typeof fetch;

    await expect(
      sendMessage({
        to: ["test@example.com"],
        subject: "test",
        body: "test body",
      }),
    ).rejects.toThrow(/Graph API .* failed \(400\)/);
  });
});
