import { describe, expect, inject, it } from "vitest";
import { createGraphQLClient, graphql } from "@/tests/utils/graphql-client";

const createRole = graphql(`
  mutation ($name: String!, $permissions: [String!]!) {
    createRole(name: $name, permissions: $permissions) {
      id
    }
  }
`);

const updateRole = graphql(`
  mutation ($roleId: ID!, $permissions: [String!]!) {
    updateRole(roleId: $roleId, permissions: $permissions) {
      roleId
    }
  }
`);

const getRole = graphql(`
  query GetRole($roleId: ID!) {
    role(id: $roleId) {
      id
      permissions
    }
  }
`);

describe("user--update-role-permissions", () => {
  const gql = createGraphQLClient(inject("url"), inject("token"));

  it("Add a permission to a role and submit; verify the updated permissions are reflected on the role detail", async () => {
    const perm1 = "user-management:user:createUser";
    const perm2 = "user-management:user:updateUser";

    const roleResult = await gql
      .mutation(createRole, { name: `PermRole-${Date.now()}`, permissions: [perm1] })
      .toPromise();
    const roleId = roleResult.data!.createRole.id;

    const result = await gql
      .mutation(updateRole, { roleId, permissions: [perm1, perm2] })
      .toPromise();

    expect(result.data!.updateRole.roleId).toBe(roleId);

    const roleDetail = await gql.query(getRole, { roleId }).toPromise();
    const permissions = roleDetail.data?.role?.permissions as string[] | undefined;
    expect(permissions).toContain(perm1);
    expect(permissions).toContain(perm2);
  });

  it("Remove all user-selected permissions from a role and submit; verify auto-assigned permissions are preserved", async () => {
    const perm1 = "user-management:user:createUser";

    const roleResult = await gql
      .mutation(createRole, { name: `EmptyPermRole-${Date.now()}`, permissions: [perm1] })
      .toPromise();
    const roleId = roleResult.data!.createRole.id;

    const result = await gql.mutation(updateRole, { roleId, permissions: [] }).toPromise();

    expect(result.data!.updateRole.roleId).toBe(roleId);
  });

  it("Remove one permission while keeping others and submit; verify the permission is no longer listed on the role", async () => {
    const perm1 = "user-management:user:createUser";
    const perm2 = "user-management:user:updateUser";

    const roleResult = await gql
      .mutation(createRole, {
        name: `MultiPermRole-${Date.now()}`,
        permissions: [perm1, perm2],
      })
      .toPromise();
    const roleId = roleResult.data!.createRole.id;

    await gql.mutation(updateRole, { roleId, permissions: [perm2] }).toPromise();

    const roleDetail = await gql.query(getRole, { roleId }).toPromise();
    const permissions = roleDetail.data?.role?.permissions as string[] | undefined;
    expect(permissions).not.toContain(perm1);
    expect(permissions).toContain(perm2);
  });
});
