using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;

namespace ERPCore.System.Errors;

/// <summary>
/// Translates <see cref="DomainException"/> into an RFC 7807 ProblemDetails
/// response, preserving the stable domain <c>code</c> as an extension. Non-domain
/// exceptions are left unhandled so the framework returns a 500 ProblemDetails.
/// Registered via AddExceptionHandler and invoked by UseExceptionHandler.
/// </summary>
public sealed class DomainExceptionHandler : IExceptionHandler
{
    private readonly IProblemDetailsService _problemDetails;

    public DomainExceptionHandler(IProblemDetailsService problemDetails)
        => _problemDetails = problemDetails;

    public async ValueTask<bool> TryHandleAsync(
        HttpContext httpContext, Exception exception, CancellationToken cancellationToken)
    {
        if (exception is not DomainException domain)
            return false;

        httpContext.Response.StatusCode = domain.StatusCode;

        return await _problemDetails.TryWriteAsync(new ProblemDetailsContext
        {
            HttpContext = httpContext,
            Exception = domain,
            ProblemDetails = new ProblemDetails
            {
                Status = domain.StatusCode,
                Title = "Domain rule violation",
                Detail = domain.Message,
                Extensions = { ["code"] = domain.Code }
            }
        });
    }
}
