---
Orders context. Each order is an agent instance keyed by OrderId.
---
context commerce.orders

uses commerce.identifiers

exports transparent { OrderError, OrderStatus }

type OrderError = enum {
  EmptyCart,
  TooManyItems,
  OutOfStock,
}

type OrderStatus = enum {
  Pending,
  Placed,
  Cancelled,
}

capability Inventory {
  fn check(productId: CustomerId) -> Effect[Result[Int, OrderError]]
}

provides Inventory = StubInventory {
  fn check(productId: CustomerId) -> Effect[Result[Int, OrderError]] {
    Ok(100)
  }
}

agent Order {
  key id: OrderId

  store status: Cell[Option[OrderStatus]]
  store items: Cell[Int]

  on call status() -> Effect[Option[OrderStatus]] {
    status
  }

  on call addItem(productId: CustomerId, quantity: Int) -> Effect[Result[(), OrderError]]
      given Inventory {
    let stockResult <- Inventory.check(productId)
    let stock = stockResult?
    if stock < quantity {
      Err(OutOfStock)
    } else if items >= 50 {
      Err(TooManyItems)
    } else {
      let cur = items
      items := cur + quantity
      Ok(())
    }
  }
}
