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

interface AttributeValue {
  id: string;
  label: string;
}

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

const createAttribute = graphql(`
  mutation CreateAttributeForDelete($code: String!, $name: String!, $valueLabels: [String!]) {
    createAttribute(code: $code, name: $name, valueLabels: $valueLabels) {
      id
    }
  }
`);

const deleteAttribute = graphql(`
  mutation DeleteAttribute($id: ID!) {
    deleteAttribute(id: $id) {
      id
    }
  }
`);

const createProduct = graphql(`
  mutation CreateProductForDeleteAttr(
    $code: String!
    $name: String!
    $unitId: ID!
    $attributes: [CreateProductInputAttributes!]
  ) {
    createProduct(code: $code, name: $name, unitId: $unitId, attributes: $attributes) {
      id
    }
  }
`);

const getAttributeValues = graphql(`
  query GetAttributeValuesForDelete($id: ID!) {
    productAttribute(id: $id) {
      id
      productAttributeValues {
        edges {
          node {
            id
            label
          }
        }
      }
    }
  }
`);

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

  it("Given an attribute with no product assignments, when delete is confirmed, then the attribute is removed.", async () => {
    const code = `DEL-${Date.now()}`;
    const createRes = await gql
      .mutation(createAttribute, {
        code,
        name: "To Delete",
        valueLabels: ["Val1"],
      })
      .toPromise();
    const attributeId = createRes.data!.createAttribute.id;

    const res = await gql.mutation(deleteAttribute, { id: attributeId }).toPromise();

    expect(res.data?.deleteAttribute.id).toBe(attributeId);
  });

  it("Given an attribute assigned to at least one product, when delete is attempted, then an error indicating existing assignments is shown.", async () => {
    const ts = Date.now();
    const unitsResult = await gql.query(listUnits, {}).toPromise();
    const unitId = unitsResult.data!.units.edges[0].node.id;

    const createRes = await gql
      .mutation(createAttribute, {
        code: `ASSIGNED-${ts}`,
        name: "Assigned Attribute",
        valueLabels: ["Val1"],
      })
      .toPromise();
    const attributeId = createRes.data!.createAttribute.id;

    const attrValues = await gql.query(getAttributeValues, { id: attributeId }).toPromise();
    const values = attrValues.data!.productAttribute!.productAttributeValues.edges.map(
      (e) => e.node,
    ) as AttributeValue[];
    const valueId = values[0].id;

    await gql
      .mutation(createProduct, {
        code: `PROD-${ts}`,
        name: "Product With Attr",
        unitId,
        attributes: [{ attributeId, valueId }] as never,
      })
      .toPromise();

    await expect(gql.mutation(deleteAttribute, { id: attributeId }).toPromise()).rejects.toThrow();
  });
});
