import { ControlPlaneSessionApiService, } from '../services/sessions/control-plane-session-api-service.js';
import { SlashCommandAutocompleteService } from '../services/slash-commands/index.js';
import { ControlPlaneSessionSubscriptionService } from '../services/sessions/control-plane-session-subscription-service.js';
import { AssistantStreamBufferService, } from '../services/sessions/assistant-stream-buffer-service.js';
import { SessionRunStatePollerService, } from '../services/sessions/session-run-state-poller-service.js';
import { ControlPlaneSessionState, } from './control-plane-session-state.js';
import { ControlPlaneSessionLoader } from './control-plane-session-loader.js';
import { ControlPlaneDirectShellController } from './control-plane-direct-shell-controller.js';
import { ControlPlaneSlashCommandController } from './control-plane-slash-command-controller.js';
import { ControlPlanePromptController } from './control-plane-prompt-controller.js';
import { ControlPlaneLiveEventReducer } from './control-plane-live-event-reducer.js';
import { ControlPlaneApprovalController } from './control-plane-approval-controller.js';
import { ControlPlaneRunController } from './control-plane-run-controller.js';
const ASSISTANT_STREAM_RENDER_INTERVAL_MS = 75;
const RUN_STATE_POLL_INTERVAL_MS = 750;
/**
 * Public facade for cli-v2 control-plane session state over the shared tRPC API.
 *
 * Keep this class thin by composition: workflow controllers own lifecycle and
 * state-transition behavior, while this facade preserves the stable API that
 * Ink components call. Shared activity/prompt policy stays in client-shared;
 * core/control-plane remains the source of truth for domain behavior.
 */
