public class ExceptionHandlerMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ExceptionHandlerMiddleware> _logger;

    public ExceptionHandlerMiddleware(RequestDelegate next, ILogger<ExceptionHandlerMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (NotFoundException ex)
        {
            _logger.LogWarning("{Message}", ex.Message);
            await WriteAsync(context, StatusCodes.Status404NotFound,
                ApiResponse<object>.Fail(StatusCodes.Status404NotFound, ex.Message, ex.ErrorCode));
        }
        catch (BadRequestException ex)
        {
            _logger.LogWarning("{Message}", ex.Message);
            await WriteAsync(context, StatusCodes.Status400BadRequest,
                ApiResponse<object>.Fail(StatusCodes.Status400BadRequest, ex.Message, ex.ErrorCode));
        }
        catch (ValidationException ex)
        {
            _logger.LogWarning("{Message}", ex.Message);
            await WriteAsync(context, StatusCodes.Status422UnprocessableEntity,
                ApiResponse<object>.Fail(StatusCodes.Status422UnprocessableEntity, ex.Message, ex.ErrorCode));
        }
        catch (ConflictException ex)
        {
            _logger.LogWarning("{Message}", ex.Message);
            await WriteAsync(context, StatusCodes.Status409Conflict,
                ApiResponse<object>.Fail(StatusCodes.Status409Conflict, ex.Message, ex.ErrorCode));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Unhandled exception");
            await WriteAsync(context, StatusCodes.Status500InternalServerError,
                ApiResponse<object>.Fail(StatusCodes.Status500InternalServerError,
                    "An unexpected error occurred", "INTERNAL_ERROR"));
        }
    }

    private static async Task WriteAsync<T>(HttpContext context, int status, ApiResponse<T> body)
    {
        context.Response.StatusCode = status;
        await context.Response.WriteAsJsonAsync(body);
    }
}
