using System.Text.Json;
using FlatRender.ContentSvc.Models.Responses;

namespace FlatRender.ContentSvc.Middleware;

public class ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> logger)
{
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
    };

    public async Task InvokeAsync(HttpContext ctx)
    {
        try
        {
            await next(ctx);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Unhandled exception");
            await WriteError(ctx, ex);
        }
    }

    private static Task WriteError(HttpContext ctx, Exception ex)
    {
        var (status, code) = ex switch
        {
            KeyNotFoundException => (404, "not_found"),
            UnauthorizedAccessException => (401, "unauthorized"),
            InvalidOperationException => (400, "invalid_operation"),
            ArgumentException => (400, "bad_request"),
            NotImplementedException => (501, "not_implemented"),
            _ => (500, "internal_error")
        };

        ctx.Response.StatusCode = status;
        ctx.Response.ContentType = "application/json";

        var error = new { error = new ApiError(code, ex.Message, ctx.TraceIdentifier) };
        return ctx.Response.WriteAsync(JsonSerializer.Serialize(error, JsonOptions));
    }
}
