namespace CareFix.Api.Infrastructure; /// An error whose message is safe to show to the user. public sealed class AppException(int status, string message, string? code = null) : Exception(message) { public int Status { get; } = status; public string? Code { get; } = code; public static AppException BadRequest(string m) => new(400, m); public static AppException NotFound(string m) => new(404, m); public static AppException Forbidden(string m) => new(403, m); public static AppException Conflict(string m) => new(409, m); } public sealed class ErrorMiddleware(RequestDelegate next, ILogger log) { public async Task Invoke(HttpContext ctx) { try { await next(ctx); } catch (AppException ex) { if (ctx.Response.HasStarted) throw; ctx.Response.StatusCode = ex.Status; await ctx.Response.WriteAsJsonAsync(new { error = ex.Message, code = ex.Code }); } catch (CareFix.Core.OpsException ex) { if (ctx.Response.HasStarted) throw; ctx.Response.StatusCode = ex.Status; await ctx.Response.WriteAsJsonAsync(new { error = ex.Message }); } catch (Exception ex) { log.LogError(ex, "Unhandled error on {Path}", ctx.Request.Path); if (ctx.Response.HasStarted) throw; ctx.Response.StatusCode = 500; await ctx.Response.WriteAsJsonAsync(new { error = "Unexpected server error. The details are in the server log." }); } } }