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

const listUnits = graphql(`
  query ListUnits {
    units {
      edges {
        node {
          id
        }
      }
    }
  }
`);

const createProductFull = graphql(`
  mutation CreateProductFull(
    $code: String!
    $name: String!
    $description: String
    $unitId: ID!
    $categoryIds: [ID!]
  ) {
    createProduct(
      code: $code
      name: $name
      description: $description
      unitId: $unitId
      categoryIds: $categoryIds
    ) {
      id
      code
      name
      status
    }
  }
`);

const createProductIdOnly = graphql(`
  mutation CreateProductIdOnly($code: String!, $name: String!, $unitId: ID!) {
    createProduct(code: $code, name: $name, unitId: $unitId) {
      id
    }
  }
`);

describe("product-manager--create-product", () => {
  const gql = createGraphQLClient(inject("url"), inject("token"));

  // Shared read-only lookup: fetch once, not per case.
  let uomId: string;
  beforeAll(async () => {
    const unitsResult = await gql.query(listUnits, {}).toPromise();
    uomId = unitsResult.data!.units.edges[0].node.id;
  });

  it("Given valid inputs, when the form is submitted, then a product is created with status DRAFT.", async () => {
    const code = `PROD-${Date.now()}`;
    const res = await gql
      .mutation(createProductFull, {
        code,
        name: "Test Product",
        description: "A test product",
        unitId: uomId,
      })
      .toPromise();

    expect(res.data?.createProduct.code).toBe(code);
    expect(res.data?.createProduct.name).toBe("Test Product");
    expect(res.data?.createProduct.status).toBe("DRAFT");
  });

  it("Given a duplicate code, when the form is submitted, then an error indicating the code already exists is shown.", async () => {
    const code = `DUP-${Date.now()}`;
    await gql
      .mutation(createProductIdOnly, { code, name: "First Product", unitId: uomId })
      .toPromise();

    await expect(
      gql
        .mutation(createProductIdOnly, { code, name: "Duplicate Product", unitId: uomId })
        .toPromise(),
    ).rejects.toThrow();
  });

  it("Given a missing required field, when the form is submitted, then a validation error is shown.", async () => {
    await expect(
      gql.mutation(createProductIdOnly, { code: "", name: "", unitId: uomId }).toPromise(),
    ).rejects.toThrow();
  });
});
