import { execFile } from 'node:child_process';
import fs from 'node:fs/promises';
import path from 'node:path';
import { promisify } from 'node:util';
import { assertSafeId, safeJoin, safeWorkspacePath } from '../../../modules/orchestration/workspace/path-safety.js';
import { WorkspaceError } from '../../../modules/orchestration/workspace/types.js';
const execFileAsync = promisify(execFile);
async function run(command, args, cwd) {
    try {
        const { stdout, stderr } = await execFileAsync(command, args, {
            cwd,
            maxBuffer: 20 * 1024 * 1024,
        });
        return {
            stdout: String(stdout),
            stderr: String(stderr),
            exitCode: 0,
        };
    }
    catch (error) {
        const err = error;
        return {
            stdout: String(err.stdout ?? ''),
            stderr: String(err.stderr ?? err.message),
            exitCode: typeof err.code === 'number' ? err.code : 1,
        };
    }
}
export class WorktreeWorkspace {
    kind = 'worktree';
    id;
    path;
    baseRef;
    branchName;
    metadata;
    projectPath;
    constructor(request, workspaceId, branchName) {
        this.id = workspaceId;
        this.path = safeWorkspacePath(workspaceId);
        this.baseRef = request.baseRef ?? 'HEAD';
        this.branchName = branchName;
        this.projectPath = request.projectPath;
        this.metadata = {
            ...request.metadata,
            keepAfterCompletion: request.keepAfterCompletion === true,
        };
    }
    static async create(request) {
        assertSafeId(request.taskId, 'task id');
        const workspaceId = `ws_${request.taskId}`;
        const branchName = `pixcode/task_${request.taskId}`;
        const workspace = new WorktreeWorkspace(request, workspaceId, branchName);
        const existingBranch = await run('git', ['rev-parse', '--verify', branchName], request.projectPath);
        if (existingBranch.exitCode === 0) {
            throw new WorkspaceError('WORKSPACE_EXISTS', `Workspace branch already exists: ${branchName}`, {
                branchName,
            });
        }
        const result = await run('git', ['worktree', 'add', workspace.path, '-b', branchName, workspace.baseRef], request.projectPath);
        if (result.exitCode !== 0) {
            throw new WorkspaceError('WORKSPACE_CREATE_FAILED', result.stderr || result.stdout, {
                stdout: result.stdout,
                stderr: result.stderr,
                baseRef: workspace.baseRef,
            });
        }
        return workspace;
    }
    exec(command, args = []) {
        return run(command, args, this.path);
    }
    async readFile(relativePath) {
        return fs.readFile(safeJoin(this.path, relativePath), 'utf8');
    }
    async writeFile(relativePath, content) {
        const target = safeJoin(this.path, relativePath);
        await fs.mkdir(path.dirname(target), { recursive: true });
        await fs.writeFile(target, content, 'utf8');
    }
    async diff() {
        const result = await run('git', ['diff', `${this.baseRef}...HEAD`], this.path);
        if (result.exitCode !== 0) {
            const output = result.stderr || result.stdout;
            return /not a git repository|usage: git diff --no-index/i.test(output) ? '' : output;
        }
        return result.stdout;
    }
    async destroy() {
        const result = await run('git', ['worktree', 'remove', '--force', this.path], this.projectPath);
        if (result.exitCode !== 0) {
            throw new WorkspaceError('WORKSPACE_DESTROY_FAILED', result.stderr || result.stdout, {
                workspacePath: this.path,
            });
        }
    }
}
//# sourceMappingURL=worktree-workspace.js.map