using System.Data; using Dapper; using SIGCM.Application.DTOs; using SIGCM.Domain.Entities; using SIGCM.Domain.Interfaces; using SIGCM.Infrastructure.Data; namespace SIGCM.Infrastructure.Repositories; public class ListingRepository : IListingRepository { private readonly IDbConnectionFactory _connectionFactory; public ListingRepository(IDbConnectionFactory connectionFactory) { _connectionFactory = connectionFactory; } public async Task CreateAsync(Listing listing, Dictionary attributes) { using var conn = _connectionFactory.CreateConnection(); conn.Open(); using var transaction = conn.BeginTransaction(); try { var sqlListing = @" INSERT INTO Listings ( CategoryId, OperationId, Title, Description, Price, Currency, CreatedAt, Status, UserId, PrintText, PrintStartDate, PrintDaysCount, IsBold, IsFrame, PrintFontSize, PrintAlignment ) VALUES ( @CategoryId, @OperationId, @Title, @Description, @Price, @Currency, @CreatedAt, @Status, @UserId, @PrintText, @PrintStartDate, @PrintDaysCount, @IsBold, @IsFrame, @PrintFontSize, @PrintAlignment ); SELECT CAST(SCOPE_IDENTITY() as int);"; var listingId = await conn.QuerySingleAsync(sqlListing, listing, transaction); if (attributes != null && attributes.Any()) { var sqlAttr = @" INSERT INTO ListingAttributeValues (ListingId, AttributeDefinitionId, Value) VALUES (@ListingId, @AttributeDefinitionId, @Value)"; foreach (var attr in attributes) { await conn.ExecuteAsync(sqlAttr, new { ListingId = listingId, AttributeDefinitionId = attr.Key, Value = attr.Value }, transaction); } } transaction.Commit(); return listingId; } catch { transaction.Rollback(); throw; } } public async Task GetByIdAsync(int id) { using var conn = _connectionFactory.CreateConnection(); return await conn.QuerySingleOrDefaultAsync("SELECT * FROM Listings WHERE Id = @Id", new { Id = id }); } public async Task GetDetailByIdAsync(int id) { using var conn = _connectionFactory.CreateConnection(); var sql = @" SELECT * FROM Listings WHERE Id = @Id; SELECT lav.*, ad.Name as AttributeName FROM ListingAttributeValues lav JOIN AttributeDefinitions ad ON lav.AttributeDefinitionId = ad.Id WHERE lav.ListingId = @Id; SELECT * FROM ListingImages WHERE ListingId = @Id ORDER BY DisplayOrder; "; using var multi = await conn.QueryMultipleAsync(sql, new { Id = id }); var listing = await multi.ReadSingleOrDefaultAsync(); if (listing == null) return null; var attributes = await multi.ReadAsync(); var images = await multi.ReadAsync(); return new SIGCM.Domain.Models.ListingDetail { Listing = listing, Attributes = attributes, Images = images }; } public async Task> GetAllAsync() { using var conn = _connectionFactory.CreateConnection(); // Subquery para obtener la imagen principal var sql = @" SELECT TOP 20 l.*, (SELECT TOP 1 Url FROM ListingImages li WHERE li.ListingId = l.Id ORDER BY IsMainInfo DESC, DisplayOrder ASC) as MainImageUrl FROM Listings l ORDER BY l.CreatedAt DESC"; return await conn.QueryAsync(sql); } public async Task> SearchAsync(string? query, int? categoryId) { using var conn = _connectionFactory.CreateConnection(); var sql = @" SELECT l.*, (SELECT TOP 1 Url FROM ListingImages li WHERE li.ListingId = l.Id ORDER BY IsMainInfo DESC, DisplayOrder ASC) as MainImageUrl FROM Listings l WHERE 1=1"; var parameters = new DynamicParameters(); if (!string.IsNullOrEmpty(query)) { sql += " AND (l.Title LIKE @Query OR l.Description LIKE @Query)"; parameters.Add("Query", $"%{query}%"); } if (categoryId.HasValue) { sql += " AND l.CategoryId = @CategoryId"; parameters.Add("CategoryId", categoryId); } sql += " ORDER BY l.CreatedAt DESC"; return await conn.QueryAsync(sql, parameters); } public async Task> GetListingsForPrintAsync(DateTime targetDate) { using var conn = _connectionFactory.CreateConnection(); // La lógica: El aviso debe haber empezado antes o en la fecha target // Y la fecha target debe ser menor a la fecha de inicio + duración var sql = @" SELECT l.*, c.Name as CategoryName FROM Listings l JOIN Categories c ON l.CategoryId = c.Id WHERE l.PrintStartDate IS NOT NULL AND @TargetDate >= CAST(l.PrintStartDate AS DATE) AND @TargetDate < DATEADD(day, l.PrintDaysCount, CAST(l.PrintStartDate AS DATE)) ORDER BY c.Name, l.Title"; // Ordenado por Rubro y luego alfabético return await conn.QueryAsync(sql, new { TargetDate = targetDate.Date }); } }