"A discount code"
type DiscountCode {
  "Discount code ID"
  _id: ID!

  "How the discount should be applied"
  calculation: DiscountCalculation

  "Discount Code"
  code: String!

  "Discount code conditions"
  conditions: DiscountConditions

  "Description to describe the discount code"
  description: String

  """
  Discount is allowed to be string or number.
  it's a formula value (could be shipping code)
  """
  discount: String

  "Discount method type"
  discountMethod: DiscountMethod

  "Label to describe the code"
  label: String

  "The shop to which this DiscountCode belongs to"
  shop: Shop!

  "History of transactions"
  transactions: [DiscountTransaction]
}

"Transaction history for a discount code"
type DiscountTransaction {
  "Date the code was applied"
  appliedAt: DateTime

  "Cart id"
  cartId: String!

  "User id"
  userId: String!
}

"The conditions an order must meet for a discount code to be applied"
type DiscountConditionOrder {
  "Order date range end"
  endDate: DateTime

  "Maximum order value"
  max: Float

  "Minimum order value"
  min: Float!

  "Order date range start"
  startDate: DateTime
}

"Conditions for a discount code to be applied"
type DiscountConditions {
  "Account Limit"
  accountLimit: Int

  "Audience that may apply this discount code"
  audience: [String]

  "Is this discount code enabled"
  enabled: Boolean!

  "Order conditions"
  order: DiscountConditionOrder

  "Permissions that may apply this discount code"
  permissions: [String]

  "Products that may apply this discount code"
  products: [String]

  """
  Number of times this code may be redeemed.
  Setting to 100 means the first 100 customers may apply this code.
  Setting this value to 0 will allow this code to be applied an infinite number of times.
  """
  redemptionLimit: Int

  "Tags that may be apply this discount code"
  tags: [String]
}

"Discount code calculation"
type DiscountCalculation {
  "Discount code calculation method"
  method: DiscountCalculationMethod
}

"Discount method types"
enum DiscountMethod {
  "Code type"
  code

  "Rate type"
  rate
}

"Discount calculation types"
enum DiscountCalculationMethod {
  "Store credit"
  credit

  "Discount of order"
  discount

  "Sale on an item"
  sale

  "Discount to shipping"
  shipping
}

"Input for an `ApplyDiscountCodeToCartInput`"
input ApplyDiscountCodeToCartInput {
  "Cart to add discount to"
  cartId: ID!

  "Discount code to add to cart"
  discountCode: String!

  "Shop cart belongs to"
  shopId: ID!

  "Cart token, if anonymous"
  token: String
}

"Input for an `RemoveDiscountCodeFromCartInput`"
input RemoveDiscountCodeFromCartInput {
  "Cart to add discount to"
  cartId: ID!

  "ID of the discount you want to remove from the cart"
  discountId: ID!

  "Shop cart belongs to"
  shopId: ID!

  "Cart token, if anonymous"
  token: String
}

"Input type for filters to be applied to an discount codes list"
input DiscountCodeFilterInput {
  "Keywords typed by the user in the search input field"
  searchField: String
}

"Response from the `applyDiscountCodeToCart` mutation"
type ApplyDiscountCodeToCartPayload {
  "The updated cart with discount code applied"
  cart: Cart!

  "The same string you sent with the mutation params, for matching mutation calls with their responses"
  clientMutationId: String
}

"Response from the `removeDiscountCodeFromCart` mutation"
type RemoveDiscountCodeFromCartPayload {
  "The updated cart with discount code removed"
  cart: Cart!

  "The same string you sent with the mutation params, for matching mutation calls with their responses"
  clientMutationId: String
}

"A connection edge in which each node is a `DiscountCode` object"
type DiscountCodeEdge {
  "The cursor that represents this node in the paginated results"
  cursor: ConnectionCursor!

  "The discount code"
  node: DiscountCode
}

"""
Wraps a list of DiscountCode`s, providing pagination cursors and information.

For information about what Relay-compatible connections are and how to use them, see the following articles:
- [Relay Connection Documentation](https://facebook.github.io/relay/docs/en/graphql-server-specification.html#connections)
- [Relay Connection Specification](https://facebook.github.io/relay/graphql/connections.htm)
- [Using Relay-style Connections With Apollo Client](https://www.apollographql.com/docs/react/recipes/pagination.html)
"""
type DiscountCodeConnection {
  "The list of nodes that match the query, wrapped in an edge to provide a cursor string for each"
  edges: [DiscountCodeEdge]

  """
  You can request the `nodes` directly to avoid the extra wrapping that `NodeEdge` has,
  if you know you will not need to paginate the results.
  """
  nodes: [DiscountCode]

  "Information to help a client request the next or previous page"
  pageInfo: PageInfo!

  "The total number of nodes that match your query"
  totalCount: Int!
}

"Input type for discount calculation"
input DiscountCalculationInput {
  "Discount code calculation method"
  method: DiscountCalculationMethod
}

