/**
 * Runtime adapter for Deno
 */
import Logger from '../../config/logger.js';
import { createMockHttpObjects, ErrorResponse } from '../RuntimeAdapter.js';
/**
 * Deno runtime adapter for Deno Deploy and edge compute environments
 * Sealed namespace for immutability
 */
export const DenoAdapter = Object.freeze({
    /**
     * Create a new Deno adapter instance
     */
    create(config) {
        const logger = config.logger ?? createDefaultLogger();
        return {
            platform: 'deno',
            async handle(event, context) {
                return handleDenoRequest(this, config, logger, event, context);
            },
            parseRequest(event) {
                return parseDenoRequest(event);
            },
            formatResponse(response) {
                return formatDenoResponse(response);
            },
            getLogger() {
                return logger && Object.keys(logger).length > 0
                    ? logger
                    : {
                        debug: (msg) => Logger.debug(`[Deno] ${msg}`),
                        info: (msg) => Logger.info(`[Deno] ${msg}`),
                        warn: (msg) => Logger.warn(`[Deno] ${msg}`),
                        error: (msg, err) => Logger.error(`[Deno] ${msg}`, err?.message),
                    };
            },
            supportsPersistentConnections() {
                // Deno Deploy isolates are request-scoped
                return false;
            },
            getEnvironment() {
                return getDenoEnvironment();
            },
            async startServer(port = 3000, host = '0.0.0.0') {
                return DenoAdapter.startServer(this, port, host);
            },
        };
    },
    /**
     * Start Deno server for continuous operation
     */
    async startServer(adapter, port = 3000, host = '0.0.0.0') {
        // @ts-ignore - Deno.serve is available in Deno runtime
        await Deno.serve({ port, hostname: host }, async (req) => {
            const platformResponse = await adapter.handle(req);
            return adapter.formatResponse(platformResponse);
        });
    },
    /**
     * Get Deno KV store for caching/secrets
     */
    async getKV() {
        // @ts-ignore - Deno.openKv is available in Deno runtime
        return await Deno.openKv?.();
    },
    /**
     * Get environment variable safely
     */
    getEnvVar(key, defaultValue) {
        // @ts-ignore - Deno.env is available in Deno runtime
        return Deno.env.get?.(key) ?? defaultValue ?? '';
    },
    /**
     * Check if running in Deno Deploy (edge)
     */
    isDeployEnvironment() {
        // @ts-ignore
        return typeof Deno !== 'undefined' && Deno.mainModule?.includes('denoDeploy');
    },
});
/**
 * Handle Deno request
 */
async function handleDenoRequest(adapter, config, logger, event, _context) {
    try {
        const denoRequest = event;
        const request = adapter.parseRequest(denoRequest);
        // Read request body
        const body = denoRequest.method !== 'GET' && denoRequest.method !== 'HEAD'
            ? await denoRequest.arrayBuffer()
            : null;
        // Create mock Node.js request/response for compatibility
        const { req, res, responseData } = createMockHttpObjects(request);
        // Set request timeout
        const timeout = config.timeout ?? 30000;
        const timeoutHandle = setTimeout(() => {
            responseData.statusCode = 504;
            responseData.body = JSON.stringify({
                error: 'Gateway Timeout',
                statusCode: 504,
            });
        }, timeout);
        try {
            // Process through handler with mock Node.js objects
            // Note: In a real implementation, we'd use the handler from the adapter config
            // For compatibility with the existing code structure
            await config.handler(req, res, body === null ? null : Buffer.from(body));
        }
        finally {
            clearTimeout(timeoutHandle);
        }
        logger?.debug('Deno request processed', {
            statusCode: responseData.statusCode,
            path: request.path,
        });
        return responseData;
    }
    catch (error) {
        Logger.error('Deno handler error', error);
        const errorResponse = ErrorResponse.create(500, 'Internal Server Error', 
        // @ts-ignore - Deno is available in Deno runtime
        typeof Deno !== 'undefined' && Deno.env.get('DENO_ENV') === 'development'
            ? { message: error.message }
            : undefined);
        return errorResponse.toResponse();
    }
}
/**
 * Parse Deno request
 */
function parseDenoRequest(event) {
    const url = new URL(event.url);
    const headers = {};
    // Convert Headers to Record
    event.headers.forEach((value, key) => {
        headers[key.toLowerCase()] = value;
    });
    return {
        method: event.method.toUpperCase(),
        path: url.pathname,
        headers,
        query: Object.fromEntries(url.searchParams.entries()),
        remoteAddr: headers['x-forwarded-for']?.toString().split(',')[0] ?? '0.0.0.0',
        signal: event.signal,
    };
}
/**
 * Format Deno response
 */
function formatDenoResponse(response) {
    // Convert to Deno Response format
    const headers = new Headers();
    for (const [key, value] of Object.entries(response.headers)) {
        if (Array.isArray(value)) {
            value.forEach((v) => headers.append(key, v));
        }
        else {
            headers.set(key, value);
        }
    }
    let body = '';
    if (typeof response.body === 'string') {
        body = response.body;
    }
    else if (response.body !== null && response.body !== undefined) {
        body = response.body.toString('utf-8');
    }
    return new Response(body, {
        status: response.statusCode,
        headers,
    });
}
/**
 * Get Deno environment
 */
function getDenoEnvironment() {
    // @ts-ignore - Deno.env is available in Deno runtime
    const env = (typeof Deno === 'undefined' ? {} : Deno.env.toObject?.() ?? {});
    return {
        nodeEnv: (env['DENO_ENV'] ?? 'production'),
        runtime: 'deno',
        dbConnection: env['DB_CONNECTION'] ?? 'postgresql',
        dbHost: env['DB_HOST'],
        dbPort: env['DB_PORT'] ? Number.parseInt(env['DB_PORT'], 10) : undefined,
    };
}
function createDefaultLogger() {
    return {
        debug: (msg, data) => Logger.debug(`[Deno] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        info: (msg, data) => Logger.info(`[Deno] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        warn: (msg, data) => Logger.warn(`[Deno] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        error: (msg, err) => Logger.error(`[Deno] ${msg}`, err?.message),
    };
}
