/**
 * Runtime adapter for AWS Fargate
 *
 * Refactor note:
 * - Extracted all internal logic into exported, named functions so they can be unit tested directly.
 * - Removed nested event-handler nesting where possible by introducing readIncomingMessageBody().
 */
import { Env } from '../../config/env.js';
import { Logger } from '../../config/logger.js';
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
import { createServer, } from '../../node-singletons/http.js';
export function createFargateAdapter(config) {
    const logger = config.logger ?? createDefaultFargateLogger();
    const state = {};
    return {
        platform: 'fargate',
        // eslint-disable-next-line @typescript-eslint/require-await
        async handle(_event, _context) {
            // Fargate adapter doesn't handle individual requests
            // Instead, use startServer() to run continuous HTTP server
            throw ErrorFactory.createConfigError('Fargate adapter requires startServer() method. Use RuntimeDetector for automatic initialization.');
        },
        parseRequest(_event) {
            throw ErrorFactory.createConfigError('Fargate adapter uses native Node.js HTTP server');
        },
        formatResponse(_response) {
            throw ErrorFactory.createConfigError('Fargate adapter uses native Node.js HTTP server');
        },
        async startServer(port = 3000, host = '0.0.0.0') {
            return startFargateServer(state, config, logger, port, host);
        },
        async stop() {
            return stopFargateServer(state, logger);
        },
        getLogger() {
            return (logger ?? {
                debug: (msg) => Logger.debug(`[Fargate] ${msg}`),
                info: (msg) => Logger.info(`[Fargate] ${msg}`),
                warn: (msg) => Logger.warn(`[Fargate] ${msg}`),
                error: (msg, err) => Logger.error(`[Fargate] ${msg}`, err?.message),
            });
        },
        supportsPersistentConnections() {
            // Container environments support persistent connections
            return true;
        },
        getEnvironment() {
            return {
                nodeEnv: Env.NODE_ENV,
                runtime: 'fargate',
                dbConnection: Env.DB_CONNECTION || 'sqlite',
                dbHost: Env.DB_HOST,
                dbPort: Env.DB_PORT,
            };
        },
    };
}
/**
 * Fargate/Container adapter for running ZinTrust in AWS Fargate, Cloud Run, or Docker
 * Wraps existing Node.js HTTP server for container orchestration
 * Sealed namespace for immutability
 */
export const FargateAdapter = Object.freeze({
    create: createFargateAdapter,
});
export async function startFargateServer(state, config, logger, port, host, serverFactory = createServer) {
    return new Promise((resolve, reject) => {
        state.server = serverFactory((req, res) => {
            void handleFargateRequest(config, logger, req, res);
        });
        state.server.listen(port, host, () => {
            logger?.info(`Fargate server listening on http://${host}:${port}`);
            resolve();
        });
        state.server.on('error', (error) => {
            logger?.error('Server error', error);
            reject(error);
        });
    });
}
export async function stopFargateServer(state, logger) {
    const server = state.server;
    if (server === undefined)
        return;
    await new Promise((resolve, reject) => {
        server.close((error) => {
            if (error) {
                logger?.error('Error closing server', error);
                reject(error);
                return;
            }
            resolve();
        });
    });
    state.server = undefined;
}
/**
 * Read the full request body (Buffer) for IncomingMessage.
 * Exported for unit testing.
 */
export async function readIncomingMessageBody(req) {
    return new Promise((resolve, reject) => {
        const chunks = [];
        req.on('data', (chunk) => {
            chunks.push(chunk);
        });
        req.on('end', () => {
            resolve(chunks.length === 0 ? null : Buffer.concat(chunks));
        });
        req.on('error', (error) => {
            reject(error);
        });
    });
}
export async function handleFargateRequest(config, logger, req, res) {
    try {
        const body = await readIncomingMessageBody(req);
        try {
            await config.handler(req, res, body);
        }
        catch (error) {
            const err = normalizeError(error);
            Logger.error('Request handler error', err);
            if (res.headersSent === false) {
                res.statusCode = 500;
                res.end('Internal Server Error');
            }
        }
    }
    catch (error) {
        Logger.error('Error reading request body', error);
        const err = normalizeError(error);
        logger?.error('Request error', err);
        if (res.headersSent === false) {
            res.statusCode = 500;
            res.end('Internal Server Error');
        }
    }
}
/**
 * Exported helper for tests (and safer than casting unknown to Error).
 */
export function normalizeError(error) {
    if (error instanceof Error)
        return error;
    if (typeof error === 'string')
        return ErrorFactory.createGeneralError(error);
    return ErrorFactory.createGeneralError('Unknown error', error);
}
export function createDefaultFargateLogger() {
    return {
        debug: (msg, data) => Logger.debug(`[Fargate] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        info: (msg, data) => Logger.info(`[Fargate] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        warn: (msg, data) => Logger.warn(`[Fargate] ${msg}`, data === undefined ? '' : JSON.stringify(data)),
        error: (msg, err) => Logger.error(`[Fargate] ${msg}`, err?.message),
    };
}
