/**
 * @jest-environment node
 */

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

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

jest.mock("@/lib/database", () => ({
  getDatabase: jest.fn(),
}));

jest.mock("@/lib/sync-user", () => ({
  ensureUserSynced: jest.fn(),
}));

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

describe("/api/trainer-client authz", () => {
  const mockAuth = require("@clerk/nextjs/server").auth as jest.Mock;
  const mockGetDatabase = require("@/lib/database").getDatabase as jest.Mock;
  const mockEnsureUserSynced = require("@/lib/sync-user")
    .ensureUserSynced as jest.Mock;

  const mockDb = {
    getUserById: jest.fn(),
    getTrainerClientAssignments: jest.fn(),
    getAllTrainerClientAssignments: jest.fn(),
    createTrainerClientAssignment: jest.fn(),
  };

  beforeEach(() => {
    jest.clearAllMocks();
    mockGetDatabase.mockResolvedValue(mockDb);
  });

  it("blocks non-admin users from listing assignments", async () => {
    mockAuth.mockResolvedValue({ userId: "trainer_1" });
    mockEnsureUserSynced.mockResolvedValue({
      id: "trainer_1",
      role: "trainer",
      gymId: "gym_a",
    });

    const request = new NextRequest("http://localhost/api/trainer-client");
    const response = await GET(request);

    expect(response.status).toBe(403);
  });

  it("blocks admins from creating assignments across gyms", async () => {
    mockAuth.mockResolvedValue({ userId: "admin_1" });
    mockEnsureUserSynced.mockResolvedValue({
      id: "admin_1",
      role: "admin",
      gymId: "gym_a",
    });

    mockDb.getUserById
      .mockResolvedValueOnce({
        id: "trainer_2",
        role: "trainer",
        gymId: "gym_b",
      })
      .mockResolvedValueOnce({
        id: "client_2",
        role: "client",
        gymId: "gym_b",
      });

    const request = new NextRequest("http://localhost/api/trainer-client", {
      method: "POST",
      body: JSON.stringify({ trainerId: "trainer_2", clientId: "client_2" }),
    });

    const response = await POST(request);

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