import { normalizeTerminalLayoutState } from '../../shared/layoutState.js';
import { requireAllowedOrigin } from './authRoutes.js';
import { authenticateTerminalRequest } from './terminalRoutes.js';
class RevisionConflict extends Error {
    current;
    constructor(current) {
        super('Stale terminal layout revision');
        this.current = current;
    }
}
export async function registerTerminalLayoutRoutes(app, config, services) {
    // Local server layout.
    app.get('/api/terminal-layout', async (request, reply) => {
        const auth = await authenticateTerminalRequest(services.authService, request, reply);
        if (!auth) {
            return reply;
        }
        const state = await services.fileStore.read();
        return terminalLayoutResponse(state.terminalLayout);
    });
    app.put('/api/terminal-layout', { preHandler: (request, reply) => requireAllowedOrigin(config, request, reply) }, async (request, reply) => saveLayout(services, request, reply, {
        read: (state) => state.terminalLayout,
        write: (state, layout) => ({ ...state, terminalLayout: layout })
    }));
    // Per-agent layout, stored on the main (not proxied to the agent).
    app.get('/api/agents/:agentId/terminal-layout', async (request, reply) => {
        const auth = await authenticateTerminalRequest(services.authService, request, reply);
        if (!auth) {
            return reply;
        }
        const state = await services.fileStore.read();
        if (!state.agents.some((agent) => agent.id === request.params.agentId)) {
            return reply.code(404).send({ error: 'agent_not_found' });
        }
        return terminalLayoutResponse(state.agentLayouts[request.params.agentId] ?? null);
    });
    app.put('/api/agents/:agentId/terminal-layout', { preHandler: (request, reply) => requireAllowedOrigin(config, request, reply) }, async (request, reply) => {
        const auth = await authenticateTerminalRequest(services.authService, request, reply);
        if (!auth) {
            return reply;
        }
        const agentId = request.params.agentId;
        const state = await services.fileStore.read();
        if (!state.agents.some((agent) => agent.id === agentId)) {
            return reply.code(404).send({ error: 'agent_not_found' });
        }
        return saveLayout(services, request, reply, {
            read: (current) => current.agentLayouts[agentId] ?? null,
            write: (current, layout) => ({ ...current, agentLayouts: { ...current.agentLayouts, [agentId]: layout } })
        });
    });
}
async function saveLayout(services, request, reply, slot) {
    const auth = await authenticateTerminalRequest(services.authService, request, reply);
    if (!auth) {
        return reply;
    }
    const body = parseUpdateRequest(request.body);
    if (!body) {
        return reply.code(400).send({ error: 'invalid_terminal_layout' });
    }
    try {
        const next = await services.fileStore.update((state) => {
            const currentRevision = slot.read(state)?.revision ?? 0;
            if (body.baseRevision !== undefined && body.baseRevision !== currentRevision) {
                throw new RevisionConflict(slot.read(state));
            }
            const layout = {
                layout: body.layout,
                revision: currentRevision + 1,
                updatedAt: new Date().toISOString()
            };
            return slot.write(state, layout);
        });
        return terminalLayoutResponse(slot.read(next));
    }
    catch (error) {
        if (error instanceof RevisionConflict) {
            return reply.code(409).send(terminalLayoutResponse(error.current));
        }
        throw error;
    }
}
function parseUpdateRequest(value) {
    if (!value || typeof value !== 'object') {
        return null;
    }
    const request = value;
    const layout = normalizeTerminalLayoutState(request.layout);
    if (!layout) {
        return null;
    }
    if (request.baseRevision !== undefined && (!Number.isInteger(request.baseRevision) || request.baseRevision < 0)) {
        return null;
    }
    return request.baseRevision === undefined ? { layout } : { layout, baseRevision: request.baseRevision };
}
function terminalLayoutResponse(stored) {
    if (!stored) {
        return { layout: null, revision: 0, updatedAt: null };
    }
    return {
        layout: stored.layout,
        revision: stored.revision,
        updatedAt: stored.updatedAt
    };
}
//# sourceMappingURL=terminalLayoutRoutes.js.map