export class ControlPlaneSessionStore {
    api;
    state;
    subscriptions;
    assistantStreamBuffer;
    runStatePoller;
    loader;
    directShell;
    slashCommands;
    prompts;
    liveEvents;
    approvals;
    runs;
    constructor(options) {
        this.api = new ControlPlaneSessionApiService(options);
        this.state = new ControlPlaneSessionState(() => this.runStatePoller.sync());
        this.subscriptions = new ControlPlaneSessionSubscriptionService({
            client: options.client,
            onSessionsUpdated: () => {
                void this.refreshSessions().catch((error) => this.state.patch({ error: formatError(error) }));
            },
            onSessionEvent: (workspaceId, event) => this.liveEvents.applySessionEvent(workspaceId, event),
            onSessionListError: (error) => this.state.patch({ error: error.message }),
            onSessionStreamError: (error) => {
                this.state.patch({ streamConnected: false, liveStatus: error.message });
            },
            onSessionStreamStarted: () => {
                this.state.patch({ streamConnected: true });
            },
            onSessionStreamComplete: () => {
                this.state.patch({ streamConnected: false });
            },
        });
        this.assistantStreamBuffer = new AssistantStreamBufferService({
            renderIntervalMs: ASSISTANT_STREAM_RENDER_INTERVAL_MS,
            canApply: (update) => (this.state.isActiveSessionAddress(update.workspaceId, update.sessionId) &&
                (this.state.getSnapshot().running || this.state.getSnapshot().submitting)),
            apply: (update) => this.liveEvents.applyAssistantStreamUpdate(update),
        });
        this.runStatePoller = new SessionRunStatePollerService({
            intervalMs: RUN_STATE_POLL_INTERVAL_MS,
            getAddress: () => this.runs.resolveRunStatePollAddress(),
            isEnabled: () => this.runs.shouldPollRunState(),
            poll: (address) => this.runs.pollRunState(address),
            onError: (error) => this.state.patch({ error: formatError(error) }),
        });
        this.loader = new ControlPlaneSessionLoader({
            api: this.api,
            state: this.state,
            subscriptions: this.subscriptions,
            assistantStreamBuffer: this.assistantStreamBuffer,
            onRefreshPendingApproval: (sessionId) => this.approvals.refresh(sessionId),
            onError: formatError,
        });
        this.approvals = new ControlPlaneApprovalController({
            api: this.api,
            state: this.state,
            formatError,
        });
        this.liveEvents = new ControlPlaneLiveEventReducer({
            state: this.state,
            loader: this.loader,
            assistantStreamBuffer: this.assistantStreamBuffer,
            refreshSessions: () => this.refreshSessions(),
            refreshPendingApproval: (sessionId) => this.approvals.refresh(sessionId),
        });
        this.directShell = new ControlPlaneDirectShellController({
            api: this.api,
            state: this.state,
            loader: this.loader,
            assistantStreamBuffer: this.assistantStreamBuffer,
            refreshSessions: () => this.refreshSessions(),
            refreshPendingApproval: (sessionId) => this.approvals.refresh(sessionId),
            formatError,
        });
        this.runs = new ControlPlaneRunController({
            api: this.api,
            state: this.state,
            loader: this.loader,
            approvals: this.approvals,
            refreshSessions: () => this.refreshSessions(),
            formatError,
        });
        this.slashCommands = new ControlPlaneSlashCommandController({
            api: this.api,
            state: this.state,
            loader: this.loader,
            formatError,
        });
        this.prompts = new ControlPlanePromptController({
            api: this.api,
            state: this.state,
            loader: this.loader,
            assistantStreamBuffer: this.assistantStreamBuffer,
            slashCommands: this.slashCommands,
            directShell: this.directShell,
            refreshSessions: () => this.refreshSessions(),
            refreshPendingApproval: (sessionId) => this.approvals.refresh(sessionId),
            formatError,
        });
    }
    getSnapshot = () => this.state.getSnapshot();
    subscribe = (listener) => {
        return this.state.subscribe(listener);
    };
    async start(input = {}) {
        this.state.patch({ loading: true, error: undefined });
        try {
            const workspaceId = await this.api.resolveWorkspaceId(input.workspaceId);
            const modelOptions = await this.api.getModelOptions();
            this.state.patch({ workspaceId, modelOptions });
            await this.refreshSlashCommandCatalog(workspaceId);
            this.subscriptions.subscribeToSessionList(workspaceId);
            const sessions = await this.refreshSessions();
            const sessionId = input.sessionId ?? sessions[0]?.id ?? (await this.createSession()).id;
            await this.selectSession(sessionId);
        }
        catch (error) {
            this.state.patch({ error: formatError(error), loading: false });
        }
    }
    dispose() {
        this.subscriptions.dispose();
        this.assistantStreamBuffer.dispose();
        this.runStatePoller.dispose();
    }
    async refreshSessions() {
        return this.loader.refreshSessions();
    }
    async searchWorkspaceFileMentions(query, limit = 20) {
        const workspaceId = this.state.requireWorkspaceId();
        const result = await this.api.searchWorkspaceFiles({ workspaceId, query, limit });
        return result.workspaceId === workspaceId ? result.files : [];
    }
    async createSession(input = {}) {
        return this.loader.createSession(input);
    }
    async selectSession(sessionId) {
        await this.loader.selectSession(sessionId);
    }
    async submitPrompt(prompt) {
        await this.prompts.submitPrompt(prompt);
    }
    getSlashCommandHints(draft) {
        return SlashCommandAutocompleteService.filterHints(draft, this.state.getSnapshot().slashCommandCatalog?.hints ?? []);
    }
    completeSlashCommandDraft(draft) {
        return SlashCommandAutocompleteService.complete(draft, this.state.getSnapshot().slashCommandCatalog?.hints ?? []);
    }
    async selectModelFromPicker(modelId) {
        await this.slashCommands.execute(`/model ${modelId}`);
    }
    async selectSessionFromPicker(sessionId) {
        await this.slashCommands.execute(`/session switch ${sessionId}`);
    }
    async selectReasoningFromPicker(reasoningEffort) {
        await this.slashCommands.execute(reasoningEffort === 'default' ? '/reasoning default' : `/reasoning ${reasoningEffort}`);
    }
    async selectPermissionModeFromPicker(mode) {
        await this.slashCommands.execute(`/permissions ${mode}`);
    }
    async cancelRun() {
        await this.runs.cancelRun();
    }
    async resolvePendingApproval(decision) {
        await this.approvals.resolve(decision);
    }
    toggleCommandResultExpanded() {
        this.state.patch((current) => ({
            commandResultExpanded: current.commandResults.some((result) => result.handled)
                ? !current.commandResultExpanded
                : false,
        }));
    }
    showLocalCommandMessage(message) {
        this.state.patch((current) => ({
            commandResults: [
                ...current.commandResults,
                { handled: true, kind: 'message', message },
            ].slice(-5),
            commandResultExpanded: true,
        }));
    }
    async refreshSlashCommandCatalog(workspaceId) {
        const slashCommandCatalog = await this.api.getSlashCommandCatalog(workspaceId);
        this.state.patch({ slashCommandCatalog });
    }
    async resolveDirectShellConfirmation(accepted) {
        await this.directShell.resolveConfirmation(accepted);
    }
}
function formatError(error) {
    return error instanceof Error ? error.message : String(error);
}
//# sourceMappingURL=control-plane-session-store.js.map