/**
 * @jest-environment node
 */

import { NextRequest } from "next/server";
import { POST } from "../route";

jest.mock("@clerk/nextjs/server", () => ({
  auth: jest.fn(),
  clerkClient: jest.fn(),
}));

jest.mock("@/lib/auth/context", () => ({
  getAuthContext: jest.fn(),
}));

jest.mock("@/lib/logger", () => ({
  info: jest.fn(),
  warn: jest.fn(),
  error: jest.fn(),
  debug: jest.fn(),
}));

describe("POST /api/invitations authz", () => {
  const mockAuth = require("@clerk/nextjs/server").auth as jest.Mock;
  const mockClerkClient = require("@clerk/nextjs/server")
    .clerkClient as jest.Mock;
  const mockGetAuthContext = require("@/lib/auth/context")
    .getAuthContext as jest.Mock;

  const createInvitation = jest.fn();

  beforeEach(() => {
    jest.clearAllMocks();
    mockClerkClient.mockResolvedValue({
      invitations: {
        createInvitation,
      },
    });
  });

  it("blocks admin from inviting into another gym", async () => {
    mockAuth.mockResolvedValue({ userId: "admin_1" });
    mockGetAuthContext.mockResolvedValue({
      userId: "admin_1",
      role: "admin",
      gymId: "gym_a",
    });

    const request = new NextRequest("http://localhost/api/invitations", {
      method: "POST",
      body: JSON.stringify({
        inviteeEmail: "test@example.com",
        roleAssigned: "trainer",
        gymId: "gym_b",
      }),
    });

    const response = await POST(request);

    expect(response.status).toBe(403);
    expect(createInvitation).not.toHaveBeenCalled();
  });

  it("allows superAdmin to invite with explicit gym", async () => {
    mockAuth.mockResolvedValue({ userId: "super_1" });
    mockGetAuthContext.mockResolvedValue({
      userId: "super_1",
      role: "superAdmin",
      gymId: null,
    });
    createInvitation.mockResolvedValue({ id: "inv_1" });

    const request = new NextRequest("http://localhost/api/invitations", {
      method: "POST",
      body: JSON.stringify({
        inviteeEmail: "test@example.com",
        roleAssigned: "admin",
        gymId: "gym_b",
      }),
    });

    const response = await POST(request);

    expect(response.status).toBe(201);
    expect(createInvitation).toHaveBeenCalledWith(
      expect.objectContaining({
        emailAddress: "test@example.com",
      }),
    );
  });
});
