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); } public async Task ExistsByUsernameAsync(string username, CancellationToken ct = default) { const string sql = """ SELECT COUNT(1) FROM dbo.Usuario WHERE Username = @Username """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); var count = await connection.ExecuteScalarAsync(sql, new { Username = username }); return count > 0; } public async Task AddAsync(Usuario usuario, CancellationToken ct = default) { // DF handles: Activo (1), PermisosJson ('[]'), FechaCreacion (GETDATE()) const string sql = """ INSERT INTO dbo.Usuario (Username, PasswordHash, Nombre, Apellido, Email, Rol) OUTPUT INSERTED.Id VALUES (@Username, @PasswordHash, @Nombre, @Apellido, @Email, @Rol) """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); var id = await connection.ExecuteScalarAsync(sql, new { usuario.Username, usuario.PasswordHash, usuario.Nombre, usuario.Apellido, usuario.Email, usuario.Rol }); return id; } 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 ); }