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

const listProducts = graphql(`
  query ListProducts {
    products {
      edges {
        node {
          id
          name
          code
          status
        }
      }
    }
  }
`);

const listDraftProducts = graphql(`
  query ListDraftProducts {
    products(query: { status: { eq: DRAFT } }) {
      edges {
        node {
          id
          name
          code
          status
        }
      }
    }
  }
`);

const listProductsPaginated = graphql(`
  query ListProductsPaginated($first: Int, $after: String) {
    products(first: $first, after: $after) {
      edges {
        node {
          id
          name
          code
          status
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
    }
  }
`);

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

  it("Given products exist, when the list screen is opened, then products are displayed in a paginated view.", async () => {
    const result = await gql.query(listProducts, {}).toPromise();

    expect(result.data?.products.edges.length).toBeGreaterThan(0);
    const product = result.data?.products.edges[0].node;
    expect(product?.id).toBeDefined();
    expect(product?.name).toBeDefined();
    expect(product?.code).toBeDefined();
    expect(product?.status).toBeDefined();
  });

  it("Given a status filter is applied, when the list is rendered, then only products with that status are shown.", async () => {
    const result = await gql.query(listDraftProducts, {}).toPromise();

    for (const edge of result.data?.products.edges ?? []) {
      expect(edge.node.status).toBe("DRAFT");
    }
  });

  it("Given multiple pages of results, when the next page is requested, then the next set of products is displayed.", async () => {
    const firstPage = await gql.query(listProductsPaginated, { first: 1 }).toPromise();

    expect(firstPage.data?.products.edges.length).toBeGreaterThan(0);

    const endCursor = firstPage.data?.products.pageInfo.endCursor;
    if (firstPage.data?.products.pageInfo.hasNextPage && endCursor) {
      const secondPage = await gql
        .query(listProductsPaginated, { first: 1, after: endCursor })
        .toPromise();

      expect(secondPage.data?.products.edges.length).toBeGreaterThan(0);
      expect(secondPage.data?.products.edges[0].node.id).not.toBe(
        firstPage.data?.products.edges[0].node.id,
      );
    }
  });
});
