import SimpleSchema from "simpl-schema";

const withoutCodeCountries = ["AO", "AG", "AW", "BS", "BZ", "BJ", "BW",
  "BF", "BI", "CM", "CF", "KM", "CG", "CD", "CK", "CI", "DJ",
  "DM", "GQ", "ER", "FJ", "TF", "GM", "GH", "GD", "GN", "GY",
  "HK", "IE", "JM", "KE", "KI", "MO", "MW", "ML", "MR", "MU",
  "MS", "NR", "AN", "NU", "KP", "PA", "QA", "RW", "KN", "LC",
  "ST", "SA", "SC", "SL", "SB", "SO", "SR", "SY", "TZ", "TL",
  "TK", "TO", "TT", "TV", "UG", "AE", "VU", "YE", "ZW"];

/**
 * @name Metafield
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} key optional
 * @property {String} namespace optional
 * @property {String} scope optional
 * @property {String} value optional
 * @property {String} valueType optional
 * @property {String} description optional
 */
const Metafield = new SimpleSchema({
  key: {
    type: String,
    max: 30,
    optional: true
  },
  namespace: {
    type: String,
    max: 20,
    optional: true
  },
  scope: {
    type: String,
    optional: true
  },
  value: {
    type: String,
    optional: true
  },
  valueType: {
    type: String,
    optional: true
  },
  description: {
    type: String,
    optional: true
  }
});

/**
 * @name OrderAddress
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} _id
 * @property {String} fullName required
 * @property {String} firstName
 * @property {String} lastName
 * @property {String} address1 required
 * @property {String} address2
 * @property {String} city required
 * @property {String} company
 * @property {String} phone required
 * @property {String} region required, State/Province/Region
 * @property {String} postal required
 * @property {String} country required
 * @property {Boolean} isCommercial required
 * @property {Boolean} isBillingDefault required
 * @property {Boolean} isShippingDefault required
 * @property {Boolean} failedValidation
 * @property {Metafield[]} metafields
 */
export const OrderAddress = new SimpleSchema({
  "_id": {
    type: String,
    optional: true
  },
  "fullName": {
    type: String,
    label: "Full name"
  },
  "firstName": {
    type: String,
    label: "First name",
    optional: true
  },
  "lastName": {
    type: String,
    label: "Last name",
    optional: true
  },
  "address1": {
    label: "Address 1",
    type: String
  },
  "address2": {
    label: "Address 2",
    type: String,
    optional: true
  },
  "city": {
    type: String,
    label: "City"
  },
  "company": {
    type: String,
    label: "Company",
    optional: true
  },
  "phone": {
    type: String,
    label: "Phone"
  },
  "region": {
    label: "State/Province/Region",
    type: String
  },
  "postal": {
    label: "ZIP/Postal Code",
    type: String,
    optional: true,
    custom() {
      const country = this.field("country");
      if (country && country.value) {
        if (!withoutCodeCountries.includes(country.value) && !this.value) {
          return "required";
        }
      }
      return true;
    }
  },
  "country": {
    type: String,
    label: "Country"
  },
  "isCommercial": {
    label: "This is a commercial address.",
    type: Boolean,
    defaultValue: false
  },
  "isBillingDefault": {
    label: "Make this your default billing address?",
    type: Boolean,
    defaultValue: false,
    optional: true
  },
  "isShippingDefault": {
    label: "Make this your default shipping address?",
    type: Boolean,
    defaultValue: false,
    optional: true
  },
  "failedValidation": {
    label: "Failed validation",
    type: Boolean,
    defaultValue: false,
    optional: true
  },
  "metafields": {
    type: Array,
    optional: true
  },
  "metafields.$": {
    type: Metafield
  }
});

/**
 * @name ShippingParcel
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} containers optional
 * @property {Number} length optional
 * @property {Number} width optional
 * @property {Number} height optional
 * @property {Number} weight optional
 */
const ShippingParcel = new SimpleSchema({
  containers: {
    type: String,
    optional: true
  },
  length: {
    type: Number,
    optional: true
  },
  width: {
    type: Number,
    optional: true
  },
  height: {
    type: Number,
    optional: true
  },
  weight: {
    type: Number,
    optional: true
  }
});

const Money = new SimpleSchema({
  currencyCode: String,
  amount: {
    type: Number,
    min: 0
  }
});

