using System.Security.Claims;
using Jiaowu.Api.Domain.System;
using Jiaowu.Api.Infrastructure.Persistence;

namespace Jiaowu.Api.Infrastructure.Middleware;

public sealed class AuditMiddleware(RequestDelegate next)
{
    public async Task InvokeAsync(HttpContext context, AppDbContext db)
    {
        await next(context);

        if (HttpMethods.IsGet(context.Request.Method) ||
            context.Request.Path.StartsWithSegments("/swagger"))
        {
            return;
        }

        // A failed business write can leave invalid tracked entities in this request scope.
        // Audit persistence must not retry those entities and replace the original response.
        db.ChangeTracker.Clear();
        db.AuditLogs.Add(new AuditLog
        {
            UserId = Guid.TryParse(
                context.User.FindFirstValue(ClaimTypes.NameIdentifier),
                out var userId)
                ? userId
                : null,
            UserName = context.User.Identity?.Name,
            Method = context.Request.Method,
            Path = context.Request.Path,
            StatusCode = context.Response.StatusCode,
            IpAddress = context.Connection.RemoteIpAddress?.ToString()
        });

        await db.SaveChangesAsync(context.RequestAborted);
    }
}
