"The fields by which you are allowed to sort any query that returns an `AccountConnection`"
enum AccountSortByField {
  "Account ID"
  _id

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

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

"A list of the possible types of `Address`"
enum AddressType {
  "Address can be used for payment transactions and invoicing"
  billing

  "Address can be used as a mailing address for sending physical items"
  shipping
}

"Defines a new Address and the account to which it should be added"
input AddAccountAddressBookEntryInput {
  "The account ID"
  accountId: ID!

  "The address to add"
  address: AddressInput!

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

"Defines the account which should be created"
input CreateAccountInput {
  "Bio to display on profile"
  bio: String

  "Email record to create account with"
  emails: [EmailRecordInput]!

  "Name to display on profile"
  name: String

  "URL of picture to display on profile"
  picture: String

  "The ID of the shop this account will belong to"
  shopId: ID!

  "The userID account was created from create a new account from"
  userId: ID!

  "Username"
  username: String

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

"Describes changes that should be applied to one of the addresses for an account"
input UpdateAccountAddressBookEntryInput {
  "The account ID"
  accountId: ID!

  "The address ID"
  addressId: ID!

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

  "If present, make this address the default address of this type"
  type: AddressType

  "The address changes to apply"
  updates: AddressInput!
}

"Describes which address should be removed from which account"
input RemoveAccountAddressBookEntryInput {
  "The account ID"
  accountId: ID!

  "The address ID"
  addressId: ID!

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

"Describes which email should be sent a password reset link"
input SendResetAccountPasswordEmailInput {
  "An optional string identifying the mutation call, which will be returned in the response payload"
  clientMutationId: String

  "The email address of the account to send reset email to"
  email: String!
}

"Describes an account update"
input UpdateAccountInput {
  "The account ID, which defaults to the viewer account"
  accountId: ID

  "Bio to display on profile"
  bio: String

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

  "The preferred currency code used by this account"
  currencyCode: String

  "The first name of the person this account represents"
  firstName: String

  "The preferred language (code) used by this account"
  language: String

  "The last name of the person this account represents"
  lastName: String

  "The full name of the person this account represents"
  name: String

  "Some note about this account"
  note: String

  "URL of picture to display on profile"
  picture: String

  "Username"
  username: String
}

"Defines a new Email and the account to which it should be added"
input AddAccountEmailRecordInput {
  "The account ID, which defaults to the viewer account"
  accountId: ID

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

  "The email address to add"
  email: Email!
}

"Defines which email address should be removed from which account"
input RemoveAccountEmailRecordInput {
  "The account ID, which defaults to the viewer account"
  accountId: ID

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

  "The email address to remove"
  email: Email!
}

"Defines which email address should be set as the default for which account"
input SetAccountDefaultEmailInput {
  "The account ID, which defaults to the viewer account"
  accountId: ID

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

  "The email address to set as default"
  email: Email!
}

input UpdateGroupsForAccountsInput {
  "The account IDs"
  accountIds: [ID]!

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

  "The group IDs"
  groupIds: [ID]!
}

"Represents a single user account"
type Account implements Node {
  "The account ID"
  _id: ID!

  "A list of physical or mailing addresses associated with this account"
  addressBook(
    "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
  ): AddressConnection

  "A list of shops this user can administer with the admin UI"
  adminUIShops: [Shop]

  "Bio to display on profile"
  bio: String

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

  "The preferred currency used by this account"
  currency: Currency

  "A list of email records associated with this account"
  emailRecords: [EmailRecord]

  "The first name of the person this account represents, if known"
  firstName: String

  "The preferred language used by this account"
  language: String

  "The last name of the person this account represents, if known"
  lastName: String

  "Arbitrary additional metadata about this account"
  metafields: [Metafield]

  "The full name of the person this account represents, if known"
  name: String

  "Some note about this account"
  note: String

  "URL of picture to display on profile"
  picture: String

  "An object storing plugin-specific preferences for this account"
  preferences: JSONObject

  """
  The primary email address for the account. This matches the address in `emailRecords` where `provides` is `default`.
  """
  primaryEmailAddress: Email!

  "The date and time at which this account was last updated"
  updatedAt: DateTime

  "The Identity user ID with which this account is associated"
  userId: String!

  "Username"
  username: String
}

"Represents a single user partial account"
type BasicAccount implements Node {
  "The account ID"
  _id: ID!

  "Flag to indicate if the account accepts marketing emails"
  acceptsMarketing: Boolean

  "Email record associated with the account"
  emails: [EmailRecord]

  "List of group Ids to which the account belongs"
  groups: [String]

  "The full name of the person this account represents, if known"
  name: String

  "List of shipping/billing addresses"
  profile: [Profile]

  "ID of shop"
  shopId: String

  "Account creation state"
  state: String

  "ID of user"
  userId: String

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

  "The date and time at which this account was last updated"
  updatedAt: DateTime

  "List of shop Ids"
  adminUIShopIds: [String]

}

type Profile {
  addressBook: [Address]
}

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

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

  "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 an `Account` object"
type AccountEdge implements NodeEdge {
  "The cursor that represents this node in the paginated results"
  cursor: ConnectionCursor!

  "The account"
  node: Account
}

"The response from the `addAccountAddressBookEntry` mutation"
type AddAccountAddressBookEntryPayload {
  "The added address"
  address: Address

  "The added address edge"
  addressEdge: AddressEdge

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

"The response from the `addAccountEmailRecord` mutation"
type AddAccountEmailRecordPayload {
  "The account, with updated `emailRecords`"
  account: Account

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

"The response from the `createAccount` mutation"
type CreateAccountPayload {
  "The added account"
  account: BasicAccount

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

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

  "The email address of the account to send reset email to"
  email: String!
}

"The response from the `removeAccountAddressBookEntry` mutation"
type RemoveAccountAddressBookEntryPayload {
  "The removed address"
  address: Address

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

"The response from the `removeAccountEmailRecord` mutation"
type RemoveAccountEmailRecordPayload {
  "The account, with updated `emailRecords`"
  account: Account

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

"The response from the `setAccountDefaultEmail` mutation"
type SetAccountDefaultEmailPayload {
  "The account, with updated `emailRecords`"
  account: Account

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

"The response from the `updateAccountAddressBookEntry` mutation"
type UpdateAccountAddressBookEntryPayload {
  "The updated address"
  address: Address

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

"The response from the `updateAccount` mutation"
type UpdateAccountPayload {
  "The updated account"
  account: Account!

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

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

  "The accounts that were modified"
  accounts: [Account]!
}

extend type Mutation {
  "Add a new address to the `addressBook` field for an account"
  addAccountAddressBookEntry(
    "Mutation input"
    input: AddAccountAddressBookEntryInput!
  ): AddAccountAddressBookEntryPayload

  "Add an email address to an account"
  addAccountEmailRecord(
    "Mutation input"
    input: AddAccountEmailRecordInput!
  ): AddAccountEmailRecordPayload

  "Create an account based off a user"
  createAccount(
    "Mutation input"
    input: CreateAccountInput!
  ): CreateAccountPayload

  "Remove an address from the `addressBook` field for an account"
  removeAccountAddressBookEntry(
    "Mutation input"
    input: RemoveAccountAddressBookEntryInput!
  ): RemoveAccountAddressBookEntryPayload

  "Remove an email address from an account"
  removeAccountEmailRecord(
    "Mutation input"
    input: RemoveAccountEmailRecordInput!
  ): RemoveAccountEmailRecordPayload

  "Send a reset password email to an email address from an account"
  sendResetAccountPasswordEmail(
    "Mutation input"
    input: SendResetAccountPasswordEmailInput!
  ): SendResetAccountPasswordEmailPayload

  "Set default email address for an account"
  setAccountDefaultEmail(
    "Mutation input"
    input: SetAccountDefaultEmailInput!
  ): SetAccountDefaultEmailPayload

  "Remove an address that exists in the `addressBook` field for an account"
  updateAccountAddressBookEntry(
    "Mutation input"
    input: UpdateAccountAddressBookEntryInput!
  ): UpdateAccountAddressBookEntryPayload

  "Update account fields"
  updateAccount(
    "Mutation input"
    input: UpdateAccountInput!
  ): UpdateAccountPayload

  "Bulk-update groups for accounts"
  updateGroupsForAccounts(
    "Mutation input"
    input: UpdateGroupsForAccountsInput!
  ): UpdateGroupsForAccountsPayload
}

extend type Query {
  "Returns the account with the provided ID"
  account(
    "The account ID"
    id: ID!
  ): Account

  "Query to get a filtered list of Accounts"
  filterAccounts(
    "Shop ID"
    shopId: ID!,

    "Input Conditions for fliter (use either 'any' or 'all' not both)"
    conditions: FilterConditionsInput,

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

    "By default, accounts are sorted by createdAt. Set this to sort by one of the other allowed fields"
    sortBy: AccountSortByField = createdAt
  ): AccountConnection

  "Query to get a filtered list of Customers"
  filterCustomers(
    "Shop ID"
    shopId: ID!,

    "Input Conditions for fliter (use either 'any' or 'all' not both)"
    conditions: FilterConditionsInput,

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

    "By default, customers are sorted by createdAt. Set this to sort by one of the other allowed fields"
    sortBy: AccountSortByField = createdAt
  ): AccountConnection

  "Returns accounts optionally filtered by account groups"
  accounts(
    "Return only accounts in any of these groups"
    groupIds: [ID],

    "Return accounts that aren't in any groups"
    notInAnyGroups: Boolean,

    "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: AccountSortByField = createdAt
  ): AccountConnection!

  "Returns customer accounts"
  customers(
    "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: AccountSortByField = createdAt
  ): AccountConnection!

  "Returns the account for the authenticated user"
  viewer: Account
}
