using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Moq;
using ROLAC.API.Data;
using ROLAC.API.Data.Interceptors;
using ROLAC.API.Entities;
using Xunit;

namespace ROLAC.API.Tests.Data;

public class AuditInterceptorTests
{
    private static AppDbContext BuildDb(AuditSaveChangesInterceptor interceptor)
    {
        var options = new DbContextOptionsBuilder<AppDbContext>()
            .UseInMemoryDatabase(Guid.NewGuid().ToString())
            .AddInterceptors(interceptor)
            .Options;
        return new AppDbContext(options);
    }

    private static AuditSaveChangesInterceptor BuildInterceptor(string userId = "user-1")
    {
        var claims  = new[] { new Claim(ClaimTypes.NameIdentifier, userId) };
        var ctx     = new DefaultHttpContext { User = new(new ClaimsIdentity(claims)) };
        var mock    = new Mock<IHttpContextAccessor>();
        mock.Setup(x => x.HttpContext).Returns(ctx);
        return new AuditSaveChangesInterceptor(new ROLAC.API.Services.Logging.CurrentUserAccessor(mock.Object));
    }

    [Fact]
    public async Task Added_SetsCreatedAtAndCreatedBy()
    {
        var interceptor = BuildInterceptor("user-42");
        using var db    = BuildDb(interceptor);

        var member = new Member { FirstName_en = "A", LastName_en = "B" };
        db.Members.Add(member);
        await db.SaveChangesAsync();

        Assert.Equal("user-42", member.CreatedBy);
        Assert.Equal("user-42", member.UpdatedBy);
        Assert.True(member.CreatedAt > DateTimeOffset.UtcNow.AddSeconds(-5));
    }

    [Fact]
    public async Task Modified_UpdatesUpdatedAtAndUpdatedBy()
    {
        var interceptor = BuildInterceptor("user-1");
        using var db    = BuildDb(interceptor);

        var member = new Member { FirstName_en = "A", LastName_en = "B" };
        db.Members.Add(member);
        await db.SaveChangesAsync();

        member.NickName = "Nick";
        await db.SaveChangesAsync();

        Assert.Equal("user-1", member.UpdatedBy);
    }
}