/**
 * @name CommonOrderItemAttribute
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} label required
 * @property {String} value optional
 */
export const CommonOrderItemAttribute = new SimpleSchema({
  label: String,
  value: {
    type: String,
    optional: true
  }
});

export const CommonOrderItem = new SimpleSchema({
  "_id": String,
  "attributes": {
    type: Array,
    optional: true
  },
  "attributes.$": CommonOrderItemAttribute,
  "isTaxable": {
    type: Boolean,
    optional: true
  },
  "parcel": {
    type: ShippingParcel,
    optional: true
  },
  "price": Money,
  "productId": String,
  "productVendor": {
    type: String,
    optional: true
  },
  "quantity": {
    type: SimpleSchema.Integer,
    min: 0
  },
  "shopId": String,
  "subtotal": Money,
  "taxCode": {
    type: String,
    optional: true
  },
  "title": String,
  "variantId": String,
  "variantTitle": {
    type: String,
    optional: true
  }
});

const CommonOrderFulfillmentPrices = new SimpleSchema({
  handling: {
    type: Money,
    optional: true
  },
  shipping: {
    type: Money,
    optional: true
  },
  total: {
    type: Money,
    optional: true
  }
});

const CommonOrderTotals = new SimpleSchema({
  groupDiscountTotal: {
    type: Money,
    optional: true
  },
  groupItemTotal: {
    type: Money,
    optional: true
  },
  groupTotal: {
    type: Money,
    optional: true
  },
  orderDiscountTotal: {
    type: Money,
    optional: true
  },
  orderItemTotal: {
    type: Money,
    optional: true
  },
  orderTotal: {
    type: Money,
    optional: true
  }
});

/**
 * @type {SimpleSchema}
 * @summary The CommonOrder schema describes an order for a single shop, containing only
 *   properties that can be provided by a Cart as well. Each fulfillment group in a Cart
 *   or Order can be transformed into a single CommonOrder. This allows plugins that
 *   operate on both cart and order to provide only a single function, accepting a CommonOrder,
 *   where the caller can transform and store the result as necessary for either Cart or Order.
 *   For example, tax services accept a CommonOrder and calculate taxes without knowing or
 *   caring whether it is for a Cart or an Order.
 */
export const CommonOrder = new SimpleSchema({
  accountId: {
    type: String,
    optional: true
  },
  billingAddress: {
    type: OrderAddress,
    optional: true
  },
  cartId: {
    type: String,
    optional: true
  },
  currencyCode: String,
  fulfillmentMethodId: {
    type: String,
    optional: true
  },
  fulfillmentPrices: CommonOrderFulfillmentPrices,
  fulfillmentType: {
    type: String
  },
  items: [CommonOrderItem],
  orderId: {
    type: String,
    optional: true
  },
  originAddress: {
    type: OrderAddress,
    optional: true
  },
  shippingAddress: {
    type: OrderAddress,
    optional: true
  },
  shopId: String,
  sourceType: {
    type: String,
    allowedValues: ["cart", "order"]
  },
  totals: {
    type: CommonOrderTotals,
    optional: true
  }
});

export const orderItemInputSchema = new SimpleSchema({
  "addedAt": {
    type: Date,
    optional: true
  },
  "price": Number,
  "productConfiguration": Object,
  "productConfiguration.productId": String,
  "productConfiguration.productVariantId": String,
  "quantity": {
    type: SimpleSchema.Integer,
    min: 1
  }
});

export const orderFulfillmentGroupInputSchema = new SimpleSchema({
  "data": {
    type: Object,
    blackbox: true,
    optional: true
  },
  "items": {
    type: Array,
    minCount: 1
  },
  "items.$": orderItemInputSchema,
  "selectedFulfillmentMethodId": String,
  "shopId": String,
  "totalPrice": {
    type: Number,
    optional: true
  },
  "type": {
    type: String
  }
});

