"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createDemoRouter = exports.resolveUserId = void 0;
const express_1 = require("express");
const index_core_1 = require("../index-core");
const ConfigManager_1 = require("../services/ConfigManager");
const log = (0, index_core_1.createLogger)('DemoRoutes');
const toIso = (timestamp) => new Date(timestamp).toISOString();
const normalizeUserKey = (value) => value.trim().toLowerCase();
const resolveUserId = async (authHeader, requireSignedInUsers) => {
    const configManager = (0, ConfigManager_1.getConfigManager)();
    const headerToken = authHeader && authHeader.startsWith('Bearer ')
        ? authHeader.slice('Bearer '.length).trim()
        : '';
    const requestScopedToken = configManager.getAuthToken() ?? '';
    const token = headerToken || requestScopedToken;
    if (!token) {
        if (requireSignedInUsers) {
            throw new Error('Authentication required');
        }
        return 'anonymous';
    }
    const proxyUrl = configManager.getProxyUrl();
    const response = await fetch(`${proxyUrl}/api/user/profile`, {
        method: 'GET',
        headers: {
            Authorization: `Bearer ${token}`,
            'Content-Type': 'application/json',
        },
        signal: AbortSignal.timeout(3_000),
    });
    if (!response.ok) {
        throw new Error('Authentication required');
    }
    const payload = (await response.json());
    const email = payload.user?.email;
    const id = payload.user?.id;
    if (email) {
        return normalizeUserKey(email);
    }
    if (id) {
        return normalizeUserKey(id);
    }
    return normalizeUserKey('signed-in-user');
};
exports.resolveUserId = resolveUserId;
const createDemoRouter = (sessionManager, options) => {
    const router = (0, express_1.Router)();
    router.post('/demo/session', async (req, res) => {
        const startedAt = Date.now();
        options.telemetry?.trackTryoutSessionProvisionStarted({
            isAuthenticatedRequest: Boolean(req.headers.authorization?.startsWith('Bearer ')),
            requireSignedInUsers: options.requireSignedInUsers,
            deploymentEnv: options.deploymentEnv,
            templateProject: sessionManager.getTemplateProjectPath(),
        });
        try {
            const userId = await (0, exports.resolveUserId)(req.headers.authorization, options.requireSignedInUsers);
            const existingSessionId = options.getActiveDemoSessionIdForRequest?.(req) ?? null;
            if (existingSessionId) {
                const existingSession = sessionManager.getSession(existingSessionId);
                if (existingSession) {
                    if (existingSession.userId !== userId) {
                        options.clearActiveDemoSessionIdForRequest?.(req, res);
                        res.status(403).json({ error: 'Session access denied' });
                        return;
                    }
                    res.json({
                        sessionId: existingSession.sessionId,
                        sessionUrl: sessionManager.getSessionUrl(existingSession.sessionId),
                        createdAt: toIso(existingSession.createdAt),
                        expiresAt: toIso(existingSession.expiresAt),
                    });
                    return;
                }
                options.clearActiveDemoSessionIdForRequest?.(req, res);
            }
            const session = await sessionManager.createSession(userId);
            options.storeActiveDemoSessionIdForRequest?.(req, res, session.sessionId);
            options.telemetry?.trackTryoutSessionProvisionCompleted({
                demoSessionId: session.sessionId,
                timeToReadyMs: Date.now() - startedAt,
                activeSessionsAfter: sessionManager.getActiveSessionCount(),
                deploymentEnv: options.deploymentEnv,
                templateProject: sessionManager.getTemplateProjectPath(),
            });
            res.json({
                sessionId: session.sessionId,
                sessionUrl: session.sessionUrl,
                createdAt: toIso(session.createdAt),
                expiresAt: toIso(session.expiresAt),
            });
        }
        catch (error) {
            const message = error instanceof Error ? error.message : 'Failed to create session';
            let statusCode = 500;
            if (message === 'Authentication required') {
                statusCode = 401;
            }
            else if (message.includes('Maximum active demo sessions reached') ||
                message.includes('Rate limit exceeded')) {
                statusCode = 429;
            }
            options.telemetry?.trackTryoutSessionProvisionFailed({
                errorType: message,
                statusCode,
                timeToFailureMs: Date.now() - startedAt,
                deploymentEnv: options.deploymentEnv,
                templateProject: sessionManager.getTemplateProjectPath(),
            });
            log.warn('Failed to create hosted demo session', error);
            res.status(statusCode).json({ error: message });
        }
    });
    router.get('/demo/session/:sessionId', (req, res) => {
        const session = sessionManager.getSession(req.params.sessionId);
        const sendFailure = (statusCode, error) => {
            res.status(statusCode).json({ error });
        };
        if (options.requireSignedInUsers) {
            void (0, exports.resolveUserId)(req.headers.authorization, true)
                .then((userId) => {
                if (!session) {
                    options.telemetry?.trackTryoutSessionMetadataRequested({
                        demoSessionId: req.params.sessionId,
                        found: false,
                        deploymentEnv: options.deploymentEnv,
                    });
                    sendFailure(404, 'Session not found');
                    return;
                }
                if (session.userId !== userId) {
                    options.telemetry?.trackTryoutSessionMetadataRequested({
                        demoSessionId: req.params.sessionId,
                        found: false,
                        deploymentEnv: options.deploymentEnv,
                    });
                    sendFailure(403, 'Session access denied');
                    return;
                }
                options.telemetry?.trackTryoutSessionMetadataRequested({
                    demoSessionId: req.params.sessionId,
                    found: true,
                    deploymentEnv: options.deploymentEnv,
                });
                res.json({
                    sessionId: session.sessionId,
                    createdAt: toIso(session.createdAt),
                    expiresAt: toIso(session.expiresAt),
                });
            })
                .catch(() => {
                options.telemetry?.trackTryoutSessionMetadataRequested({
                    demoSessionId: req.params.sessionId,
                    found: false,
                    deploymentEnv: options.deploymentEnv,
                });
                sendFailure(401, 'Authentication required');
            });
            return;
        }
        options.telemetry?.trackTryoutSessionMetadataRequested({
            demoSessionId: req.params.sessionId,
            found: Boolean(session),
            deploymentEnv: options.deploymentEnv,
        });
        if (!session) {
            res.status(404).json({ error: 'Session not found' });
            return;
        }
        res.json({
            sessionId: session.sessionId,
            createdAt: toIso(session.createdAt),
            expiresAt: toIso(session.expiresAt),
        });
    });
    return router;
};
exports.createDemoRouter = createDemoRouter;
//# sourceMappingURL=demo.js.map