import { resolveCommand, getCommandsForSurface } from './slash-command-registry.js';
export class SlashCommandService {
    sessions;
    compactionService;
    constructor(sessions, compactionService) {
        this.sessions = sessions;
        this.compactionService = compactionService;
    }
    parse(raw) {
        const trimmed = raw.trim();
        if (!trimmed.startsWith('/')) {
            return undefined;
        }
        const parts = trimmed.slice(1).split(/\s+/);
        const name = parts[0].toLowerCase();
        const command = resolveCommand(`/${name}`);
        if (!command) {
            return undefined;
        }
        return {
            command,
            args: parts.slice(1),
            raw,
        };
    }
    async execute(input, ctx, handler) {
        const { command, args } = input;
        switch (command) {
            case 'help':
                return this.buildHelpResult(ctx.surface);
            case 'sessions':
                return this.buildSessionsResult(ctx);
            case 'resume':
                return this.executeResume(args, ctx, handler);
            case 'delete':
                return this.executeDelete(args, ctx, handler);
            case 'new':
                return this.executeNew(ctx, handler);
            case 'reset':
                return this.executeNew(ctx, handler);
            case 'checkpoints':
                return this.buildCheckpointsResult(ctx);
            case 'save':
                return this.executeSaveCheckpoint(ctx);
            case 'restore':
                return this.executeRestore(args, ctx, handler);
            case 'checkpoint_delete':
                return this.executeDeleteCheckpoint(args, ctx);
            case 'pending':
                return { kind: 'ok', message: 'Use the pending actions display in the UI.' };
            case 'approve':
                if (!handler.approvePendingPermissions) {
                    return { kind: 'unsupported_in_surface', message: '/approve is not available in this surface.' };
                }
                return this.executeApprove(handler);
            case 'compact':
                return { kind: 'ok', message: 'Compaction runs automatically when needed.' };
            case 'open': {
                return { kind: 'error', message: '/open requires a recent workflow. No workflow available.' };
            }
            case 'toggle_thinking': {
                if (handler.setDisplayOptions) {
                    const current = handler.getDisplayOptions?.() ?? { showThinking: true };
                    handler.setDisplayOptions({ showThinking: !current.showThinking });
                    return { kind: 'ok', message: `Thinking display ${!current.showThinking ? 'hidden' : 'visible'}.` };
                }
                return { kind: 'unsupported_in_surface', message: '/toggle_thinking is not available in this surface.' };
            }
            case 'toggle_cli': {
                if (handler.setDisplayOptions) {
                    const current = handler.getDisplayOptions?.() ?? { showExecution: true };
                    handler.setDisplayOptions({ showExecution: !current.showExecution });
                    return { kind: 'ok', message: `Command executions display ${!current.showExecution ? 'hidden' : 'visible'}.` };
                }
                return { kind: 'unsupported_in_surface', message: '/toggle_cli is not available in this surface.' };
            }
            case 'stop':
                return { kind: 'ok', message: 'Stop signalled. Finish current operation and wait for it to complete.' };
            case 'exit':
                return { kind: 'ok', message: '/exit' };
            default:
                return { kind: 'unknown_command', message: `Unknown command: /${command}` };
        }
    }
    buildHelpResult(surface) {
        const commands = getCommandsForSurface(surface);
        const lines = commands.map((c) => `${c.usage.padEnd(32)} — ${c.description}${c.aliases.length > 0 ? ` (alias: ${c.aliases.map((a) => `/${a}`).join(', ')})` : ''}`);
        return {
            kind: 'ok',
            message: `Available commands:\n${lines.join('\n')}`,
            data: { commands },
        };
    }
    async executeApprove(handler) {
        const approvedCount = await handler.approvePendingPermissions?.();
        if (!approvedCount) {
            return { kind: 'ok', message: 'No permissions pending.', data: { approvedCount: 0 } };
        }
        return {
            kind: 'ok',
            message: `Permission granted for ${approvedCount} action(s).`,
            data: {
                approvedCount,
                resumePrompt: 'Permission granted. Continue the current task and execute the previously blocked step now.',
            },
        };
    }
    buildSessionsResult(ctx) {
        const scope = { kind: ctx.surface, key: ctx.sessionId };
        const sessions = this.sessions.listForScope(scope);
        const activeId = this.sessions.getActiveForScope(scope)?.id;
        if (sessions.length === 0) {
            return { kind: 'ok', message: 'No sessions found.', data: { sessions: [] } };
        }
        const entries = sessions.map((s) => ({
            id: s.id,
            title: s.title,
            createdAt: s.createdAt,
            updatedAt: s.updatedAt,
            isActive: s.id === activeId,
            isClosed: Boolean(s.closedAt),
        }));
        const lines = entries.map((e) => {
            const activeMarker = e.isActive ? ' [ACTIVE]' : '';
            const closedMarker = e.isClosed ? ' [CLOSED]' : '';
            const date = new Date(e.updatedAt).toLocaleString();
            return `${e.id}  "${e.title}"${activeMarker}${closedMarker}  ${date}`;
        });
        return {
            kind: 'ok',
            message: `Sessions:\n${lines.join('\n')}`,
            data: { sessions: entries },
        };
    }
    executeResume(args, ctx, handler) {
        if (args.length === 0) {
            return { kind: 'invalid_arguments', message: 'Usage: /resume <session_id>' };
        }
        const targetId = args[0];
        const session = this.sessions.get(targetId);
        if (!session) {
            return { kind: 'session_not_found', message: `Session not found: ${targetId}` };
        }
        const scope = { kind: ctx.surface, key: ctx.sessionId };
        this.sessions.ensure(targetId, { scope });
        handler.resumeSession(scope, targetId);
        handler.resetLocalState();
        return {
            kind: 'ok',
            message: `Resumed session: "${session.title}" (${targetId})`,
            data: { sessionId: targetId },
        };
    }
    executeDelete(args, ctx, handler) {
        if (args.length === 0) {
            return { kind: 'invalid_arguments', message: 'Usage: /delete <session_id>' };
        }
        const targetId = args[0];
        const session = this.sessions.get(targetId);
        if (!session) {
            return { kind: 'session_not_found', message: `Session not found: ${targetId}` };
        }
        const scope = { kind: ctx.surface, key: ctx.sessionId };
        const activeSession = this.sessions.getActiveForScope(scope);
        const isActive = activeSession?.id === targetId;
        this.sessions.delete(targetId).catch(() => { });
        if (isActive) {
            const fresh = this.sessions.rotateForScope(scope, { title: 'New conversation' });
            handler.resumeSession(scope, fresh.id);
            handler.resetLocalState();
        }
        return {
            kind: 'ok',
            message: `Session deleted: "${session.title}" (${targetId})${isActive ? '. Started new session.' : ''}`,
            data: { deletedId: targetId, newActiveId: isActive ? this.sessions.getActiveForScope(scope)?.id : undefined },
        };
    }
    executeNew(ctx, handler) {
        const scope = { kind: ctx.surface, key: ctx.sessionId };
        const fresh = this.sessions.rotateForScope(scope, { title: 'New conversation' });
        handler.resumeSession(scope, fresh.id);
        handler.resetLocalState();
        return {
            kind: 'ok',
            message: `New session started: ${fresh.id}`,
            data: { sessionId: fresh.id },
        };
    }
    buildCheckpointsResult(ctx) {
        const checkpoints = this.sessions.listCheckpointsSync(ctx.threadId);
        if (checkpoints.length === 0) {
            return { kind: 'ok', message: 'No checkpoints saved for this session.', data: { checkpoints: [] } };
        }
        const entries = checkpoints.map((cp) => ({
            id: cp.id,
            sessionId: cp.sessionId,
            createdAt: cp.createdAt,
            messageCount: cp.messageCount,
            summary: cp.summary,
        }));
        const lines = checkpoints.map((cp, i) => `${i + 1}. ${cp.id} — ${new Date(cp.createdAt).toLocaleString()} — ${cp.messageCount} msgs`);
        return {
            kind: 'ok',
            message: `Checkpoints:\n${lines.join('\n')}`,
            data: { checkpoints: entries },
        };
    }
    async executeSaveCheckpoint(ctx) {
        try {
            const compactionState = this.compactionService.getState(ctx.threadId);
            const checkpoint = await this.sessions.saveCheckpoint(ctx.threadId, { compactionState });
            return {
                kind: 'ok',
                message: `Checkpoint saved: ${checkpoint.id}`,
                data: { checkpointId: checkpoint.id },
            };
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return { kind: 'error', message: `Failed to save checkpoint: ${message}` };
        }
    }
    async executeRestore(args, ctx, handler) {
        if (args.length === 0) {
            return { kind: 'invalid_arguments', message: 'Usage: /restore <checkpoint_id>' };
        }
        const checkpointId = args[0];
        try {
            const result = await this.sessions.restoreCheckpoint(ctx.threadId, checkpointId);
            if (result.compactionState) {
                this.compactionService.setState(ctx.threadId, result.compactionState);
            }
            else {
                this.compactionService.reset(ctx.threadId);
            }
            handler.resetLocalState();
            return {
                kind: 'ok',
                message: `Checkpoint ${checkpointId} restored. Feed cleared. Resume your conversation.`,
                data: { checkpointId },
            };
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return { kind: 'checkpoint_not_found', message: `Failed to restore checkpoint: ${message}` };
        }
    }
    async executeDeleteCheckpoint(args, ctx) {
        if (args.length === 0) {
            return { kind: 'invalid_arguments', message: 'Usage: /checkpoint_delete <checkpoint_id>' };
        }
        const checkpointId = args[0];
        try {
            await this.sessions.deleteCheckpoint(ctx.threadId, checkpointId);
            return { kind: 'ok', message: `Checkpoint deleted: ${checkpointId}` };
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            return { kind: 'error', message: `Failed to delete checkpoint: ${message}` };
        }
    }
}
//# sourceMappingURL=slash-command-service.js.map