// Exported for unit tests
export const orderInputSchema = new SimpleSchema({
  // Although billing address is typically needed only by the payment plugin,
  // some tax services require it to calculate taxes for digital items. Thus
  // it should be provided here in order to be added to the CommonOrder if possible.
  "billingAddress": {
    type: OrderAddress,
    optional: true
  },
  "cartId": {
    type: String,
    optional: true
  },
  "currencyCode": String,
  /**
   * If you need to store customFields, be sure to add them to your
   * GraphQL input schema and your Order SimpleSchema with proper typing.
   * This schema need not care what `customFields` is because the input
   * and Order schemas will validate. Thus, we use blackbox here.
   */
  "customFields": {
    type: Object,
    blackbox: true,
    optional: true
  },
  "email": String,
  "fulfillmentGroups": {
    type: Array,
    minCount: 1
  },
  "fulfillmentGroups.$": orderFulfillmentGroupInputSchema,
  "ordererPreferredLanguage": {
    type: String,
    optional: true
  },
  "shopId": String
});

export const paymentInputSchema = new SimpleSchema({
  amount: Number,
  // Optionally override the order.billingAddress for each payment
  billingAddress: {
    type: OrderAddress,
    optional: true
  },
  data: {
    type: Object,
    optional: true,
    blackbox: true
  },
  method: String
});

/**
 * @name AnonymousAccessToken
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {Date} createdAt when token was created
 * @property {String} hashedToken token hash = base64(sha256(token-random-string))
 */
const AnonymousAccessToken = new SimpleSchema({
  createdAt: Date,
  hashedToken: String
});

/**
 * @name Document
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} docId required
 * @property {String} docType optional
 */
const Document = new SimpleSchema({
  docId: {
    type: String
  },
  docType: {
    type: String,
    optional: true
  }
});

/**
 * @name ExportHistory
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} status (required) Whether the export attempt succeeded or failed
 * @property {Date} dateAttempted (required) Date the export was attempted
 * @property {String} exportMethod (required) Name of the export method (e.g. CSV, Shopify)
 * @property {String} destinationIdentifier The identifier for this order on the remote system
 * @property {String} shopId (required) The shop ID
 */
const ExportHistory = new SimpleSchema({
  status: {
    type: String,
    allowedValues: ["success", "failure"]
  },
  dateAttempted: {
    type: Date
  },
  exportMethod: {
    type: String
  },
  destinationIdentifier: {
    type: String,
    optional: true
  },
  shopId: {
    type: String
  }
});

/**
 * @name History
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} event required
 * @property {String} value required
 * @property {String} userId required
 * @property {String} updatedAt required
 */
const History = new SimpleSchema({
  event: {
    type: String
  },
  value: {
    type: String
  },
  userId: {
    type: String
  },
  updatedAt: {
    type: Date
  }
});

/**
 * @name OrderInvoice
 * @type {SimpleSchema}
 * @memberof Schemas
 * @property {Number} discounts Total of all discounts (a positive number, but subtracted from the grand total)
 * @property {Number} effectiveTaxRate The effective tax rate, for display
 * @property {Number} shipping Price of the selected fulfillment method
 * @property {Number} subtotal Item total
 * @property {Number} surcharges Total of all surcharges
 * @property {Number} taxableAmount Total amount that was deemed taxable by the tax service
 * @property {Number} taxes Total tax
 * @property {Number} total Grand total
 */
export const OrderInvoice = new SimpleSchema({
  currencyCode: String,
  discounts: {
    type: Number,
    min: 0
  },
  effectiveTaxRate: {
    type: Number,
    min: 0
  },
  shipping: {
    type: Number,
    min: 0
  },
  subtotal: {
    type: Number,
    min: 0
  },
  surcharges: {
    type: Number,
    min: 0
  },
  taxes: {
    type: Number,
    min: 0
  },
  taxableAmount: {
    type: Number,
    min: 0
  },
  total: {
    type: Number,
    min: 0
  }
});

/**
 * @name Notes
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} content required
 * @property {String} userId required
 * @property {Date} updatedAt required
 */
const Notes = new SimpleSchema({
  content: {
    type: String
  },
  userId: {
    type: String
  },
  updatedAt: {
    type: Date
  }
});

/**
 * @name Workflow
 * @summary Control view flow by attaching layout to a collection.
 * Shop defaultWorkflow is defined in Shop.
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} status, default value: `new`
 * @property {String[]} workflow optional
 */
const Workflow = new SimpleSchema({
  "status": {
    type: String,
    defaultValue: "new"
  },
  "workflow": {
    type: Array,
    optional: true
  },
  "workflow.$": String
});

