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 con protección de nulos
  public async Task<IEnumerable<Client>> SearchAsync(string query)
  {
    using var conn = _db.CreateConnection();
    var sql = @"
            SELECT TOP 10 
                Id, 
                ISNULL(Name, 'Sin Nombre') as Name, 
                ISNULL(DniOrCuit, '') as DniOrCuit,
                Email, Phone, Address
            FROM Clients 
            WHERE Name LIKE @Query OR DniOrCuit LIKE @Query
            ORDER BY Name";
    return await conn.QueryAsync<Client>(sql, new { Query = $"%{query}%" });
  }

  // Asegurar existencia (Upsert)
  public async Task<int> EnsureClientExistsAsync(string name, string dni)
  {
    using var conn = _db.CreateConnection();

    var existingId = await conn.ExecuteScalarAsync<int?>(
        "SELECT Id FROM Clients WHERE DniOrCuit = @Dni", new { Dni = dni });

    if (existingId.HasValue)
    {
      await conn.ExecuteAsync("UPDATE Clients SET Name = @Name WHERE Id = @Id", new { Name = name, Id = existingId });
      return existingId.Value;
    }
    else
    {
      var sql = @"
                INSERT INTO Clients (Name, DniOrCuit) VALUES (@Name, @Dni);
                SELECT CAST(SCOPE_IDENTITY() as int);";
      return await conn.QuerySingleAsync<int>(sql, new { Name = name, Dni = dni });
    }
  }

  // Obtener todos con estadísticas (ISNULL agregado para seguridad)
  public async Task<IEnumerable<dynamic>> GetAllWithStatsAsync()
  {
    using var conn = _db.CreateConnection();
    var sql = @"
        SELECT 
            c.Id as id, 
            ISNULL(c.Name, 'Sin Nombre') as name, 
            ISNULL(c.DniOrCuit, 'S/D') as dniOrCuit,
            ISNULL(c.Email, 'Sin correo') as email, 
            ISNULL(c.Phone, 'Sin teléfono') as phone,
            (SELECT COUNT(1) FROM Listings l WHERE l.ClientId = c.Id) as totalAds,
            ISNULL((SELECT SUM(AdFee) FROM Listings l WHERE l.ClientId = c.Id), 0) as totalSpent
        FROM Clients c
        ORDER BY c.Name";
    return await conn.QueryAsync(sql);
  }

  public async Task UpdateAsync(Client client)
  {
    using var conn = _db.CreateConnection();
    var sql = @"
        UPDATE Clients 
        SET Name = @Name, 
            DniOrCuit = @DniOrCuit, 
            Email = @Email, 
            Phone = @Phone, 
            Address = @Address
        WHERE Id = @Id";
    await conn.ExecuteAsync(sql, client);
  }

  public async Task<dynamic?> GetClientSummaryAsync(int clientId)
  {
    using var conn = _db.CreateConnection();
    var sql = @"
        SELECT 
            c.Id, c.Name, c.DniOrCuit, c.Email, c.Phone, c.Address,
            (SELECT COUNT(1) FROM Listings WHERE ClientId = c.Id) as TotalAds,
            ISNULL((SELECT SUM(AdFee) FROM Listings WHERE ClientId = c.Id), 0) as TotalInvested,
            (SELECT MAX(CreatedAt) FROM Listings WHERE ClientId = c.Id) as LastAdDate,
            (SELECT COUNT(1) FROM Listings WHERE ClientId = c.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 = c.Id 
                GROUP BY cat.Name 
                ORDER BY COUNT(l.Id) DESC
            ), 'N/A') as PreferredCategory
        FROM Clients c
        WHERE c.Id = @Id";

    return await conn.QuerySingleOrDefaultAsync<dynamic>(sql, new { Id = clientId });
  }
}