import { execSync } from 'child_process';
export const FOURRUNR_DB_CONTAINERS = ['4runr-postgres', '4runr-redis'];
const COMPOSE_PROJECT = '4runr';
function dockerShell() {
    return process.platform === 'win32' ? process.env['COMSPEC'] || 'cmd.exe' : undefined;
}
function dockerExec(command, timeoutMs = 30000) {
    return execSync(command, {
        encoding: 'utf-8',
        stdio: 'pipe',
        timeout: timeoutMs,
        ...(dockerShell() ? { shell: dockerShell() } : {}),
    });
}
export async function isDockerAvailable() {
    try {
        const result = dockerExec('docker --version', 5000);
        return result.includes('Docker version');
    }
    catch {
        return false;
    }
}
export async function isDockerRunning() {
    try {
        dockerExec('docker info', 5000);
        return true;
    }
    catch {
        return false;
    }
}
export function isContainerRunning(containerName) {
    try {
        const state = dockerExec(`docker inspect --format="{{.State.Running}}" ${containerName}`, 5000).trim();
        return state === 'true';
    }
    catch {
        return false;
    }
}
export async function areContainersRunning() {
    return FOURRUNR_DB_CONTAINERS.every((name) => isContainerRunning(name));
}
export async function startStoppedContainers() {
    const stopped = FOURRUNR_DB_CONTAINERS.filter((name) => !isContainerRunning(name));
    if (stopped.length === 0) {
        return;
    }
    try {
        dockerExec(`docker start ${stopped.join(' ')}`, 60000);
    }
    catch {
    }
}
export async function startDockerCompose(composeFilePath) {
    const cmd = `docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" up -d`;
    execSync(cmd, {
        stdio: 'inherit',
        timeout: 120000,
        ...(dockerShell() ? { shell: dockerShell() } : {}),
    });
}
export async function ensure4RunrStackRunning(composeFilePath) {
    await startStoppedContainers();
    if (!(await areContainersRunning())) {
        await startDockerCompose(composeFilePath);
    }
    await startStoppedContainers();
}
export async function stopDockerCompose(composeFilePath) {
    execSync(`docker compose -p ${COMPOSE_PROJECT} -f "${composeFilePath}" stop`, {
        stdio: 'pipe',
        timeout: 30000,
        ...(dockerShell() ? { shell: dockerShell() } : {}),
    });
}
export async function stop4RunrContainers() {
    try {
        if (process.platform === 'win32') {
            execSync('docker stop 4runr-postgres 4runr-redis 2>nul', {
                stdio: 'pipe',
                timeout: 30000,
                shell: process.env['COMSPEC'] || 'cmd.exe',
            });
        }
        else {
            execSync('docker stop 4runr-postgres 4runr-redis 2>/dev/null || true', {
                stdio: 'pipe',
                timeout: 30000,
                shell: '/bin/sh',
            });
        }
    }
    catch {
    }
}
export async function waitForHealthy(containerName, timeoutMs = 30000) {
    const start = Date.now();
    while (Date.now() - start < timeoutMs) {
        try {
            const health = dockerExec(`docker inspect --format="{{.State.Health.Status}}" ${containerName}`, 5000).trim();
            if (health === 'healthy') {
                return;
            }
            if (health === '' || health === '<no value>') {
                const running = dockerExec(`docker inspect --format="{{.State.Running}}" ${containerName}`, 5000).trim();
                if (running === 'true') {
                    await sleep(2000);
                    return;
                }
            }
        }
        catch {
        }
        await sleep(1000);
    }
    const logs = getContainerLogs(containerName, 20);
    throw new Error(`Container ${containerName} did not become healthy within ${timeoutMs}ms. Recent logs:\n${logs}`);
}
export async function isPortInUse(port) {
    try {
        const result = dockerExec(`docker ps --filter "publish=${port}" --format "{{.Names}}"`, 5000);
        return result.trim().length > 0;
    }
    catch {
        return false;
    }
}
export function getContainerLogs(containerName, lines = 50) {
    try {
        return dockerExec(`docker logs --tail ${lines} ${containerName}`, 10000);
    }
    catch (err) {
        return `Failed to retrieve logs: ${err instanceof Error ? err.message : String(err)}`;
    }
}
function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}
export async function getDockerStatus() {
    const status = {
        available: false,
        running: false,
        containersRunning: false,
    };
    try {
        status.available = await isDockerAvailable();
        if (!status.available) {
            status.error = 'Docker not installed';
            return status;
        }
        status.running = await isDockerRunning();
        if (!status.running) {
            status.error = 'Docker daemon not running';
            return status;
        }
        status.containersRunning = await areContainersRunning();
        return status;
    }
    catch (err) {
        status.error = err instanceof Error ? err.message : String(err);
        return status;
    }
}
//# sourceMappingURL=docker-manager.js.map