/**
 * @name OrderDiscount
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {Number} amount Amount of discount applied to the order
 * @property {String} discountId Discount ID
 */
const OrderDiscount = new SimpleSchema({
  amount: Number,
  discountId: String
});

/**
 * @name OrderItemAttribute
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} label required
 * @property {String} value optional
 */
const OrderItemAttribute = new SimpleSchema({
  label: String,
  value: {
    type: String,
    optional: true
  }
});

/**
 * @name OrderItem
 * @memberof Schemas
 * @summary Defines one item in an order
 * @type {SimpleSchema}
 * @property {String} _id Unique ID for the item
 * @property {String} addedAt Date/time when this was first added to the cart/order
 * @property {OrderItemAttribute[]} attributes Attributes of this item
 * @property {String} cancelReason Free text reason for cancel, if this item is canceled
 * @property {String} createdAt Date/time when this order item was created
 * @property {Document[]} documents optional
 * @property {History[]} history optional
 * @property {String} optionTitle optionTitle from the selected variant
 * @property {ShippingParcel} parcel Currently, parcel is in simple product schema. Need to include it here as well.
 * @property {Money} price The price+currency of variantId at the moment the related order was placed
 * @property {String} productId required
 * @property {String} productSlug Product slug
 * @property {String} productType Product type
 * @property {String} productVendor Product vendor
 * @property {Number} quantity required
 * @property {String} shopId The owner shop
 * @property {Number} subtotal The item subtotal, quantity x price
 * @property {String} title Title from the selected product
 * @property {String} updatedAt required
 * @property {String} variantId required
 * @property {String} variantTitle Title from the selected variant
 * @property {Workflow} workflow optional
 *
 */
export const OrderItem = new SimpleSchema({
  "_id": String,
  "addedAt": Date,
  "attributes": {
    type: Array,
    optional: true
  },
  "attributes.$": OrderItemAttribute,
  "cancelReason": {
    type: String,
    optional: true
  },
  "createdAt": Date,
  "documents": {
    type: Array,
    optional: true
  },
  "documents.$": {
    type: Document
  },
  "history": {
    type: Array,
    optional: true
  },
  "history.$": {
    type: History
  },
  "optionTitle": {
    type: String,
    optional: true
  },
  "parcel": {
    type: ShippingParcel,
    optional: true
  },
  "price": Money,
  "productId": String,
  "productSlug": {
    type: String,
    optional: true
  },
  "productType": {
    label: "Product Type",
    type: String,
    optional: true
  },
  "productTagIds": {
    label: "Product Tags",
    type: Array,
    optional: true
  },
  "productTagIds.$": String,
  "productVendor": {
    label: "Product Vendor",
    type: String,
    optional: true
  },
  "quantity": {
    label: "Quantity",
    type: SimpleSchema.Integer,
    min: 0
  },
  "shopId": String,
  "subtotal": Number,
  "title": String,
  "updatedAt": Date,
  "variantId": {
    type: String,
    optional: true
  },
  "variantTitle": {
    type: String,
    optional: true
  },
  "workflow": {
    type: Workflow,
    optional: true,
    defaultValue: {}
  }
});

/**
 * @name SelectedFulfillmentOption
 * @memberof Schemas
 * @type {SimpleSchema}
 * @property {String} _id Shipment method Id
 * @property {String} carrier optional
 * @property {String} currencyCode Currency code for interpreting rate and handling
 * @property {String} group Group, allowed values: `Ground`, `Priority`, `One Day`, `Free`
 * @property {Number} handling optional, default value: `0`
 * @property {String} label Public label
 * @property {String} name Method name
 * @property {Number} rate Rate
 */
export const SelectedFulfillmentOption = new SimpleSchema({
  _id: String,
  carrier: {
    type: String,
    optional: true
  },
  currencyCode: String,
  group: {
    type: String,
    optional: true
  },
  handling: {
    type: Number,
    min: 0
  },
  label: String,
  name: String,
  rate: {
    type: Number,
    min: 0
  },
  discount: {
    type: Number,
    min: 0,
    optional: true
  }
});

