import { BACKENDS } from './backends/index.js';
import { planLayouts } from './policy.js';
import { runSpec } from './transport.js';
const DEFAULT_STAGGER_MS = 400;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
/** The concrete launch command for a request (pure — no side effects). */
export function specForRequest(req) {
    const backend = BACKENDS[req.backend];
    if (!backend)
        throw new Error(`unknown backend: ${req.backend}`);
    const meta = req.agent || req.sessionId || req.title
        ? { agent: req.agent, sessionId: req.sessionId, title: req.title }
        : undefined;
    if (req.layout === 'tab')
        return backend.buildTab(req.cwd, req.command, meta);
    return backend.buildSplit(req.cwd, req.command, req.layout === 'split-down' ? 'down' : 'right', meta);
}
/** Open a single surface for one request. Never throws — failures come back in the result. */
export async function openSurface(req, opts = {}) {
    try {
        // Both can throw: specForRequest on an unknown backend, runSpec when the
        // SSH transport rejects an invalid --device target. Keep them inside the
        // catch so a bad request degrades to a per-surface failure, never a throw.
        const spec = specForRequest(req);
        const res = await runSpec(spec, req.host, opts.resolveHost);
        return { ok: res.ok, request: req, error: res.error };
    }
    catch (err) {
        return { ok: false, request: req, error: err?.message ?? String(err) };
    }
}
/** Turn a list of commands into layout-assigned requests (pure — the planning step). */
export function buildRequests(items, opts) {
    const layouts = planLayouts(items.length, opts.packing ?? 'two-per-tab');
    return items.map((item, i) => ({
        backend: opts.backend,
        layout: layouts[i],
        cwd: item.cwd,
        command: item.command,
        host: opts.host,
        agent: item.agent,
        sessionId: item.sessionId,
        title: item.title,
    }));
}
/**
 * Open many surfaces, applying the layout policy (default: two-per-tab).
 * Sequential + staggered so each split follows the tab it splits.
 */
export async function openSurfaces(items, opts) {
    const requests = buildRequests(items, opts);
    const stagger = opts.staggerMs ?? DEFAULT_STAGGER_MS;
    const results = [];
    for (let i = 0; i < requests.length; i++) {
        results.push(await openSurface(requests[i], opts));
        if (i < requests.length - 1)
            await sleep(stagger);
    }
    return results;
}
