// src/core/eval/strategy/registry.ts
// Strategy registry for kernel-level strategy contracts.

import type { RunStrategy } from "./contract";
import { DeterministicStrategy } from "./deterministic";

export class StrategyRegistry {
  private readonly strategies = new Map<string, RunStrategy>();
  private activeName = "deterministic";

  register(strategy: RunStrategy): void {
    this.strategies.set(strategy.name, strategy);

    // Keep deterministic as preferred default when available.
    if (strategy.name === "deterministic") {
      this.activeName = "deterministic";
      return;
    }

    if (!this.strategies.has(this.activeName)) {
      this.activeName = strategy.name;
    }
  }

  get(name: string): RunStrategy | undefined {
    return this.strategies.get(name);
  }

  setActive(name: string): void {
    if (!this.strategies.has(name)) {
      throw new Error(`Cannot activate strategy "${name}": not registered`);
    }
    this.activeName = name;
  }

  getActiveName(): string {
    return this.activeName;
  }

  getActive(): RunStrategy {
    const active = this.strategies.get(this.activeName);
    if (active) {
      return active;
    }

    const deterministic = this.strategies.get("deterministic");
    if (deterministic) {
      this.activeName = "deterministic";
      return deterministic;
    }

    const first = this.list().map((name) => this.strategies.get(name)).find(Boolean);
    if (first) {
      this.activeName = first.name;
      return first;
    }

    throw new Error("No strategies registered. Register at least deterministic before evaluation.");
  }

  list(): string[] {
    return Array.from(this.strategies.keys()).sort();
  }

  has(name: string): boolean {
    return this.strategies.has(name);
  }

  unregister(name: string): boolean {
    const removed = this.strategies.delete(name);
    if (!removed) {
      return false;
    }

    if (name === this.activeName) {
      if (this.strategies.has("deterministic")) {
        this.activeName = "deterministic";
      } else {
        const next = this.list()[0];
        this.activeName = next ?? "deterministic";
      }
    }

    return true;
  }

  clear(): void {
    this.strategies.clear();
    this.activeName = "deterministic";
  }

  // Legacy aliases retained for compatibility.
  getDefault(): RunStrategy | undefined {
    try {
      return this.getActive();
    } catch {
      return undefined;
    }
  }

  setDefault(name: string): void {
    this.setActive(name);
  }

  getDefaultName(): string {
    return this.getActiveName();
  }

  get size(): number {
    return this.strategies.size;
  }
}

export const globalStrategyRegistry = new StrategyRegistry();
if (!globalStrategyRegistry.has("deterministic")) {
  globalStrategyRegistry.register(new DeterministicStrategy());
}
globalStrategyRegistry.setActive("deterministic");
