// 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 Clock {
  now(): Promise<number>;
}

export const ClockToken: unique symbol = Symbol("Clock");

export class SystemClock implements Clock {
  async now(): Promise<number> {
    return 0;
  }
}

export const SystemClockProvider = { token: ClockToken, factory: () => new SystemClock() };

export interface SessionsState {
  readonly live: Record<string, { v: number; exp: number }>;
}

const __SessionsRegistry = new StateRegistry();
function __zeroOfSessionsState(): SessionsState { return { live: {} }; }

function __rehydrateSessionsState(s: SessionsState): void {
  for (const __e of Object.values(s.live)) { const __r = ((__v) => typeof __v === "number" && Number.isInteger(__v) ? Ok(__v) : Err({ kind: "StructuralMismatch", path: "live", expected: "number", actual: typeof __v } as BoundaryError))((__e.v as unknown as JsonValue)); if (__r.tag === "Err") throw rehydrationViolation("Sessions", __r.error); }
}

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

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

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

  async put(token: string, userId: number, deps: { Clock: Clock }): Promise<void> {
    const __state = { ...(await this.loadState()) };
    const __result = await (async () => {
      const __r0 = await (async () => { const __now = await deps.Clock.now(); __state.live[token] = { v: userId, exp: __now + 300000 }; return undefined; })();
      return undefined;
    })();
    await this.commitState(__state);
    return __result;
  }

  async lookup(token: string, deps: { Clock: Clock }): Promise<Option<number>> {
    const __state = await this.loadState();
    const found = await (async () => { const __now = await deps.Clock.now(); const __k = token; return ((__k in __state.live) && __state.live[__k].exp > __now) ? Some(__state.live[__k].v) : None; })();
    return found;
  }

  async active(deps: { Clock: Clock }): Promise<number> {
    const __state = await this.loadState();
    const n = await (async () => { const __now = await deps.Clock.now(); return Object.values(__state.live).filter((__e) => __e.exp > __now).length; })();
    return n;
  }

}

export function __makeSessions(key: string, env?: { SESSIONS?: DurableObjectNamespace }): Sessions {
  return makeAgent(__SessionsRegistry, env?.SESSIONS, key, (state) => new Sessions(state));
}

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

