import type { DriverRegistry } from "@open-matrix/inference";
import type { EffectBackend } from "../core/effects/backend";
import type { Val } from "../core/eval/values";
import type { Runtime } from "../core/eval/runtime";
import type { OracleAdapter, SnapshotRepo, ReceiptStore } from "./oracle-runtime";
import type { Profile } from "../core/governance/profile";
import type { BudgetTracker } from "../core/governance/budgets";

export type AmbStrategy = "DFS" | "FAIR";

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

export type OracleBackendLike = EffectBackend & {
  setBudget: (budget: BudgetTracker) => void;
};

export type AmbBackendLike = EffectBackend & {
  setBudget: (budget: BudgetTracker) => void;
  setStrategy: (strategy: AmbStrategy) => void;
  reset: () => void;
  hasAlternatives: () => boolean;
};

export async function createOracleRuntimeBackend(options: {
  oracle: OracleAdapter | undefined;
  snapshots: SnapshotRepo;
  receipts: ReceiptStore;
  profile: Profile;
  budget: BudgetTracker | undefined;
  runtime: Runtime;
  registry: DriverRegistry | undefined;
  defaultDriver: string | undefined;
}): Promise<OracleBackendLike> {
  const mod = await import("../../packages/oracle/core/src/backend");
  return new mod.OracleBackend(
    options.oracle,
    options.snapshots,
    options.receipts,
    options.profile,
    options.budget,
    options.runtime as any,
    options.registry,
    options.defaultDriver,
  ) as OracleBackendLike;
}

export async function createAmbRuntimeBackend(budget?: BudgetTracker): Promise<AmbBackendLike> {
  const mod = await import("../../packages/strategies/nondeterministic/src/backend");
  return new mod.AmbBackend(budget) as AmbBackendLike;
}

export async function createCommitRuntimeBackend(options: {
  commit: CommitAdapterLike;
  profile: Profile;
  runtime: Runtime;
  snapshots: SnapshotRepo;
  receipts: ReceiptStore;
}): Promise<EffectBackend> {
  const mod = await import("../../packages/self-healing/src/backend");
  return new mod.CommitBackend(
    options.commit,
    options.profile,
    options.runtime as any,
    options.snapshots,
    options.receipts,
  ) as EffectBackend;
}

export async function createCacheRuntimeBackend(): Promise<EffectBackend> {
  const mod = await import("../../packages/oracle/cached-infer/src/backend");
  return new mod.CacheBackend() as EffectBackend;
}

export async function createEmacsRuntimeBackend(): Promise<EffectBackend> {
  const mod = await import("../../packages/emacs/src/backend");
  return new mod.EmacsBackend() as EffectBackend;
}
