// Generated by bynkc — do not edit by hand.
// context orders

import { Ok, Err, Some, None, type Result, type Option, type ValidationError, type DurableObjectState, type DurableObjectNamespace, StateRegistry, makeAgent, rehydrationViolation, type JsonValue, type BoundaryError } from "./runtime.js";

export type OrderStatus =
    { readonly tag: "Pending" }
  | { readonly tag: "Placed" }
  | { readonly tag: "Cancelled" };

export const OrderStatus = {
  Pending: { tag: "Pending" } as OrderStatus,
  Placed: { tag: "Placed" } as OrderStatus,
  Cancelled: { tag: "Cancelled" } as OrderStatus,
};

export type OrderError =
    { readonly tag: "AlreadyPlaced" }
  | { readonly tag: "AlreadyCancelled" };

export const OrderError = {
  AlreadyPlaced: { tag: "AlreadyPlaced" } as OrderError,
  AlreadyCancelled: { tag: "AlreadyCancelled" } as OrderError,
};

export interface OrderState {
  readonly status: OrderStatus;
  readonly items: number;
}

const __OrderRegistry = new StateRegistry();
function __zeroOfOrderState(): OrderState { return { status: OrderStatus.Pending, items: 0 }; }

function __rehydrateOrderState(s: OrderState): void {
  { const __r = deserialise_OrderStatus((s.status as unknown as JsonValue), "status"); if (__r.tag === "Err") throw rehydrationViolation("Order", __r.error); }
  { const __r = ((__v) => typeof __v === "number" && Number.isInteger(__v) ? Ok(__v) : Err({ kind: "StructuralMismatch", path: "items", expected: "number", actual: typeof __v } as BoundaryError))((s.items as unknown as JsonValue)); if (__r.tag === "Err") throw rehydrationViolation("Order", __r.error); }
}

export class Order {
  state: DurableObjectState;
  constructor(state: DurableObjectState) {
    this.state = state;
  }

  private async loadState(): Promise<OrderState> {
    const stored = await this.state.storage.get<OrderState>("state");
    if (stored === undefined) return __zeroOfOrderState();
    const __merged = { ...__zeroOfOrderState(), ...stored };
    __rehydrateOrderState(__merged);
    return __merged;
  }

  private async commitState(s: OrderState): Promise<void> {
    await this.state.storage.put("state", s);
  }

  async addItem(quantity: number, deps: {}): Promise<Result<void, OrderError>> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const cur = __state.items;
      __state.items = cur + quantity;
      return Ok(undefined);
    })();
    await this.commitState(__state);
    return __result;
  }

  async place(deps: {}): Promise<Result<void, OrderError>> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      switch (__state.status.tag) {
        case "Pending": {
          __state.status = OrderStatus.Placed;
          return Ok(undefined);
        }
        case "Placed": {
          return Err(OrderError.AlreadyPlaced);
        }
        case "Cancelled": {
          return Err(OrderError.AlreadyCancelled);
        }
      }
      throw new Error("non-exhaustive match");
    })();
    await this.commitState(__state);
    return __result;
  }

}

export function __makeOrder(key: string, env?: { ORDER?: DurableObjectNamespace }): Order {
  return makeAgent(__OrderRegistry, env?.ORDER, key, (state) => new Order(state));
}

export function __resetAgents(): void {
  __OrderRegistry.reset();
}

export function serialise_OrderStatus(value: OrderStatus): JsonValue {
  switch (value.tag) {
    case "Pending":
      return { kind: "Pending" };
    case "Placed":
      return { kind: "Placed" };
    case "Cancelled":
      return { kind: "Cancelled" };
  }
}

export function deserialise_OrderStatus(json: JsonValue, path: string = "$"): Result<OrderStatus, BoundaryError> {
  if (typeof json !== "object" || json === null || Array.isArray(json)) {
    return Err({ kind: "StructuralMismatch", path, expected: "object", actual: typeof json });
  }
  const obj = json as { [k: string]: JsonValue };
  const kind = obj["kind"];
  switch (kind) {
    case "Pending":
      return Ok({ tag: "Pending" } as OrderStatus);
    case "Placed":
      return Ok({ tag: "Placed" } as OrderStatus);
    case "Cancelled":
      return Ok({ tag: "Cancelled" } as OrderStatus);
    default:
      return Err({ kind: "StructuralMismatch", path, expected: "sum variant kind", actual: String(kind) });
  }
}


