import { Env } from '../config/env.js';
import { Logger } from '../config/logger.js';
import ErrorRouting from '../routes/error.js';
import { ErrorResponse } from '../http/ErrorResponse.js';
import { RequestContext } from '../http/RequestContext.js';
import { respondWithMiddlewareFailure, } from './MiddlewareFailureResponder.js';
const isWritableEnded = (res) => {
    if (typeof res.getRaw !== 'function')
        return false;
    const raw = res.getRaw();
    if (typeof raw !== 'object' || raw === null)
        return false;
    if (!('writableEnded' in raw))
        return false;
    return Boolean(raw.writableEnded);
};
const shouldHideStackFromResponse = (error) => {
    if (typeof error !== 'object' || error === null)
        return false;
    const candidate = error;
    return (candidate.name === 'NotFoundError' ||
        candidate.code === 'NOT_FOUND' ||
        candidate.statusCode === 404);
};
export const ErrorHandlerMiddleware = Object.freeze({
    create(options = {}) {
        return async (req, res, next) => {
            try {
                await next();
            }
            catch (error) {
                Logger.error('Unhandled request error:', error);
                const requestId = RequestContext.get(req)?.requestId ?? req.context['requestId'];
                const includeStack = Env.NODE_ENV !== 'production' && !shouldHideStackFromResponse(error);
                if (!isWritableEnded(res)) {
                    const errorMode = Env.get('ERROR_MODE', 'html');
                    res.setStatus(500);
                    if (errorMode === 'html') {
                        // Use HTML error page instead of JSON
                        const handleInternalServerErrorWithWrappers = ErrorRouting.handleInternalServerErrorWithWrappers;
                        await handleInternalServerErrorWithWrappers(req, res, error, requestId);
                    }
                    else {
                        const body = ErrorResponse.internalServerError('Internal server error', requestId, includeStack ? error?.stack : undefined);
                        await respondWithMiddlewareFailure(req, res, options.onFailure, {
                            middleware: 'error',
                            reason: 'unhandled_exception',
                            statusCode: 500,
                            message: 'Internal server error',
                            body,
                            error,
                            requestId,
                        });
                    }
                }
            }
        };
    },
});
export default ErrorHandlerMiddleware;
