import { beforeEach, describe, expect, it, vi } from "vitest";

const apiClient = {
  get: vi.fn(),
  post: vi.fn(),
  put: vi.fn(),
  patch: vi.fn(),
  delete: vi.fn(),
};

const fetchAllCursorPages = vi.fn(async () => ({
  items: [{ id: "tenant-1", name: "Tenant", slug: "tenant" }],
  total: 1,
}));

vi.mock("./apiClient", () => ({
  default: apiClient,
}));

vi.mock("./auth", () => ({
  userManager: {
    getUser: vi.fn(async () => ({ access_token: "access-token" })),
  },
}));

vi.mock("../../../common/core/pagination", () => ({
  fetchAllCursorPages,
}));

describe("adminApi endpoint contracts", () => {
  beforeEach(() => {
    apiClient.get.mockReset();
    apiClient.post.mockReset();
    apiClient.put.mockReset();
    apiClient.patch.mockReset();
    apiClient.delete.mockReset();

    apiClient.get.mockResolvedValue({
      data: { ok: true },
      headers: { "content-disposition": 'attachment; filename="export.csv"' },
    });
    apiClient.post.mockResolvedValue({ data: { ok: true } });
    apiClient.put.mockResolvedValue({ data: { ok: true } });
    apiClient.patch.mockResolvedValue({ data: { ok: true } });
    apiClient.delete.mockResolvedValue({ data: { ok: true } });
    fetchAllCursorPages.mockClear();
    window.localStorage.clear();
  });

  it("routes read APIs to their documented admin endpoints", async () => {
    const adminApi = await import("./adminApi");

    await adminApi.fetchAuditLogs(10, "cursor-a");
    await adminApi.fetchAdminOverviewStats();
    await adminApi.fetchDataIntegrityReport();
    await adminApi.fetchOrphanUserLoginIDs();
    await adminApi.fetchOrySSOTSystemStatus();
    await adminApi.fetchAdminRPUsageDaily({
      days: 30,
      period: "week",
      tenantId: "tenant-1",
    });
    await adminApi.fetchTenants(25, 50, "parent-1", "cursor-b");
    await adminApi.fetchAllTenants({ pageSize: 200, parentId: "parent-1" });
    await adminApi.fetchTenant("tenant-1");
    await adminApi.fetchTenantAdmins("tenant-1");
    await adminApi.fetchTenantOwners("tenant-1");
    await adminApi.fetchGroups("tenant-1");
    await adminApi.fetchGroup("tenant-1", "group-1");
    await adminApi.fetchGroupRoles("tenant-1", "group-1");
    await adminApi.fetchApiKeys(20, 40);
    await adminApi.fetchUsers(30, 60, "admin", "tenant");
    await adminApi.fetchUser("user-1");
    await adminApi.fetchWorksmobileOverview("tenant-1");
    await adminApi.fetchWorksmobileComparison("tenant-1", true);
    await adminApi.fetchWorksmobileCredentialBatches("tenant-1");
    await adminApi.downloadWorksmobileInitialPasswordsCSV("tenant-1");
    await adminApi.downloadWorksmobileInitialPasswordsCSV(
      "tenant-1",
      "credential-batch-1",
    );
    await adminApi.fetchPasswordPolicy();
    await adminApi.fetchUserRpHistory("user-1");
    await adminApi.fetchMe();
    await adminApi.fetchRelyingParties("tenant-1");
    await adminApi.fetchAllRelyingParties();
    await adminApi.fetchRelyingParty("client-1");
    await adminApi.fetchRPOwners("client-1");

    expect(apiClient.get).toHaveBeenCalledWith("/v1/audit", {
      params: { limit: 10, cursor: "cursor-a" },
    });
    expect(apiClient.get).toHaveBeenCalledWith("/v1/admin/ory/ssot");
    expect(apiClient.get).toHaveBeenCalledWith("/v1/admin/tenants", {
      params: {
        limit: 25,
        offset: 50,
        parentId: "parent-1",
        cursor: "cursor-b",
      },
    });
    expect(fetchAllCursorPages).toHaveBeenCalledWith(
      expect.objectContaining({
        path: "/v1/admin/tenants",
        pageSize: 200,
        params: { parentId: "parent-1" },
      }),
    );
    expect(apiClient.get).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/comparison",
      { params: { includeMatched: true } },
    );
    expect(apiClient.get).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/credential-batches",
    );
    expect(apiClient.get).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/initial-passwords.csv",
      {
        params: { batchId: "credential-batch-1" },
        responseType: "blob",
      },
    );
    expect(await adminApi.exportTenantsCSV(true, "parent-1")).toMatchObject({
      filename: "export.csv",
    });
    expect(
      await adminApi.exportUsersCSV("admin", "tenant", true),
    ).toMatchObject({
      filename: "export.csv",
    });
  });

  it("routes mutation APIs to their documented admin endpoints", async () => {
    const adminApi = await import("./adminApi");

    await adminApi.deleteOrphanUserLoginIDs(["orphan-1"]);
    await adminApi.flushIdentityCache();
    await adminApi.createTenant({ name: "Tenant", slug: "tenant" });
    await adminApi.updateTenant("tenant-1", { status: "inactive" });
    await adminApi.deleteTenant("tenant-1");
    await adminApi.deleteTenantsBulk(["tenant-1"]);
    await adminApi.importTenantsCSV(new File(["name"], "tenants.csv"));
    await adminApi.approveTenant("tenant-1");
    await adminApi.addTenantAdmin("tenant-1", "user-1");
    await adminApi.removeTenantAdmin("tenant-1", "user-1");
    await adminApi.addTenantOwner("tenant-1", "user-1");
    await adminApi.removeTenantOwner("tenant-1", "user-1");
    await adminApi.createGroup("tenant-1", { name: "Group" });
    await adminApi.deleteGroup("tenant-1", "group-1");
    await adminApi.addGroupMember("tenant-1", "group-1", "user-1");
    await adminApi.removeGroupMember("tenant-1", "group-1", "user-1");
    await adminApi.assignGroupRole("tenant-1", "group-1", "tenant-2", "owner");
    await adminApi.removeGroupRole("tenant-1", "group-1", "tenant-2", "owner");
    await adminApi.createApiKey({ name: "key", scopes: ["read"] });
    await adminApi.updateApiKeyScopes("key-1", { scopes: ["write"] });
    await adminApi.rotateApiKeySecret("key-1");
    await adminApi.deleteApiKey("key-1");
    await adminApi.createUser({ email: "user@example.com", name: "User" });
    await adminApi.bulkCreateUsers([
      { email: "user@example.com", name: "User", metadata: {} },
    ]);
    await adminApi.enqueueWorksmobileBackfillDryRun("tenant-1");
    await adminApi.enqueueWorksmobileOrgUnitSync("tenant-1", "org/unit");
    await adminApi.enqueueWorksmobileOrgUnitDelete("tenant-1", "org/unit");
    await adminApi.enqueueWorksmobileUserSync("tenant-1", "user-1");
    await adminApi.enqueueWorksmobileUserSync(
      "tenant-1",
      "user-2",
      "credential-batch-1",
      "InputPass1!",
    );
    await adminApi.resetWorksmobileUserPassword(
      "tenant-1",
      "user-2",
      "credential-batch-2",
    );
    await adminApi.deleteWorksmobileCredentialBatchPasswords(
      "tenant-1",
      "credential-batch-1",
    );
    await adminApi.retryWorksmobileJob("tenant-1", "job-1");
    await adminApi.bulkUpdateUsers({ userIds: ["user-1"], status: "inactive" });
    await adminApi.bulkDeleteUsers(["user-1"]);
    await adminApi.updateUser("user-1", { status: "active" });
    await adminApi.deleteUser("user-1");
    await adminApi.createRelyingParty("tenant-1", {
      client_name: "RP",
      redirect_uris: ["https://rp.example/callback"],
    });
    await adminApi.updateRelyingParty("client-1", {
      client_name: "RP",
      redirect_uris: ["https://rp.example/callback"],
    });
    await adminApi.deleteRelyingParty("client-1");
    await adminApi.addRPOwner("client-1", "User:user-1");
    await adminApi.removeRPOwner("client-1", "User:user-1");

    expect(apiClient.delete).toHaveBeenCalledWith(
      "/v1/admin/integrity/orphan-user-login-ids",
      { data: { ids: ["orphan-1"] } },
    );
    expect(apiClient.post).toHaveBeenCalledWith(
      "/v1/admin/ory/ssot/identity-cache/flush",
    );
    expect(apiClient.put).toHaveBeenCalledWith("/v1/admin/users/user-1", {
      status: "active",
    });
    expect(apiClient.post).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/orgunits/org%2Funit/sync",
    );
    expect(apiClient.post).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/users/user-2/sync",
      {
        credentialBatchId: "credential-batch-1",
        initialPassword: "InputPass1!",
      },
    );
    expect(apiClient.post).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/users/user-2/password/reset",
      { credentialBatchId: "credential-batch-2" },
    );
    expect(apiClient.delete).toHaveBeenCalledWith(
      "/v1/admin/tenants/tenant-1/worksmobile/credential-batches/credential-batch-1/passwords",
    );
    expect(apiClient.delete).toHaveBeenCalledWith(
      "/v1/admin/relying-parties/client-1/owners/User:user-1",
    );
  });
});
