// Generated by bynkc — do not edit by hand.
// context shop.inventory

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 interface Reservation {
  readonly id: string;
  readonly orderId: string;
  readonly qty: number;
}

export const Reservation = {
};

export interface InventoryState {
  readonly reservations: Record<string, Reservation>;
  readonly reservations__idx_orderId: Record<string, string[]>;
}

const __InventoryRegistry = new StateRegistry();
function __zeroOfInventoryState(): InventoryState { return { reservations: {}, reservations__idx_orderId: {} }; }

function __rehydrateInventoryState(s: InventoryState): void {
  for (const __v of Object.values(s.reservations)) { const __r = deserialise_Reservation((__v as unknown as JsonValue), "reservations"); if (__r.tag === "Err") throw rehydrationViolation("Inventory", __r.error); }
  for (const __k of Object.keys(s.reservations)) { const __r = ((__v) => typeof __v === "string" ? Ok(__v) : Err({ kind: "StructuralMismatch", path: "reservations", expected: "string", actual: typeof __v } as BoundaryError))((__k as unknown as JsonValue)); if (__r.tag === "Err") throw rehydrationViolation("Inventory", __r.error); }
}

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

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

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

  async reserve(rid: string, r: Reservation, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (() => { const __k = String(rid); const __v = r; const __o = __state.reservations[__k]; if (__o !== undefined) { { const __ik = String((__o).orderId); const __ia = __state.reservations__idx_orderId[__ik]; if (__ia) { const __ii = __ia.indexOf(__k); if (__ii >= 0) __ia.splice(__ii, 1); if (__ia.length === 0) delete __state.reservations__idx_orderId[__ik]; } } } __state.reservations[__k] = __v; { const __ik = String((__v).orderId); (__state.reservations__idx_orderId[__ik] = __state.reservations__idx_orderId[__ik] ?? []).push(__k); } return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async retag(rid: string, oid: string, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (() => { const __k = String(rid); if (!(__k in __state.reservations)) { throw new Error("Map.update: key absent"); } const __o = __state.reservations[__k]; { const __ik = String((__o).orderId); const __ia = __state.reservations__idx_orderId[__ik]; if (__ia) { const __ii = __ia.indexOf(__k); if (__ii >= 0) __ia.splice(__ii, 1); if (__ia.length === 0) delete __state.reservations__idx_orderId[__ik]; } } const __v = ((r) => ({ ...r, orderId: oid }))(__o); __state.reservations[__k] = __v; { const __ik = String((__v).orderId); (__state.reservations__idx_orderId[__ik] = __state.reservations__idx_orderId[__ik] ?? []).push(__k); } return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async drop(rid: string, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (() => { const __k = String(rid); const __o = __state.reservations[__k]; if (__o !== undefined) { { const __ik = String((__o).orderId); const __ia = __state.reservations__idx_orderId[__ik]; if (__ia) { const __ii = __ia.indexOf(__k); if (__ii >= 0) __ia.splice(__ii, 1); if (__ia.length === 0) delete __state.reservations__idx_orderId[__ik]; } } delete __state.reservations[__k]; } return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async countForOrder(oid: string, deps: {}): Promise<number> {
    const __state = await this.loadState();
    return ((() => (__state.reservations__idx_orderId[String(oid)] ?? []).map((__pk) => __state.reservations[__pk])))().length;
  }

  async qtyForOrder(oid: string, deps: {}): Promise<number> {
    const __state = await this.loadState();
    return ((() => (__state.reservations__idx_orderId[String(oid)] ?? []).map((__pk) => __state.reservations[__pk])))().reduce((__s: number, __x) => __s + ((r) => r.qty)(__x), 0);
  }

}

export function __makeInventory(key: string, env?: { INVENTORY?: DurableObjectNamespace }): Inventory {
  return makeAgent(__InventoryRegistry, env?.INVENTORY, key, (state) => new Inventory(state));
}

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

export function serialise_Reservation(value: Reservation): JsonValue {
  return {
    id: value.id as JsonValue,
    orderId: value.orderId as JsonValue,
    qty: value.qty as JsonValue,
  };
}

export function deserialise_Reservation(json: JsonValue, path: string = "$"): Result<Reservation, 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 };
  if (typeof obj["id"] !== "string") {
    return Err({ kind: "StructuralMismatch", path: `${path}.id`, expected: "string", actual: typeof obj["id"] });
  }
  const __id = obj["id"];
  if (typeof obj["orderId"] !== "string") {
    return Err({ kind: "StructuralMismatch", path: `${path}.orderId`, expected: "string", actual: typeof obj["orderId"] });
  }
  const __orderId = obj["orderId"];
  if (typeof obj["qty"] !== "number") {
    return Err({ kind: "StructuralMismatch", path: `${path}.qty`, expected: "number", actual: typeof obj["qty"] });
  }
  if (!Number.isInteger(obj["qty"])) {
    return Err({ kind: "StructuralMismatch", path: `${path}.qty`, expected: "integer", actual: String(obj["qty"]) });
  }
  const __qty = obj["qty"];
  return Ok({ id: __id, orderId: __orderId, qty: __qty } as Reservation);
}


