using Dapper; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Domain.Entities; namespace SIGCM2.Infrastructure.Persistence; public sealed class UsuarioRepository : IUsuarioRepository { private readonly SqlConnectionFactory _connectionFactory; public UsuarioRepository(SqlConnectionFactory connectionFactory) { _connectionFactory = connectionFactory; } public async Task GetByUsernameAsync(string username) { const string sql = """ SELECT Id, Username, PasswordHash, Nombre, Apellido, Email, Rol, PermisosJson, Activo FROM dbo.Usuario WHERE Username = @Username AND Activo = 1 """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(); var row = await connection.QuerySingleOrDefaultAsync(sql, new { Username = username }); if (row is null) return null; return MapRow(row); } public async Task GetByIdAsync(int id, CancellationToken ct = default) { const string sql = """ SELECT Id, Username, PasswordHash, Nombre, Apellido, Email, Rol, PermisosJson, Activo FROM dbo.Usuario WHERE Id = @Id """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(); var row = await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); if (row is null) return null; return MapRow(row); } private static Usuario MapRow(UsuarioRow row) => new( id: row.Id, username: row.Username, passwordHash: row.PasswordHash, nombre: row.Nombre, apellido: row.Apellido, email: row.Email, rol: row.Rol, permisosJson: row.PermisosJson, activo: row.Activo ); // Flat DTO for Dapper mapping (avoids polluting domain entity with Dapper attributes) private sealed record UsuarioRow( int Id, string Username, string PasswordHash, string Nombre, string Apellido, string? Email, string Rol, string PermisosJson, bool Activo ); }