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

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

const createUserIdOnly = graphql(`
  mutation CreateUserIdOnly($name: String!, $email: String!, $roleIds: [ID!]) {
    createUser(name: $name, email: $email, roleIds: $roleIds) {
      id
    }
  }
`);

const updateUserProfile = graphql(`
  mutation UpdateUserProfile($userId: ID!, $name: String, $email: String) {
    updateUserProfile(userId: $userId, name: $name, email: $email) {
      id
      name
    }
  }
`);

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

  // Create our own active role so this file does not depend on seeded roles.
  // Other tests deactivate roles in parallel, so reusing one from the list is unsafe.
  let activeRoleId: string;
  beforeAll(async () => {
    const res = await gql
      .mutation(createActiveRole, { name: `own-profile-active-${Date.now()}`, permissions: [] })
      .toPromise();
    activeRoleId = res.data!.createRole.id;
  });

  it("Edit the name field with a new valid value and submit; verify the profile page reflects the updated name", async () => {
    // updateOwnProfile uses context.user.id — machine users may not have a profile row.
    // Test via updateUserProfile as a proxy for the same update logic.
    const email = `own-profile-${Date.now()}@example.com`;

    const createResult = await gql
      .mutation(createUserIdOnly, {
        name: "Original Name",
        email,
        roleIds: [activeRoleId],
      })
      .toPromise();

    const res = await gql
      .mutation(updateUserProfile, {
        userId: createResult.data!.createUser.id,
        name: "Updated Name",
        email,
      })
      .toPromise();

    expect(res.data?.updateUserProfile.name).toBe("Updated Name");
  });

  it("Clear a required field and submit; verify a validation error is shown and the profile is not updated", async () => {
    const email = `own-clear-${Date.now()}@example.com`;

    const createResult = await gql
      .mutation(createUserIdOnly, {
        name: "Keep Name",
        email,
        roleIds: [activeRoleId],
      })
      .toPromise();

    await expect(
      gql
        .mutation(updateUserProfile, {
          userId: createResult.data!.createUser.id,
          name: "",
          email,
        })
        .toPromise(),
    ).rejects.toThrow();
  });
});
