using GestionIntegral.Api.Data.Repositories.Comunicaciones;
using GestionIntegral.Api.Data.Repositories.Usuarios;
using GestionIntegral.Api.Dtos.Comunicaciones;

namespace GestionIntegral.Api.Services.Comunicaciones
{
  public class EmailLogService : IEmailLogService
  {
    private readonly IEmailLogRepository _emailLogRepository;
    private readonly IUsuarioRepository _usuarioRepository;

    public EmailLogService(IEmailLogRepository emailLogRepository, IUsuarioRepository usuarioRepository)
    {
      _emailLogRepository = emailLogRepository;
      _usuarioRepository = usuarioRepository;
    }

    public async Task<IEnumerable<EmailLogDto>> ObtenerHistorialPorReferencia(string referenciaId)
    {
      var logs = await _emailLogRepository.GetByReferenceAsync(referenciaId);
      if (!logs.Any())
      {
        return Enumerable.Empty<EmailLogDto>();
      }

      // Optimización N+1: Obtener todos los usuarios necesarios en una sola consulta
      var idsUsuarios = logs
          .Where(l => l.IdUsuarioDisparo.HasValue)
          .Select(l => l.IdUsuarioDisparo!.Value)
          .Distinct();

      var usuariosDict = new Dictionary<int, string>();
      if (idsUsuarios.Any())
      {
        var usuarios = await _usuarioRepository.GetByIdsAsync(idsUsuarios);
        usuariosDict = usuarios.ToDictionary(u => u.Id, u => $"{u.Nombre} {u.Apellido}");
      }

      // Mapear a DTO
      return logs.Select(log => new EmailLogDto
      {
        FechaEnvio = log.FechaEnvio,
        Estado = log.Estado,
        Asunto = log.Asunto,
        DestinatarioEmail = log.DestinatarioEmail,
        Error = log.Error,
        NombreUsuarioDisparo = log.IdUsuarioDisparo.HasValue
              ? usuariosDict.GetValueOrDefault(log.IdUsuarioDisparo.Value, "Usuario Desconocido")
              : "Sistema"
      });
    }

    public async Task<IEnumerable<EmailLogDto>> ObtenerDetallesPorLoteId(int idLoteDeEnvio)
    {
      var logs = await _emailLogRepository.GetByLoteIdAsync(idLoteDeEnvio);
      if (!logs.Any())
      {
        return Enumerable.Empty<EmailLogDto>();
      }

      // Reutilizamos la misma lógica de optimización N+1 que ya teníamos
      var idsUsuarios = logs
          .Where(l => l.IdUsuarioDisparo.HasValue)
          .Select(l => l.IdUsuarioDisparo!.Value)
          .Distinct();

      var usuariosDict = new Dictionary<int, string>();
      if (idsUsuarios.Any())
      {
        var usuarios = await _usuarioRepository.GetByIdsAsync(idsUsuarios);
        usuariosDict = usuarios.ToDictionary(u => u.Id, u => $"{u.Nombre} {u.Apellido}");
      }

      return logs.Select(log => new EmailLogDto
      {
        FechaEnvio = log.FechaEnvio,
        Estado = log.Estado,
        Asunto = log.Asunto,
        DestinatarioEmail = log.DestinatarioEmail,
        Error = log.Error,
        NombreUsuarioDisparo = log.IdUsuarioDisparo.HasValue
              ? usuariosDict.GetValueOrDefault(log.IdUsuarioDisparo.Value, "Usuario Desconocido")
              : "Sistema"
      });
    }
  }
}