/**
 * TempDirSandboxStrategy — lightweight sandbox using OS temp directories.
 *
 * Creates a temporary directory for each test case, provides it as
 * the working directory, and cleans up after execution. No isolation
 * guarantees — the agent has full access to the host filesystem.
 *
 * This is the universal fallback when Docker is unavailable.
 *
 * @see docs/archive/exec-plans/architecture-overhaul/phase-4-agent-harness.md
 */
import { randomUUID } from "crypto";
import { existsSync, mkdirSync, readdirSync, rmSync } from "fs";
import { tmpdir } from "os";
import { resolve } from "path";
export class TempDirSandboxStrategy {
    name = "Temporary Directory";
    type = "tempdir";
    async isAvailable() {
        // Always available — every OS has a temp directory
        return true;
    }
    async provision(options) {
        // Include sanitized taskId for debugging (strip non-alphanumeric for safety)
        const safeTaskId = (options.taskId ?? "anon")
            .replace(/[^a-zA-Z0-9_-]/g, "")
            .slice(0, 20);
        const id = `ailf-sandbox-${safeTaskId}-${randomUUID().slice(0, 8)}`;
        const workingDir = resolve(tmpdir(), id);
        mkdirSync(workingDir, { recursive: true });
        return {
            id,
            workingDir,
            strategy: "tempdir",
            createdAt: new Date().toISOString(),
        };
    }
    async collectArtifacts(sandbox) {
        const modifiedFiles = [];
        if (existsSync(sandbox.workingDir)) {
            collectFilesRecursive(sandbox.workingDir, "", modifiedFiles);
        }
        return {
            modifiedFiles,
            durationMs: Date.now() - new Date(sandbox.createdAt).getTime(),
        };
    }
    async teardown(sandbox) {
        const workDir = resolve(sandbox.workingDir);
        // Guard: only delete directories under os.tmpdir() to prevent
        // accidental deletion if workingDir is corrupted
        if (existsSync(workDir) && workDir.startsWith(resolve(tmpdir()))) {
            rmSync(workDir, { recursive: true, force: true });
        }
    }
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function collectFilesRecursive(dir, prefix, files, maxDepth = 20) {
    if (maxDepth <= 0)
        return;
    for (const entry of readdirSync(dir, { withFileTypes: true })) {
        if (entry.isSymbolicLink())
            continue; // Skip symlinks to prevent traversal
        const relative = prefix ? `${prefix}/${entry.name}` : entry.name;
        if (entry.isDirectory()) {
            collectFilesRecursive(resolve(dir, entry.name), relative, files, maxDepth - 1);
        }
        else {
            files.push(relative);
        }
    }
}
