/**
 * The mailbox id a live session's box is keyed by. Teams stamp a durable
 * `agentId` (== the Claude session id for Claude teammates); a bare run has
 * only its `sessionId`. The spawn-time `AGENTS_MAILBOX_DIR` wiring must key the
 * box by this same id — this is the single source of truth for both sides.
 */
export function mailboxIdForActiveSession(s) {
    return s.agentId ?? s.sessionId;
}
function labelFor(s) {
    return s.label ?? s.topic ?? s.teamName ?? s.host ?? s.context;
}
/**
 * Resolve `target` against the live sessions. Exact id matches win over prefix
 * matches; results are de-duped by canonical mailbox id (collapsed subagents
 * share one). `isCloudTask` is consulted first so a cloud task id routes to the
 * cloud provider.
 */
export function resolveMessageTarget(target, sessions, isCloudTask) {
    if (isCloudTask(target))
        return { kind: 'cloud', id: target };
    // An empty target would make every `startsWith` prefix match — never guess.
    if (target.length === 0)
        return { kind: 'none' };
    const exact = sessions.filter((s) => s.sessionId === target || s.agentId === target);
    const chosen = exact.length > 0
        ? exact
        : sessions.filter((s) => Boolean(s.sessionId?.startsWith(target)) || Boolean(s.agentId?.startsWith(target)));
    // De-dupe by canonical mailbox id (one box per logical agent).
    const byId = new Map();
    for (const s of chosen) {
        const id = mailboxIdForActiveSession(s);
        if (id && !byId.has(id))
            byId.set(id, s);
    }
    const ids = [...byId.keys()];
    if (ids.length === 0)
        return { kind: 'none' };
    if (ids.length === 1)
        return { kind: 'local', id: ids[0] };
    return {
        kind: 'ambiguous',
        candidates: [...byId.entries()].map(([id, s]) => ({ id, label: labelFor(s) })),
    };
}
/**
 * Decide how `agents message <target>` should handle a target that matched no
 * local/cloud session (RUSH-2366 follow-up): `getActiveSessions()` has no
 * visibility into a detached `agents run --device <host> --no-follow`
 * dispatch, whose only local record is the `~/.agents/.cache/hosts/<id>.json`
 * sidecar `agents devices ps` reads. Pure — the caller does the actual lookup
 * (`resolveTaskRef`) and I/O (the ssh reroute).
 *
 * `remoteRef` prefers the remote agent's OWN identity (its captured session id
 * or `--name` handle) over the LOCAL dispatch-record id the user typed here —
 * the live process on the host registers itself under the former, never the
 * latter.
 */
export function decideHostTaskRoute(task, target) {
    if (!task)
        return { kind: 'not-found' };
    if (task.status === 'running') {
        return { kind: 'reroute', remoteRef: task.sessionId ?? task.name ?? target, host: task.host };
    }
    return { kind: 'finished', host: task.host, status: task.status, exitCode: task.exitCode };
}
