using System.Text; using Dapper; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Common; using SIGCM2.Domain.Entities; namespace SIGCM2.Infrastructure.Persistence; public sealed class MedioRepository : IMedioRepository { private readonly SqlConnectionFactory _connectionFactory; public MedioRepository(SqlConnectionFactory connectionFactory) { _connectionFactory = connectionFactory; } public async Task AddAsync(Medio m, CancellationToken ct = default) { // DF handles: Activo (1), FechaCreacion (SYSUTCDATETIME()). const string sql = """ INSERT INTO dbo.Medio (Codigo, Nombre, Tipo, PlataformaEmpresaId) OUTPUT INSERTED.Id VALUES (@Codigo, @Nombre, @Tipo, @PlataformaEmpresaId) """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); return await connection.ExecuteScalarAsync(sql, new { m.Codigo, m.Nombre, Tipo = (int)m.Tipo, m.PlataformaEmpresaId, }); } public async Task GetByIdAsync(int id, CancellationToken ct = default) { const string sql = """ SELECT Id, Codigo, Nombre, Tipo, PlataformaEmpresaId, Activo, FechaCreacion, FechaModificacion FROM dbo.Medio WHERE Id = @Id """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); var row = await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); return row is null ? null : MapRow(row); } public async Task ExistsByCodigoAsync(string codigo, CancellationToken ct = default) { const string sql = """ SELECT COUNT(1) FROM dbo.Medio WHERE Codigo = @Codigo """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); var count = await connection.ExecuteScalarAsync(sql, new { Codigo = codigo }); return count > 0; } public async Task UpdateAsync(Medio m, CancellationToken ct = default) { const string sql = """ UPDATE dbo.Medio SET Nombre = @Nombre, Tipo = @Tipo, PlataformaEmpresaId = @PlataformaEmpresaId, Activo = @Activo, FechaModificacion = @FechaModificacion WHERE Id = @Id """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); await connection.ExecuteAsync(sql, new { m.Nombre, Tipo = (int)m.Tipo, m.PlataformaEmpresaId, m.Activo, FechaModificacion = m.FechaModificacion, m.Id, }); } public async Task> GetPagedAsync(MediosQuery q, CancellationToken ct = default) { var page = Math.Max(1, q.Page); var pageSize = Math.Clamp(q.PageSize, 1, 100); var offset = (page - 1) * pageSize; var where = new StringBuilder("WHERE 1=1"); var parameters = new DynamicParameters(); parameters.Add("PageSize", pageSize); parameters.Add("Offset", offset); if (q.Activo.HasValue) { where.Append(" AND Activo = @Activo"); parameters.Add("Activo", q.Activo.Value ? 1 : 0); } if (q.Tipo.HasValue) { where.Append(" AND Tipo = @Tipo"); parameters.Add("Tipo", (int)q.Tipo.Value); } if (!string.IsNullOrWhiteSpace(q.Search)) { where.Append(" AND (Codigo LIKE @Search OR Nombre LIKE @Search)"); parameters.Add("Search", $"%{q.Search}%"); } var sql = $""" SELECT Id, Codigo, Nombre, Tipo, PlataformaEmpresaId, Activo, FechaCreacion, FechaModificacion, COUNT(*) OVER() AS TotalCount FROM dbo.Medio {where} ORDER BY Codigo OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY """; await using var connection = _connectionFactory.CreateConnection(); await connection.OpenAsync(ct); var rows = await connection.QueryAsync(sql, parameters); var list = rows.ToList(); var total = list.Count > 0 ? list[0].TotalCount : 0; var items = list.Select(r => MapRow(r)).ToList(); return new PagedResult(items, page, pageSize, total); } // ── mapping ─────────────────────────────────────────────────────────────── private static Medio MapRow(MedioRow r) => new( id: r.Id, codigo: r.Codigo, nombre: r.Nombre, tipo: (TipoMedio)r.Tipo, plataformaEmpresaId: r.PlataformaEmpresaId, activo: r.Activo, fechaCreacion: r.FechaCreacion, fechaModificacion: r.FechaModificacion); private static Medio MapRow(MedioPagedRow r) => new( id: r.Id, codigo: r.Codigo, nombre: r.Nombre, tipo: (TipoMedio)r.Tipo, plataformaEmpresaId: r.PlataformaEmpresaId, activo: r.Activo, fechaCreacion: r.FechaCreacion, fechaModificacion: r.FechaModificacion); private sealed record MedioRow( int Id, string Codigo, string Nombre, byte Tipo, int? PlataformaEmpresaId, bool Activo, DateTime FechaCreacion, DateTime? FechaModificacion); private sealed record MedioPagedRow( int Id, string Codigo, string Nombre, byte Tipo, int? PlataformaEmpresaId, bool Activo, DateTime FechaCreacion, DateTime? FechaModificacion, int TotalCount); }