import { EventReplayBuffer } from './event-buffer.js';
import { RemoteSessionRegistry } from './session-registry.js';
function toModelSummary(model) {
    if (!model)
        return undefined;
    return {
        provider: model.provider,
        id: model.id
    };
}
export class DesktopRemoteControlRuntime {
    session;
    approvalController;
    registry;
    eventBuffer;
    listeners = new Set();
    controllerAttached = false;
    remoteApprovalActive = false;
    unsubscribeSession;
    unsubscribeApprovals;
    constructor(options) {
        this.session = options.session;
        this.approvalController = options.approvalController;
        this.registry = new RemoteSessionRegistry({
            listSessions: options.listSessions
        });
        this.eventBuffer = new EventReplayBuffer({
            capacity: options.eventCapacity ?? 500
        });
        this.unsubscribeApprovals = this.approvalController.subscribe((event) => {
            if (event.type === 'requested') {
                this.publish({
                    type: 'approval_pending',
                    approval: event.approval
                });
                return;
            }
            this.publish({
                type: 'approval_resolved',
                approvalId: event.approval.id,
                choice: event.choice
            });
        });
        this.unsubscribeSession = this.session.subscribe((event) => {
            if (event.type === 'agent_end') {
                this.remoteApprovalActive = false;
            }
            this.publish({
                type: 'session_event',
                event
            });
        });
    }
    isControllerAttached() {
        return this.controllerAttached;
    }
    shouldRouteApprovalsToRemote() {
        return this.controllerAttached && this.remoteApprovalActive;
    }
    subscribe(listener) {
        this.listeners.add(listener);
        return () => {
            this.listeners.delete(listener);
        };
    }
    detach() {
        this.controllerAttached = false;
        this.remoteApprovalActive = false;
        this.approvalController.rejectAll();
    }
    close() {
        this.detach();
        this.unsubscribeSession();
        this.unsubscribeApprovals();
        this.listeners.clear();
    }
    async attach(options) {
        if (!options.requestedSessionId && !options.requestedSessionPath) {
            this.controllerAttached = true;
            return {
                kind: 'attached',
                snapshot: this.buildSnapshot(this.buildLiveSessionSummary()),
                replay: this.eventBuffer.replayAfter(options.lastSeq)
            };
        }
        const target = await this.registry.resolveTarget({
            currentSessionPath: this.session.sessionFile,
            requestedSessionId: options.requestedSessionId,
            requestedSessionPath: options.requestedSessionPath
        });
        if (target.kind === 'picker' || target.kind === 'create' || target.kind === 'not_found') {
            return target;
        }
        if (target.session.path !== this.session.sessionFile) {
            const switched = await this.session.switchSession(target.session.path);
            if (!switched) {
                return { kind: 'cancelled' };
            }
        }
        this.controllerAttached = true;
        const snapshot = this.buildSnapshot(target.session);
        return {
            kind: 'attached',
            snapshot,
            replay: this.eventBuffer.replayAfter(options.lastSeq)
        };
    }
    async handleCommand(command) {
        switch (command.type) {
            case 'get_snapshot':
                return { kind: 'snapshot', snapshot: this.buildSnapshot() };
            case 'list_sessions':
                return {
                    kind: 'sessions',
                    sessions: await this.listAvailableSessions()
                };
            case 'attach': {
                const result = await this.attach(command);
                if (result.kind === 'attached') {
                    return result;
                }
                return result;
            }
            case 'select_session': {
                const switched = await this.session.switchSession(command.sessionPath);
                if (!switched) {
                    return { kind: 'cancelled' };
                }
                return { kind: 'snapshot', snapshot: this.buildSnapshot() };
            }
            case 'new_session': {
                const created = await this.session.newSession({
                    parentSession: command.parentSession
                });
                if (!created) {
                    return { kind: 'cancelled' };
                }
                return { kind: 'snapshot', snapshot: this.buildSnapshot() };
            }
            case 'prompt':
                this.remoteApprovalActive = true;
                await this.session.prompt(command.message, {
                    images: command.images
                });
                return { kind: 'ok' };
            case 'steer':
                this.remoteApprovalActive = true;
                await this.session.steer(command.message, command.images);
                return { kind: 'ok' };
            case 'follow_up':
                this.remoteApprovalActive = true;
                await this.session.followUp(command.message, command.images);
                return { kind: 'ok' };
            case 'abort':
                this.remoteApprovalActive = false;
                await this.session.abort();
                return { kind: 'ok' };
            case 'approval_response': {
                const resolved = this.approvalController.resolve(command.approvalId, command.choice);
                if (!resolved) {
                    return {
                        kind: 'approval_missing',
                        approvalId: command.approvalId
                    };
                }
                return { kind: 'ok' };
            }
            case 'set_session_name':
                this.session.setSessionName(command.name);
                return { kind: 'snapshot', snapshot: this.buildSnapshot() };
        }
    }
    publish(event) {
        const sequenced = this.eventBuffer.append(event);
        for (const listener of this.listeners) {
            listener(sequenced);
        }
    }
    buildSnapshot(sessionSummary) {
        const summary = sessionSummary ?? this.buildLiveSessionSummary();
        return {
            session: summary,
            state: {
                model: toModelSummary(this.session.model),
                thinkingLevel: this.session.thinkingLevel,
                isStreaming: this.session.isStreaming,
                isCompacting: this.session.isCompacting,
                pendingMessageCount: this.session.pendingMessageCount,
                steeringMessages: this.session.getSteeringMessages(),
                followUpMessages: this.session.getFollowUpMessages(),
                sessionStats: this.session.getSessionStats()
            },
            messages: this.session.messages,
            pendingApprovals: this.approvalController.getPending(),
            latestSeq: this.eventBuffer.latestSeq()
        };
    }
    async listAvailableSessions() {
        const sessions = await this.registry.listSessions(this.session.sessionFile);
        const live = this.buildLiveSessionSummary();
        const withoutLiveDuplicate = sessions.filter((session) => session.path !== live.path);
        return [live, ...withoutLiveDuplicate];
    }
    buildLiveSessionSummary() {
        return {
            path: this.session.sessionFile ?? `live:${this.session.sessionId}`,
            id: this.session.sessionId,
            cwd: process.cwd(),
            name: this.session.sessionName,
            createdAt: '',
            modifiedAt: '',
            messageCount: this.session.messages.length,
            firstMessage: '',
            lastMessage: '',
            isCurrent: true
        };
    }
}
//# sourceMappingURL=desktop-runtime.js.map