/**
 * Sandbox selector — chooses the best available sandbox strategy.
 *
 * Selection logic:
 * 1. If task config specifies a strategy, use it
 * 2. If Docker is available, prefer Docker (better isolation)
 * 3. Fall back to TempDir (always available)
 *
 * CI environments (detected via CI env var) always prefer Docker.
 *
 * @see docs/archive/exec-plans/architecture-overhaul/phase-4-agent-harness.md
 */
import { DockerSandboxStrategy } from "./docker-sandbox.js";
import { GitWorktreeSandboxStrategy } from "./git-worktree-sandbox.js";
import { TempDirSandboxStrategy } from "./tempdir-sandbox.js";
// ---------------------------------------------------------------------------
// Strategy registry
// ---------------------------------------------------------------------------
const strategies = {
    docker: () => new DockerSandboxStrategy(),
    "git-worktree": () => new GitWorktreeSandboxStrategy(),
    none: () => new TempDirSandboxStrategy(), // "none" = tempdir
    tempdir: () => new TempDirSandboxStrategy(),
};
/**
 * Select the best available sandbox strategy.
 *
 * @param preferred - Preferred sandbox type from task config
 * @param log - Optional log function for diagnostics
 * @returns The selected strategy with fallback metadata
 */
export async function selectSandboxStrategy(preferred, log) {
    const emit = log ?? (() => { });
    // If a specific strategy is requested, try it first
    if (preferred && preferred !== "none") {
        const strategy = strategies[preferred]();
        const available = await strategy.isAvailable();
        if (available) {
            emit(`Using ${strategy.name} sandbox strategy (requested)`);
            return { strategy, isFallback: false };
        }
        emit(`${strategy.name} is not available, falling back...`);
    }
    // CI environments prefer Docker
    const isCI = Boolean(process.env.CI || process.env.GITHUB_ACTIONS);
    if (isCI) {
        const docker = new DockerSandboxStrategy();
        if (await docker.isAvailable()) {
            emit("Using Docker sandbox strategy (CI environment)");
            return { strategy: docker, isFallback: preferred !== "docker" };
        }
    }
    // Default fallback: Docker → TempDir
    const docker = new DockerSandboxStrategy();
    if (await docker.isAvailable()) {
        emit("Using Docker sandbox strategy (auto-detected)");
        return {
            strategy: docker,
            isFallback: preferred !== undefined && preferred !== "docker",
            ...(preferred && preferred !== "docker"
                ? {
                    warning: `Preferred sandbox "${preferred}" unavailable, using Docker instead`,
                }
                : {}),
        };
    }
    // Universal fallback
    const tempdir = new TempDirSandboxStrategy();
    emit("Using TempDir sandbox strategy (fallback)");
    return {
        strategy: tempdir,
        isFallback: preferred !== undefined && preferred !== "tempdir",
        ...(preferred && preferred !== "tempdir" && preferred !== "none"
            ? {
                warning: `Preferred sandbox "${preferred}" unavailable, using temp directory instead`,
            }
            : {}),
    };
}
/**
 * Create a specific sandbox strategy by type.
 * Does NOT check availability — caller should verify first.
 */
export function createSandboxStrategy(type) {
    return strategies[type]();
}
