using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using System.Net;
using System.Text.Json;

namespace DigitalData.Core.Exceptions.Middleware;

public record HttpExceptionHandler(Type ExceptionType, Func<HttpContext, Exception, ILogger?, Task> HandleExceptionAsync)
{
    #region Alternative generator methods
    public static HttpExceptionHandler Create<TException>(Func<HttpContext, Exception, ILogger?, Task> HandleExceptionAsync) where TException : Exception
        => new HttpExceptionHandler(typeof(TException), HandleExceptionAsync);

    public static HttpExceptionHandler Create<TException>(HttpStatusCode statusCode, Func<Exception, string> messageFactory) where TException : Exception
        => Create<TException>(
        async (context, ex, logger) =>
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)statusCode;
            var message = messageFactory(ex);
            await context.Response.WriteAsync(JsonSerializer.Serialize(new { message }));
        }
    );
    #endregion

    #region Default handlers
    public static readonly Func<Exception, string> DefaultMessageFactory = ex => ex.Message;

    public static HttpExceptionHandler DefaultBadRequest => Create<BadRequestException>(HttpStatusCode.BadRequest, DefaultMessageFactory);

    public static HttpExceptionHandler DefaultNotFound => Create<NotFoundException>(HttpStatusCode.NotFound, DefaultMessageFactory);

    public static HttpExceptionHandler Default => Create<Exception>(
        async (context, ex, logger) =>
        {
            context.Response.ContentType = "application/json";
            context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            var message = "An unexpected error occurred.";
            await context.Response.WriteAsync(JsonSerializer.Serialize(new { message }));
        });
    #endregion
};