extend schema
  @link(
    url: "https://specs.apollo.dev/federation/v2.3"
    import: ["@key", "@shareable", "@inaccessible", "@tag", "@external"]
  )
  @link(url: "https://specs.graphql-hive.com/hive/v1.0", import: ["@meta"])
  @meta(name: "owner", content: "products-team")
  @meta(name: "contact", content: "#products-channel")

directive @example(text: String!) on FIELD_DEFINITION

directive @meta(
  name: String!
  content: String!
) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION

"""
Product interface defining common product fields
"""
interface ProductItf implements SkuItf @meta(name: "domain", content: "products") {
  upc: String!
  sku: String
  name: String
  package: String
  variations: [ProductItf]
  dimensions: ProductDimension
  createdBy: User
  hidden: String @inaccessible
  oldField: String @deprecated(reason: "refactored out")
}

"""
SKU interface for items with stock keeping units
"""
interface SkuItf {
  sku: String
}

"""
# Product Entity

The **Product** type represents physical or _digital items_ available in the catalog. Products are uniquely identified and federated across multiple subgraphs.

## Key Capabilities

### Unique Identification
- Universal Product Code (`upc`) - primary key
- SKU + package combination - composite key
- Learn more about [federation keys](https://the-guild.dev/graphql/hive/federation)

### Product Data
1. Descriptive metadata (name, package)
2. Physical specifications (dimensions, weight)
3. Business metrics (reviews, creator info)

> **Access Control**: The `hidden` field is marked `@inaccessible` and won't appear in the public schema.

---

**Query Pattern**: Fetch via `product(upc: String!)`
**Variations**: Products can have multiple `variations` for sizes/colors
**Reviews**: Aggregated score available in `reviewsScore` field

![Product Schema Diagram](https://the-guild.dev/graphql/hive/_next/static/media/federation-diagram.dcf3cf6b.png)

*Related types: `ProductItf`, `ProductDimension`, `ShippingClass`*
"""
type Product implements ProductItf & SkuItf @key(fields: "upc") @key(fields: "sku package") {
  """
  Universal Product Code. A standardized numeric global identifier
  """
  upc: String! @shareable
  """
  SKUs are unique to the company and are used internally. Alphanumeric.
  """
  sku: String @tag(name: "internal") @meta(name: "sensitivity", content: "internal")
  """
  Product name
  """
  name: String @example(text: "Foo Bar")
  """
  Package type or size information
  """
  package: String
  """
  Product variations (e.g., different sizes, colors)
  """
  variations: [ProductItf]
  """
  Physical dimensions of the product
  """
  dimensions: ProductDimension
  """
  User who created this product
  """
  createdBy: User
  """
  Hidden internal field
  """
  hidden: String
  """
  Aggregated review score for this product
  """
  reviewsScore: Float! @meta(name: "category", content: "analytics")
  """
  Deprecated field that has been refactored out
  """
  oldField: String
}

"""
Available shipping classes with delivery speeds
"""
enum ShippingClass {
  """
  Standard ground shipping (5-7 business days)
  """
  STANDARD
  """
  Express shipping (2-3 business days)
  """
  EXPRESS
  """
  Overnight shipping (next business day)
  """
  OVERNIGHT
}

"""
Price range filter for product searches
"""
input PriceRangeInput {
  """
  Minimum price (inclusive)
  """
  min: Float
  """
  Maximum price (inclusive)
  """
  max: Float
}

"""
Filter criteria for searching products
"""
input ProductFilterInput {
  """
  Search text to match against product name and description
  """
  searchText: String
  """
  Filter by product categories
  """
  categories: [String!]
  """
  Filter by price range
  """
  priceRange: PriceRangeInput
  """
  Filter by shipping class
  """
  shippingClass: ShippingClass
}

"""
Physical dimensions of a product (shared across subgraphs)
"""
type ProductDimension @shareable {
  """
  Size description (e.g., 'Small', 'Large', '10x5x3')
  """
  size: String
  """
  Weight in pounds
  """
  weight: Float
}

extend type User @key(fields: "id") {
  """
  Unique identifier for the user
  """
  id: ID!
  """
  Total number of products created by this user
  """
  totalProductsCreated: Int @shareable
}

type Query {
  """
  Get all products in the catalog
  """
  allProducts: [ProductItf!]! @meta(name: "priority", content: "tier1")
  """
  Get a specific product by its UPC
  """
  product(
    """
    Universal Product Code of the product to retrieve
    """
    upc: String!
  ): ProductItf
  """
  Get the top N products (default: 5)
  """
  topProducts(
    """
    Number of products to return (default: 5)
    """
    first: Int = 5
  ): [ProductItf!]!
  """
  Search and filter products based on criteria
  """
  searchProducts(
    """
    ## Product Search Filter

    Comprehensive filter criteria for searching and filtering products in the catalog. The **ProductFilterInput** supports multiple filtering dimensions that can be _combined_ for precise results.

    ### Available Filter Options

    - **Search Text** (`searchText`) - Full-text search across product names and descriptions
    - **Categories** (`categories`) - Filter by one or more product categories
    - **Price Range** (`priceRange`) - Min/max price boundaries (inclusive)
    - **Shipping Class** (`shippingClass`) - Filter by delivery speed (STANDARD, EXPRESS, OVERNIGHT)

    ### Common Usage Patterns

    1. Text search only: `{ searchText: "laptop" }`
    2. Category + price: `{ categories: ["Electronics"], priceRange: { min: 100, max: 500 } }`
    3. Multiple filters: `{ searchText: "tablet", categories: ["Electronics", "Computers"], shippingClass: EXPRESS }`

    > **Tip**: All filter fields are optional - combine them as needed for your search requirements

    ---

    *See `ProductFilterInput` type for complete field definitions and constraints*
    """
    filter: ProductFilterInput!
  ): [ProductItf!]!
  """
  Get products filtered by category and price range
  """
  products(
    """
    Optional category name to filter products
    """
    category: String
    """
    Minimum price threshold (inclusive)
    """
    minPrice: Float
    """
    Maximum price threshold (inclusive)
    """
    maxPrice: Float
  ): [ProductItf!]!
  """
  Get products filtered by physical dimensions and shipping class
  """
  productsByDimensions(
    """
    Minimum weight in pounds (inclusive)
    """
    minWeight: Float
    """
    Maximum weight in pounds (inclusive)
    """
    maxWeight: Float
    """
    Size description to match (e.g., 'Small', 'Large', '10x5x3')
    """
    size: String
    """
    Shipping class filter (STANDARD, EXPRESS, or OVERNIGHT)
    """
    shippingClass: ShippingClass
  ): [ProductItf!]!
}
