namespace MyOffice.Web.Infrastructure;

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

/// <summary>
/// Returns ProblemDetails for unhandled exceptions (replaces missing /Error page).
/// </summary>
public sealed class UnhandledExceptionHandler : IExceptionHandler
{
	private readonly IHostEnvironment _environment;
	private readonly ILogger<UnhandledExceptionHandler> _logger;
	private readonly ProblemDetailsFactory _problemDetailsFactory;

	public UnhandledExceptionHandler(
		IHostEnvironment environment,
		ILogger<UnhandledExceptionHandler> logger,
		ProblemDetailsFactory problemDetailsFactory
	)
	{
		_environment = environment;
		_logger = logger;
		_problemDetailsFactory = problemDetailsFactory;
	}

	public async ValueTask<bool> TryHandleAsync(
		HttpContext httpContext,
		Exception exception,
		CancellationToken cancellationToken
	)
	{
		_logger.LogError(exception, "Unhandled exception for {Method} {Path}",
			httpContext.Request.Method,
			httpContext.Request.Path);

		var problem = _problemDetailsFactory.CreateProblemDetails(
			httpContext,
			statusCode: StatusCodes.Status500InternalServerError,
			title: "An unexpected error occurred.",
			detail: _environment.IsDevelopment() ? exception.Message : null);

		httpContext.Response.StatusCode = problem.Status ?? StatusCodes.Status500InternalServerError;
		httpContext.Response.ContentType = "application/problem+json";
		await httpContext.Response.WriteAsJsonAsync(problem, cancellationToken);
		return true;
	}
}
