/**
 * Unit tests for `signInWithGoogleAction` in `src/actions/auth-actions.ts`.
 *
 * The action wraps Neon Auth's `signIn.social({ provider: "google" })`
 * and returns the redirect URL to the client. It must:
 *   - Return `{ url, error: null }` when Neon Auth responds with a URL.
 *   - Return `{ url: null, error }` on any auth error / network failure.
 *   - Pass through `callbackURL` and `errorCallbackURL` to Neon Auth.
 */
import { describe, it, expect, vi, beforeEach } from "vitest";

const { mockSocial } = vi.hoisted(() => ({
  mockSocial: vi.fn(),
}));

vi.mock("server-only", () => ({}));
// `signIn` is a namespace object re-exported from @/lib/auth with
// methods like `email`, `social`, etc. — mock the whole thing.
vi.mock("@/lib/auth", () => ({
  signIn: { social: mockSocial },
  signOut: vi.fn(),
}));

vi.mock("next/navigation", () => ({
  redirect: vi.fn(),
}));

const { signInWithGoogleAction } = await import("@/actions/auth-actions");

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

describe("signInWithGoogleAction", () => {
  it("returns the Neon Auth redirect URL on success", async () => {
    mockSocial.mockResolvedValue({
      data: { url: "https://accounts.google.com/o/oauth2/v2/auth?..." },
      error: null,
    });
    const r = await signInWithGoogleAction({ callbackURL: "/admin" });
    expect(r.error).toBeNull();
    expect(r.url).toBe("https://accounts.google.com/o/oauth2/v2/auth?...");
    expect(mockSocial).toHaveBeenCalledWith({
      provider: "google",
      callbackURL: "/admin",
      errorCallbackURL: "/login?error=oauth",
    });
  });

  it("defaults callbackURL to /admin and errorCallbackURL to /login?error=oauth", async () => {
    mockSocial.mockResolvedValue({ data: { url: "https://x" }, error: null });
    await signInWithGoogleAction({});
    expect(mockSocial).toHaveBeenCalledWith({
      provider: "google",
      callbackURL: "/admin",
      errorCallbackURL: "/login?error=oauth",
    });
  });

  it("passes through a custom errorCallbackURL", async () => {
    mockSocial.mockResolvedValue({ data: { url: "https://x" }, error: null });
    await signInWithGoogleAction({
      callbackURL: "/wholesale/portal",
      errorCallbackURL: "/wholesale/login?error=oauth",
    });
    expect(mockSocial).toHaveBeenCalledWith({
      provider: "google",
      callbackURL: "/wholesale/portal",
      errorCallbackURL: "/wholesale/login?error=oauth",
    });
  });

  it("returns a structured error when Neon Auth rejects the request", async () => {
    mockSocial.mockResolvedValue({
      data: null,
      error: { code: "PROVIDER_NOT_CONFIGURED", message: "Google OAuth is not enabled" },
    });
    const r = await signInWithGoogleAction({});
    expect(r.url).toBeNull();
    expect(r.error).toBe("Google OAuth is not enabled");
  });

  it("returns a structured error when the response has no URL", async () => {
    mockSocial.mockResolvedValue({ data: {}, error: null });
    const r = await signInWithGoogleAction({});
    expect(r.url).toBeNull();
    expect(r.error).toMatch(/no redirect URL/i);
  });

  it("returns a structured error on unexpected exceptions", async () => {
    mockSocial.mockRejectedValue(new Error("network down"));
    const r = await signInWithGoogleAction({});
    expect(r.url).toBeNull();
    expect(r.error).toBe("network down");
  });
});
