/**
 * Server - HTTP Server implementation
 * Uses Node.js built-in HTTP server with no external dependencies
 */
import { appConfig } from '../config/app.js';
import { HTTP_HEADERS } from '../config/constants.js';
import { Logger } from '../config/logger.js';
import { ServiceContainer } from '../container/ServiceContainer.js';
import { ErrorRouting } from '../routes/error.js';
import { ErrorFactory } from '../exceptions/ZintrustError.js';
import { Kernel } from '../http/Kernel.js';
import { Request } from '../http/Request.js';
import { Response } from '../http/Response.js';
import * as http from '../node-singletons/http.js';
/**
 * Set security headers on response
 */
const getContentSecurityPolicyForPath = () => {
    // Default CSP for the API/framework
    return ("default-src 'self'; " +
        "script-src 'self' 'unsafe-inline'; " +
        "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
        "style-src-elem 'self' 'unsafe-inline' https://fonts.googleapis.com; " +
        "img-src 'self' data:; " +
        "font-src 'self' https://fonts.gstatic.com;");
};
const setSecurityHeaders = (res, contentType) => {
    res.setHeader(HTTP_HEADERS.X_POWERED_BY, 'ZinTrust');
    res.setHeader(HTTP_HEADERS.X_CONTENT_TYPE_OPTIONS, 'nosniff');
    res.setHeader(HTTP_HEADERS.X_FRAME_OPTIONS, 'DENY');
    res.setHeader(HTTP_HEADERS.X_XSS_PROTECTION, '1; mode=block');
    res.setHeader(HTTP_HEADERS.REFERRER_POLICY, 'strict-origin-when-cross-origin');
    // Only apply CSP to HTML responses, not API endpoints
    // eslint-disable-next-line @typescript-eslint/prefer-optional-chain
    if (contentType !== undefined && contentType !== null && contentType.includes('text/html')) {
        res.setHeader(HTTP_HEADERS.CONTENT_SECURITY_POLICY, getContentSecurityPolicyForPath());
    }
};
const handleRequest = async (params, req, res) => {
    let request;
    let response;
    try {
        const contentType = req?.headers['content-type'];
        setSecurityHeaders(res, contentType);
        if (!req) {
            throw ErrorFactory.createConnectionError('Request object is missing');
        }
        const kernel = params.getKernel();
        request = Request.create(req);
        response = Response.create(res);
        // Delegate request lifecycle to Kernel (routing + middleware + handler execution).
        await kernel.handleRequest(request, response);
    }
    catch (error) {
        ErrorFactory.createTryCatchError('Server error:', error);
        // Prefer wrapper-based error handling when available.
        if (request !== undefined && response !== undefined) {
            ErrorRouting.handleInternalServerErrorWithWrappers(request, response, error);
            return;
        }
        ErrorRouting.handleInternalServerErrorRaw(res);
    }
};
/**
 * Server - HTTP Server implementation
 * Refactored to Functional Object pattern
 */
export const Server = Object.freeze({
    /**
     * Create a new server instance
     */
    create(app, port, host, kernel = null) {
        const serverPort = port ?? appConfig.port;
        const serverHost = host ?? appConfig.host;
        let kernelInstance = kernel;
        const getKernel = () => {
            if (kernelInstance !== null)
                return kernelInstance;
            const anyApp = app;
            const container = typeof anyApp.getContainer === 'function'
                ? anyApp.getContainer()
                : ServiceContainer.create();
            kernelInstance = Kernel.create(app.getRouter(), container);
            return kernelInstance;
        };
        const httpServer = http.createServer(async (req, res) => handleRequest({ getKernel }, req, res));
        const sockets = new Set();
        httpServer.on('connection', (socket) => {
            sockets.add(socket);
            socket.on('close', () => sockets.delete(socket));
        });
        return {
            async listen() {
                return new Promise((resolve) => {
                    httpServer.listen(serverPort, serverHost, () => {
                        resolve();
                    });
                });
            },
            async close() {
                return new Promise((resolve) => {
                    httpServer.close(() => {
                        Logger.info('ZinTrust server stopped');
                        resolve();
                    });
                    // Ensure keep-alive / hanging connections don't block shutdown
                    for (const socket of sockets) {
                        try {
                            socket.destroy();
                        }
                        catch {
                            // best-effort
                        }
                    }
                });
            },
            getHttpServer() {
                return httpServer;
            },
        };
    },
});
export default Server;
