"The fields by which you are allowed to sort any query that returns an `GroupConnection`"
enum GroupSortByField {
  "Group ID"
  _id

  "Date and time at which this group was created"
  createdAt

  "Group name"
  name

  "Date and time at which this group was last updated"
  updatedAt
}

"A group definition"
input GroupInput {
  "A free text description of this group"
  description: String

  "A unique name for the group"
  name: String!

  "A unique URL-safe string representing this group"
  slug: String
}

"Fields to update for an existing account group"
input UpdateGroupInput {
  "A free text description of this group"
  description: String

  "A unique name for the group"
  name: String

  "A unique URL-safe string representing this group"
  slug: String
}

"The details for creating a group"
input CreateAccountGroupInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The group to create"
  group: GroupInput!

  "The ID of the shop this group belongs to"
  shopId: ID
}

"The details for updating a group"
input UpdateAccountGroupInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The changes to apply to the group"
  group: UpdateGroupInput!

  "The group ID"
  groupId: ID!

  "The ID of the shop this group belongs to"
  shopId: ID
}

"The details for removing a group"
input RemoveAccountGroupInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The group ID"
  groupId: ID!

  "The ID of the shop this group belongs to"
  shopId: ID
}

"Defines a group and account that should be linked"
input AddAccountToGroupInput {
  "The account ID"
  accountId: ID!

  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The group ID"
  groupId: ID!
}

"Defines a group and account that should be unlinked"
input RemoveAccountFromGroupInput {
  "The account ID"
  accountId: ID!

  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The group ID"
  groupId: ID!
}

"Represents an account group"
type Group implements Node {
  "The group ID"
  _id: ID!

  "The date and time at which this group was created"
  createdAt: DateTime!

  "The account that created this group"
  createdBy: Account

  "A free text description of this group"
  description: String

  "A unique name for the group"
  name: String!

  "The shop to which this group belongs"
  shop: Shop

  "A unique URL-safe string representing this group"
  slug: String!

  "The date and time at which this group was last updated"
  updatedAt: DateTime!
}

"""
Wraps a list of `Groups`, 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 GroupConnection {
  "The list of nodes that match the query, wrapped in an edge to provide a cursor string for each"
  edges: [GroupEdge]

  """
  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: [Group]

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

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

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

  "The group"
  node: Group
}

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

  "The updated group"
  group: Group
}

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

  "The new group"
  group: Group
}

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

  "The updated group"
  group: Group
}

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

  "The removed group"
  group: Group!
}


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

  "The removed group"
  group: Group
}

extend type Shop {
  "Returns a list of groups for this shop, as a Relay-compatible connection."
  groups(
    "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,

    "Return results sorted in this order"
    sortOrder: SortOrder = asc,

    "By default, groups are sorted by when they were created, oldest first. Set this to sort by one of the other allowed fields"
    sortBy: GroupSortByField = createdAt
  ): GroupConnection
}

extend type Account {
  "A paged list of the account groups in which this account is listed"
  groups(
    "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,

    "Return results sorted in this order"
    sortOrder: SortOrder = asc,

    "By default, groups are sorted by when they were created, oldest first. Set this to sort by one of the other allowed fields"
    sortBy: GroupSortByField = createdAt
  ): GroupConnection
}

extend type Mutation {
  "Add an account to a group"
  addAccountToGroup(
    "Mutation input"
    input: AddAccountToGroupInput!
  ): AddAccountToGroupPayload

  "Create a new account group. These are usually used for account permissions"
  createAccountGroup(
    "Mutation input"
    input: CreateAccountGroupInput!
  ): CreateAccountGroupPayload

  "Remove an account from a group"
  removeAccountFromGroup(
    "Mutation input"
    input: RemoveAccountFromGroupInput!
  ): RemoveAccountFromGroupPayload

  "Remove an existing account group"
  removeAccountGroup(
    "Mutation input"
    input: RemoveAccountGroupInput!
  ): RemoveAccountGroupPayload

  "Update an existing account group"
  updateAccountGroup(
    "Mutation input"
    input: UpdateAccountGroupInput!
  ): UpdateAccountGroupPayload
}

extend type Query {
  "Returns a single group by ID."
  group(
    "The group ID"
    id: ID!
  ): Group

  "Returns a list of groups for the shop with ID `shopId`, as a Relay-compatible connection."
  groups(
    "Return groups for this shop"
    shopId: ID!,

    "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,

    "Return results sorted in this order"
    sortOrder: SortOrder = asc,

    "By default, groups are sorted by when they were created, oldest first. Set this to sort by one of the other allowed fields"
    sortBy: GroupSortByField = createdAt
  ): GroupConnection
}
