/**
 * @jest-environment node
 */

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

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

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

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

jest.mock("@fitai/database", () => ({
  db: {
    all: jest.fn(),
    get: jest.fn(),
    run: jest.fn(),
  },
  sql: jest.fn((strings: TemplateStringsArray) => strings.join("")),
}));

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

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

  const mockDb = {
    getUserById: jest.fn(),
    deleteUser: jest.fn(),
  };

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

  it("blocks self deletion", async () => {
    mockAuth.mockResolvedValue({ userId: "admin_1" });
    mockEnsureUserSynced.mockResolvedValue({
      id: "admin_1",
      role: "admin",
      gymId: "gym_a",
    });

    const request = new NextRequest("http://localhost/api/users?id=admin_1", {
      method: "DELETE",
    });

    const response = await DELETE(request);
    expect(response.status).toBe(403);
    expect(mockDb.deleteUser).not.toHaveBeenCalled();
  });

  it("blocks cross-gym deletion for admin", async () => {
    mockAuth.mockResolvedValue({ userId: "admin_1" });
    mockEnsureUserSynced.mockResolvedValue({
      id: "admin_1",
      role: "admin",
      gymId: "gym_a",
    });
    mockDb.getUserById.mockResolvedValue({ id: "user_2", gymId: "gym_b" });

    const request = new NextRequest("http://localhost/api/users?id=user_2", {
      method: "DELETE",
    });

    const response = await DELETE(request);
    expect(response.status).toBe(403);
    expect(mockDb.deleteUser).not.toHaveBeenCalled();
  });

  it("allows superAdmin cross-gym deletion", async () => {
    mockAuth.mockResolvedValue({ userId: "super_1" });
    mockEnsureUserSynced.mockResolvedValue({
      id: "super_1",
      role: "superAdmin",
      gymId: null,
    });
    mockDb.getUserById.mockResolvedValue({ id: "user_2", gymId: "gym_b" });

    const request = new NextRequest("http://localhost/api/users?id=user_2", {
      method: "DELETE",
    });

    const response = await DELETE(request);
    const payload = await response.json();

    expect(response.status).toBe(200);
    expect(payload.success).toBe(true);
    expect(mockDb.deleteUser).toHaveBeenCalledWith("user_2");
  });
});