"Input type for a discount code"
input DiscountCodeInput {
  "How the discount should be applied"
  calculation: DiscountCalculationInput

  "Discount Code"
  code: String!

  "Discount code conditions"
  conditions: DiscountConditionsInput

  "Description to describe the discount code"
  description: String

  """
  Discount is allowed to be string or number.
  it's a formula value (could be shipping code)
  """
  discount: String

  "Discount method type"
  discountMethod: DiscountMethod

  "Label to describe the code"
  label: String

  "History of transactions"
  transactions: [DiscountTransactionInput]
}

"Discount transation input type"
input DiscountTransactionInput {
  "Date the code was applied"
  appliedAt: DateTime

  "Cart id"
  cartId: String!

  "User id"
  userId: String!
}

"Discount order conditions input type"
input DiscountConditionOrderInput {
  "Order date range end"
  endDate: DateTime

  "Maximum order value"
  max: Float

  "Minimum order value"
  min: Float!

  "Order date range start"
  startDate: DateTime,
}

"Discount conditions input type"
input DiscountConditionsInput {
  "Account Limit"
  accountLimit: Int

  "Audience that may apply this discount code"
  audience: [String]

  "Is this discount code enabled"
  enabled: Boolean!

  "Order conditions"
  order: DiscountConditionOrderInput

  "Permissions that may apply this discount code"
  permissions: [String]

  "Products that may apply this discount code"
  products: [String]

  """
  Number of times this code may be redeemed.
  Setting to 100 means the first 100 customers may apply this code.
  Setting this value to 0 will allow this code to be applied an infinite number of times.
  """
  redemptionLimit: Int

  "Tags that may be apply this discount code"
  tags: [String]
}

"Describes the input for creating a discount code"
input CreateDiscountCodeInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The discount code to update"
  discountCode: DiscountCodeInput

  "The shop ID of the discount code to update"
  shopId: ID!
}

"The response from the `createDiscountCode` mutation"
type CreateDiscountCodePayload {
  "The same string you sent with the mutation params, for matching mutation calls with their responses"
  clientMutationId: String

  "The created discount code"
  discountCode: DiscountCode
}

"Describes the input for updating a discount code"
input UpdateDiscountCodeInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The discount code to update"
  discountCode: DiscountCodeInput

  "The ID of the discount code to update"
  discountCodeId: ID!

  "The shop ID of the discount code to update"
  shopId: ID!
}

"The response from the `updateDiscountCode` mutation"
type UpdateDiscountCodePayload {
  "The same string you sent with the mutation params, for matching mutation calls with their responses"
  clientMutationId: String

  "The updated discount code"
  discountCode: DiscountCode
}

"Describes the input for removing a discount code"
input DeleteDiscountCodeInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The discount code ID"
  discountCodeId: ID!

  "Shop ID"
  shopId: ID!
}

"The response from the `deleteDiscountCode` mutation"
type DeleteDiscountCodePayload {
  "The same string you sent with the mutation params, for matching mutation calls with their responses"
  clientMutationId: String

  "The deleted discount code"
  discountCode: DiscountCode
}

extend type Query {
  "Gets discount codes"
  discountCodes(
    "Provide a shop ID from which you want to get discount codes"
    shopId: ID!

    "Filters to apply to a discount codes query"
    filters: DiscountCodeFilterInput 

    "Return only results that come after this cursor. Use this with `first` to specify the number of results to return."
    after: ConnectionCursor,

    "Return only results that come before this cursor. Use this with `last` to specify the number of results to return."
    before: ConnectionCursor,

    "Return at most this many results. This parameter may be used with either `after` or `offset` parameters."
    first: ConnectionLimitInt,

    "Return at most this many results. This parameter may be used with the `before` parameter."
    last: ConnectionLimitInt,

    "Return only results that come after the Nth result. This parameter may be used with the `first` parameter."
    offset: Int,
  ): DiscountCodeConnection
}

extend type Mutation {
  "Create a new discount code"
  createDiscountCode(
    "Mutation input"
    input: CreateDiscountCodeInput!
  ): CreateDiscountCodePayload

  "Update a discount code"
  updateDiscountCode(
    "Mutation input"
    input: UpdateDiscountCodeInput!
  ): UpdateDiscountCodePayload

  "Delete a discount code"
  deleteDiscountCode(
    "Mutation input"
    input: DeleteDiscountCodeInput!
  ): DeleteDiscountCodePayload

  "Apply a discount code to a cart"
  applyDiscountCodeToCart(
    "Mutation input"
    input: ApplyDiscountCodeToCartInput!
  ): ApplyDiscountCodeToCartPayload!

  "Remove a discount code from a cart"
  removeDiscountCodeFromCart(
    "Mutation input"
    input: RemoveDiscountCodeFromCartInput!
  ): RemoveDiscountCodeFromCartPayload!
}