/**
 * @name OrderFulfillmentGroup Schema
 * @memberof Schemas
 * @summary One fulfillment group of an order
 * @type {SimpleSchema}
 * @property {String} _id Group ID
 * @property {Object} address Shipping address
 * @property {String} customsLabelUrl URL for customs label
 * @property {Object} invoice Invoice (same as the one on Payment)
 * @property {Object[]} items The order items in this group
 * @property {String[]} itemIds For convenience, the _id of all the items
 * @property {Object} payment The payment info for this group
 * @property {Object} shipmentMethod The fulfillment method that was chosen by the customer
 * @property {String} shippingLabelUrl URL for shipping label
 * @property {String} shopId The shop that fulfills this group
 * @property {Number} totalItemQuantity The total item quantity, sum of all quantities
 * @property {String} tracking Tracking reference ID
 * @property {String} trackingUrl Tracking URL
 * @property {String} type Fulfillment type
 * @property {Object} workflow Current status and past statuses for this fulfillment
 */
export const OrderFulfillmentGroup = new SimpleSchema({
  "_id": String,
  "address": {
    type: OrderAddress,
    optional: true
  },
  "customsLabelUrl": {
    type: String,
    optional: true
  },
  "invoice": OrderInvoice,
  "items": {
    type: Array,
    minCount: 1
  },
  "items.$": OrderItem,
  "itemIds": [String],
  "shipmentMethod": SelectedFulfillmentOption,
  "shippingLabelUrl": {
    type: String,
    optional: true
  },
  "shopId": String,
  "totalItemQuantity": {
    type: SimpleSchema.Integer,
    min: 1
  },
  "tracking": {
    type: String,
    optional: true
  },
  "trackingUrl": {
    type: String,
    optional: true
  },
  "type": {
    type: String
  },
  "updatedAt": {
    type: Date,
    optional: true
  },
  "workflow": Workflow
});

/**
 * @name OrderTransaction Schema
 * @memberof Schemas
 * @summary Order transactions tie Shipping, Payment, and Inventory transactions
 * @type {SimpleSchema}
 * @property {String} itemId optional
 * @property {String} paymentId optional
 * @property {String} shipmentId optional
 * @property {String} inventoryId optional
 * @property {Date} createdAt required
 */
const OrderTransaction = new SimpleSchema({
  itemId: {
    type: String,
    optional: true
  },
  paymentId: {
    type: String,
    optional: true
  },
  shipmentId: {
    type: String,
    optional: true
  },
  inventoryId: {
    type: String,
    optional: true
  },
  createdAt: {
    type: Date
  }
});


/**
 * @name CurrencyExchangeRate
 * @type {SimpleSchema}
 * @memberof Schemas
 * @property {String} userCurrency, default value: `"USD"`
 * @property {Number} exchangeRate optional
 */
const CurrencyExchangeRate = new SimpleSchema({
  userCurrency: {
    type: String,
    optional: true,
    defaultValue: "USD"
  },
  exchangeRate: {
    type: Number,
    optional: true
  }
});

/**
 * @name Payment
 * @type {SimpleSchema}
 * @memberof Schemas
 * @property {String} _id Payment ID
 * @property {Address} [address] Billing address
 * @property {Number} amount The amount paid or authorized
 * @property {String} [cardBrand] The brand of card, if the payment method was a credit card
 * @property {CurrencyExchangeRate} [currency] The exchange rate, if the user's currency is different from shop's
 * @property {Object} [data] Arbitrary data that the payment method needs
 * @property {String} mode "authorize" if still needs to be captured, or "capture" if captured. "cancel" if auth was canceled.
 * @property {Invoice} invoice A summary of the totals that make up the full charge amount. Created when the payment is added to an order.
 * @property {String} shopId The ID of the shop that is being paid.
 */
export const Payment = new SimpleSchema({
  "_id": {
    type: String,
    label: "Payment Id"
  },
  "address": {
    type: OrderAddress,
    optional: true
  },
  "amount": Number,
  "captureErrorCode": {
    type: String,
    optional: true
  },
  "captureErrorMessage": {
    type: String,
    optional: true
  },
  "cardBrand": {
    type: String,
    optional: true
  },
  "createdAt": Date,
  "currency": {
    type: CurrencyExchangeRate,
    optional: true
  },
  "currencyCode": String,
  "data": {
    type: Object,
    optional: true,
    blackbox: true
  },
  "displayName": String,
  "method": String,
  "mode": String,
  "name": String,
  "paymentPluginName": String,
  "processor": String,
  "riskLevel": {
    type: String,
    optional: true
  },
  "shopId": String,
  "status": String,
  "transactionId": String,
  "transactions": {
    type: Array
  },
  "transactions.$": {
    type: Object,
    blackbox: true
  }
});

