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

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 Item {
  readonly name: string;
  readonly qty: number;
}

export const Item = {
};

export interface CartState {
  readonly items: Record<string, Item>;
}

const __CartRegistry = new StateRegistry();
function __zeroOfCartState(): CartState { return { items: {} }; }

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

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

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

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

  async add(sku: string, it: Item, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await ((__state.items[sku] = it), undefined);
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async lookup(sku: string, deps: {}): Promise<Option<Item>> {
    const __state = await this.loadState();
    const found = await (() => { const __k = sku; return (__k in __state.items) ? Some(__state.items[__k]) : None; })();
    return found;
  }

  async bump(sku: string, deps: {}): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (() => { const __k = sku; if (!(__k in __state.items)) { throw new Error("Map.update: key absent"); } __state.items[__k] = ((i) => ({ ...i, qty: i.qty + 1 }))(__state.items[__k]); return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async count(deps: {}): Promise<number> {
    const __state = await this.loadState();
    const n = await Object.keys(__state.items).length;
    return n;
  }

}

export function __makeCart(key: string, env?: { CART?: DurableObjectNamespace }): Cart {
  return makeAgent(__CartRegistry, env?.CART, key, (state) => new Cart(state));
}

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

export function serialise_Item(value: Item): JsonValue {
  return {
    name: value.name as JsonValue,
    qty: value.qty as JsonValue,
  };
}

export function deserialise_Item(json: JsonValue, path: string = "$"): Result<Item, 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["name"] !== "string") {
    return Err({ kind: "StructuralMismatch", path: `${path}.name`, expected: "string", actual: typeof obj["name"] });
  }
  const __name = obj["name"];
  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({ name: __name, qty: __qty } as Item);
}


