// Ignore Spelling: Middlewares
using AsbCloudApp.Exceptions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace AsbCloudWebApi.Middlewares;

public class SimplifyExceptionsMiddleware
{
    private readonly RequestDelegate next;

    public SimplifyExceptionsMiddleware(RequestDelegate next)
    {
        this.next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await next.Invoke(context);
        }
        catch (ArgumentInvalidException ex)
        {
            Console.WriteLine($"ArgumentException in {context.Request.Method}: {ex.Message}");
            context.Response.Clear();
            context.Response.StatusCode = 400;
            context.Response.ContentType = "application/json";
            var body = MakeJsonBody(ex);
            await context.Response.WriteAsync(body);
        }
        catch (ForbidException ex)
        {
            Console.WriteLine($"ForbidException in {context.Request.Method}: {ex.Message}");
            context.Response.Clear();
            context.Response.StatusCode = 403;
        }
        catch (OperationCanceledException ex)
        {
            Console.WriteLine(ex.Message);
        }
        catch (Exception ex) // TODO: find explicit exception. Use Trace. Add body size to message.
        {
            if (context.Response.HasStarted)
                throw;

            context.Response.Clear();
            context.Response.StatusCode = 500;
            
            if (ex.Message.Contains("Reading the request body timed out due to data arriving too slowly. See MinRequestBodyDataRate."))
                Console.WriteLine("Reading the request body timed out due to data arriving too slowly.");
            else
                throw;
        }
    }

    private static string MakeJsonBody(ArgumentInvalidException ex)
    {
        var problem = new ValidationProblemDetails(ex.ErrorState);
        var buffer = System.Text.Json.JsonSerializer.Serialize(problem);
        return buffer;
    }
}