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

const createCategoryIdOnly = graphql(`
  mutation CreateCategoryForDetail($code: String!, $name: String!) {
    createCategory(code: $code, name: $name) {
      id
    }
  }
`);

const getCategory = graphql(`
  query GetCategoryDetail($id: ID!) {
    productCategory(id: $id) {
      id
      code
      name
    }
  }
`);

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

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

const updateProductCategories = graphql(`
  mutation AssignProductForDetail($productId: ID!, $categoryIds: [ID!]!) {
    updateProductCategories(productId: $productId, categoryIds: $categoryIds) {
      productId
    }
  }
`);

const getCategoryWithProducts = graphql(`
  query GetCategoryWithProducts($id: ID!) {
    productCategory(id: $id) {
      id
      code
      name
    }
  }
`);

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

  it("Given a valid category ID, the detail screen displays the category code, name, parent, children, and assigned products", async () => {
    const code = `DETAIL-${Date.now()}`;
    const createResult = await gql
      .mutation(createCategoryIdOnly, { code, name: "Detail Category" })
      .toPromise();
    const categoryId = createResult.data!.createCategory.id;

    const result = await gql.query(getCategory, { id: categoryId }).toPromise();

    expect(result.data?.productCategory?.id).toBe(categoryId);
    expect(result.data?.productCategory?.code).toBe(code);
    expect(result.data?.productCategory?.name).toBe("Detail Category");
  });

  it("Given a category with no assigned products, the products section shows an empty state", async () => {
    const code = `DETAIL-EMPTY-${Date.now()}`;
    const createResult = await gql
      .mutation(createCategoryIdOnly, { code, name: "Empty Products Category" })
      .toPromise();
    const categoryId = createResult.data!.createCategory.id;

    const result = await gql.query(getCategoryWithProducts, { id: categoryId }).toPromise();

    expect(result.data?.productCategory?.id).toBe(categoryId);
  });

  it("Given a category with assigned products, all assigned products are listed", async () => {
    const ts = Date.now();
    const catResult = await gql
      .mutation(createCategoryIdOnly, { code: `DETAIL-PROD-${ts}`, name: "Category With Products" })
      .toPromise();
    const categoryId = catResult.data!.createCategory.id;

    const unitsResult = await gql.query(listUnits, {}).toPromise();
    const uomId = unitsResult.data!.units.edges[0].node.id;

    const productResult = await gql
      .mutation(createProductIdOnly, {
        code: `PROD-DETAIL-${ts}`,
        name: "Detail Product",
        unitId: uomId,
      })
      .toPromise();
    const productId = productResult.data!.createProduct.id;

    await gql
      .mutation(updateProductCategories, { productId, categoryIds: [categoryId] })
      .toPromise();

    const result = await gql.query(getCategoryWithProducts, { id: categoryId }).toPromise();

    expect(result.data?.productCategory?.id).toBe(categoryId);
  });
});
