using Dapper;
using SIGCM2.Application.Audit;
using SIGCM2.Infrastructure.Persistence;

namespace SIGCM2.Infrastructure.Audit;

public sealed class SecurityEventRepository : ISecurityEventRepository
{
    private readonly SqlConnectionFactory _factory;

    public SecurityEventRepository(SqlConnectionFactory factory)
    {
        _factory = factory;
    }

    public async Task<long> InsertAsync(
        DateTime occurredAt,
        int? actorUserId,
        string? attemptedUsername,
        Guid? sessionId,
        string action,
        string result,
        string? failureReason,
        string? ipAddress,
        string? userAgent,
        string? metadata,
        CancellationToken ct = default)
    {
        const string sql = """
            INSERT INTO dbo.SecurityEvent
                (OccurredAt, ActorUserId, AttemptedUsername, SessionId, Action, Result,
                 FailureReason, IpAddress, UserAgent, Metadata)
            OUTPUT INSERTED.Id
            VALUES
                (@OccurredAt, @ActorUserId, @AttemptedUsername, @SessionId, @Action, @Result,
                 @FailureReason, @IpAddress, @UserAgent, @Metadata);
            """;

        await using var conn = _factory.CreateConnection();
        await conn.OpenAsync(ct);

        var cmd = new CommandDefinition(sql, new
        {
            OccurredAt = occurredAt,
            ActorUserId = actorUserId,
            AttemptedUsername = attemptedUsername,
            SessionId = sessionId,
            Action = action,
            Result = result,
            FailureReason = failureReason,
            IpAddress = ipAddress,
            UserAgent = userAgent,
            Metadata = metadata,
        }, cancellationToken: ct);

        return await conn.ExecuteScalarAsync<long>(cmd);
    }
}
