using Dapper; using SIGCM.Domain.Entities; using SIGCM.Infrastructure.Data; namespace SIGCM.Infrastructure.Repositories; public class ClientRepository { private readonly IDbConnectionFactory _db; public ClientRepository(IDbConnectionFactory db) { _db = db; } // Búsqueda inteligente redireccionada a Users public async Task> SearchAsync(string query) { using var conn = _db.CreateConnection(); var sql = @" SELECT TOP 10 Id, ISNULL(BillingName, Username) as Name, ISNULL(BillingTaxId, '') as DniOrCuit, Email, Phone, BillingAddress as Address FROM Users WHERE BillingName LIKE @Query OR BillingTaxId LIKE @Query OR Username LIKE @Query ORDER BY BillingName"; return await conn.QueryAsync(sql, new { Query = $"%{query}%" }); } // Asegurar existencia (Upsert en la tabla Users) public async Task EnsureClientExistsAsync(string name, string dni) { using var conn = _db.CreateConnection(); var existingId = await conn.ExecuteScalarAsync( "SELECT Id FROM Users WHERE BillingTaxId = @Dni", new { Dni = dni }); if (existingId.HasValue) { await conn.ExecuteAsync("UPDATE Users SET BillingName = @Name WHERE Id = @Id", new { Name = name, Id = existingId }); return existingId.Value; } else { // Si no existe, creamos un usuario con rol Cliente (sin password por ahora, es solo para gestión de mostrador) var sql = @" INSERT INTO Users (Username, Role, BillingName, BillingTaxId, PasswordHash, MustChangePassword) VALUES (@Username, 'Client', @Name, @Dni, 'N/A', 0); SELECT CAST(SCOPE_IDENTITY() as int);"; // El username será el DNI para asegurar unicidad si no hay otro dato return await conn.QuerySingleAsync(sql, new { Username = dni, Name = name, Dni = dni }); } } // Obtener todos con estadísticas desde Users public async Task> GetAllWithStatsAsync() { using var conn = _db.CreateConnection(); var sql = @" SELECT u.Id as id, ISNULL(u.BillingName, u.Username) as name, ISNULL(u.BillingTaxId, 'S/D') as dniOrCuit, ISNULL(u.Email, 'Sin correo') as email, ISNULL(u.Phone, 'Sin teléfono') as phone, (SELECT COUNT(1) FROM Listings l WHERE l.ClientId = u.Id) as totalAds, ISNULL((SELECT SUM(AdFee) FROM Listings l WHERE l.ClientId = u.Id), 0) as totalSpent FROM Users u WHERE Role IN ('Client', 'User') -- Mostramos tanto clientes puros como usuarios web ORDER BY name"; return await conn.QueryAsync(sql); } public async Task UpdateAsync(Client client) { using var conn = _db.CreateConnection(); var sql = @" UPDATE Users SET BillingName = @Name, BillingTaxId = @DniOrCuit, Email = @Email, Phone = @Phone, BillingAddress = @Address WHERE Id = @Id"; await conn.ExecuteAsync(sql, client); } public async Task GetClientSummaryAsync(int clientId) { using var conn = _db.CreateConnection(); var sql = @" SELECT u.Id, ISNULL(u.BillingName, u.Username) as Name, u.BillingTaxId as DniOrCuit, u.Email, u.Phone, u.BillingAddress as Address, (SELECT COUNT(1) FROM Listings WHERE ClientId = u.Id) as TotalAds, ISNULL((SELECT SUM(AdFee) FROM Listings WHERE ClientId = u.Id), 0) as TotalInvested, (SELECT MAX(CreatedAt) FROM Listings WHERE ClientId = u.Id) as LastAdDate, (SELECT COUNT(1) FROM Listings WHERE ClientId = u.Id AND Status = 'Published') as ActiveAds, ISNULL(( SELECT TOP 1 cat.Name FROM Listings l JOIN Categories cat ON l.CategoryId = cat.Id WHERE l.ClientId = u.Id GROUP BY cat.Name ORDER BY COUNT(l.Id) DESC ), 'N/A') as PreferredCategory FROM Users u WHERE u.Id = @Id"; return await conn.QuerySingleOrDefaultAsync(sql, new { Id = clientId }); } }