/**
 * @name Order Schema
 * @memberof Schemas
 * @type {SimpleSchema}
 * @summary Order has an array of History, Documents, Notes, Items and OrderTransactions.
 * @property {String} _id required
 * @property {String} accountId Account ID for account orders, or null for anonymous
 * @property {Object[]} anonymousAccessTokens Tokens for accessing anonymous orders, null for account orders
 * @property {String} anonymousAccessTokens.hashedToken The hashed value for DB queries
 * @property {Date} anonymousAccessTokens.createdAt When the token was created. Expiry is not currently implemented, but this Date is here to support that.
 * @property {Address} [billingAddress] Optional billing address
 * @property {String} cartId optional For tracking which cart created this order
 * @property {Date} createdAt required
 * @property {String} currencyCode required
 * @property {Object} customFields optional
 * @property {Document[]} documents optional
 * @property {String} email optional
 * @property {Object[]} exportHistory optional
 * @property {History[]} history optional
 * @property {Notes[]} notes optional
 * @property {Payment[]} payments Array of payments
 * @property {Shipment[]} shipping Array of fulfillment groups
 * @property {String} shopId required The owner shop
 * @property {Surcharges[]} surcharges Surcharges applied to this order
 * @property {OrderTransaction[]} transactions optional
 * @property {Date} updatedAt optional
 * @property {Workflow} workflow optional
 */
export const Order = new SimpleSchema({
  "_id": {
    type: String,
    optional: true
  },
  "accountId": {
    type: String,
    optional: true
  },
  "anonymousAccessTokens": {
    type: Array,
    optional: true
  },
  "anonymousAccessTokens.$": AnonymousAccessToken,
  // Although billing address is typically needed only by the payment plugin,
  // some tax services require it to calculate taxes for digital items. Thus
  // it should be provided here in order to be added to the CommonOrder if possible.
  "billingAddress": {
    type: OrderAddress,
    optional: true
  },
  "cartId": {
    type: String,
    optional: true
  },
  "createdAt": Date,
  "currencyCode": String,
  "customFields": {
    type: Object,
    blackbox: true,
    optional: true
  },
  "discounts": {
    type: Array,
    optional: true
  },
  "discounts.$": OrderDiscount,
  "documents": {
    type: Array,
    optional: true
  },
  "documents.$": Document,
  "email": {
    type: String,
    optional: true,
    regEx: SimpleSchema.RegEx.Email
  },
  "exportHistory": {
    type: Array,
    optional: true
  },
  "exportHistory.$": ExportHistory,
  "history": {
    type: Array,
    optional: true
  },
  "history.$": History,
  "notes": {
    type: Array,
    optional: true
  },
  "notes.$": Notes,
  "ordererPreferredLanguage": {
    type: String,
    optional: true
  },
  "payments": {
    type: Array,
    optional: true
  },
  "payments.$": Payment,
  "referenceId": {
    type: String
  },
  "shipping": [OrderFulfillmentGroup],
  "shopId": String,
  "surcharges": {
    type: Array,
    optional: true
  },
  "surcharges.$": {
    type: Object,
    blackbox: true
  },
  "totalItemQuantity": {
    type: SimpleSchema.Integer,
    min: 1
  },
  "transactions": {
    type: Array,
    optional: true
  },
  "transactions.$": OrderTransaction,
  "updatedAt": {
    type: Date,
    optional: true
  },
  "workflow": {
    type: Workflow,
    optional: true,
    defaultValue: {}
  },
  "appliedPromotions": {
    type: Array,
    optional: true,
    defaultValue: []
  },
  "appliedPromotions.$": {
    type: Object,
    blackbox: true
  }
});

/**
 * @summary Extend schemas from other plugins
 * @param {Object} schemas Schema map from context
 * @return {undefined}
 */
export function extendOrdersSchemas(schemas) {
  schemas.Shop.extend({
    orderStatusLabels: {
      type: Object,
      blackbox: true,
      optional: true
    }
  });
}
