import type { Runtime } from "../../../src/core/eval/runtime";
import { COWStore } from "../../../src/core/eval/store";
import type { Env } from "../../../src/core/eval/env";
import type { Store } from "../../../src/core/eval/store";
import type { State } from "../../../src/core/eval/machine";
import type { Val } from "../../../src/core/eval/values";
import type { EffectBackend } from "../../../src/core/effects/backend";
import type { OpCall } from "../../../src/core/effects/opcall";
import { SleepBackend } from "../../../src/core/effects/backends/sleep";
import { installMembranePrims } from "./membranePrimitives";

export interface CommitAdapter {
  commit(payload: Val, ctxDigest: string): Promise<Val>;
}

export interface KernelRuntime extends Runtime {
  registerBackend(backend: EffectBackend): void;
}

class KernelRuntimeImpl implements KernelRuntime {
  private readonly backendMap = new Map<string, EffectBackend>();

  constructor() {
    this.registerBackend(new SleepBackend());
  }

  registerBackend(backend: EffectBackend): void {
    for (const op of backend.ops) {
      this.backendMap.set(op, backend);
    }
  }

  async dispatch(state: State, opcall: OpCall): Promise<State | "Uncaught"> {
    const backend = this.backendMap.get(opcall.op);
    if (!backend) {
      return "Uncaught";
    }
    return backend.handle(state, opcall);
  }
}

export function createKernelRuntime(options: {
  profile?: unknown;
  budget?: unknown;
  commit?: CommitAdapter;
} = {}): KernelRuntime {
  void options;
  return new KernelRuntimeImpl();
}

export function createKernelPrimitives(store: Store = new COWStore()): { env: Env; store: Store } {
  return installMembranePrims(store);
}
