using Microsoft.AspNetCore.Diagnostics;

namespace Web.Api.Common;

internal sealed class GlobalExceptionHandler(ILogger<GlobalExceptionHandler> logger) : IExceptionHandler
{
    public async ValueTask<bool> TryHandleAsync(
        HttpContext httpContext,
        Exception exception,
        CancellationToken cancellationToken
    ) {
        var (statusCode, message) = exception switch
        {
            BadHttpRequestException => (StatusCodes.Status400BadRequest, "Invalid request body"),
            KeyNotFoundException => (StatusCodes.Status404NotFound, exception.Message),
            InvalidOperationException => (StatusCodes.Status400BadRequest, exception.Message),
            UnauthorizedAccessException => (StatusCodes.Status401Unauthorized, exception.Message),
            // 내부 예외 메시지(EF Core/SQL 등)가 클라이언트로 노출되지 않도록 일반 메시지로 응답. 상세는 아래 LogError 로만 기록.
            _ => (StatusCodes.Status500InternalServerError, "요청 처리 중 오류가 발생했습니다.")
        };

        if (statusCode == StatusCodes.Status500InternalServerError)
        {
            logger.LogError(exception, "Unhandled exception occurred");
        }
        else
        {
            logger.LogWarning(exception, "Handled exception: {Message}", exception.Message);
        }

        httpContext.Response.StatusCode = statusCode;
        httpContext.Response.ContentType = "application/json";

        await httpContext.Response.WriteAsJsonAsync(new ApiResponse
        {
            Success = false,
            Status = statusCode,
            Message = message
        }, cancellationToken);

        return true;
    }
}