using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace adas_core.Infrastructure.Services;

public class PublisherService : IPublisherService
{
    private readonly ILogger<PublisherService> _logger;
    private readonly HashSet<string> _queues = new();
    private readonly IBus? _bus;

    public PublisherService(
        IOptions<RabbitMqSettings> rabbitMqSettings,
        ILogger<PublisherService> logger)
    {
        _logger = logger;

        try
        {
            var connection = rabbitMqSettings.Value.ConnectionString;

            if (string.IsNullOrWhiteSpace(connection))
            {
                _logger.LogError("Missing RabbitMQ connection string");
                return;
            }

            var services = new ServiceCollection();
            services.AddEasyNetQ(connection);

            var provider = services.BuildServiceProvider();
            _bus = provider.GetRequiredService<IBus>();

            _logger.LogInformation("PublisherService initialized");
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error initializing PublisherService");
        }
    }

    public Task<bool> CreateQueue(string queueName)
    {
        if (string.IsNullOrWhiteSpace(queueName))
            return Task.FromResult(false);

        if (_queues.Contains(queueName))
        {
            _logger.LogDebug("Queue {queueName} already registered", queueName);
            return Task.FromResult(true);
        }

        _queues.Add(queueName);

        _logger.LogInformation("Queue registered: {queueName}", queueName);

        // EasyNetQ crea colas automáticamente
        return Task.FromResult(true);
    }

    public async Task<bool> SendMessage(string msg, string queueName)
    {
        try
        {
            if (_bus == null)
            {
                _logger.LogError("Bus is null");
                return false;
            }

            await CreateQueue(queueName);

            _logger.LogDebug("Sending message to {queueName}", queueName);

            await _bus.SendReceive.SendAsync(queueName, msg);

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error sending message to {queueName}", queueName);
            return false;
        }
    }

    public async Task<bool> SendMessage(object obj, string queueName)
    {
        var json = JsonConvert.SerializeObject(obj);
        return await SendMessage(json, queueName);
    }

    public async Task<bool> SendMessageError(object obj, string queueName)
    {
        try
        {
            if (_bus == null)
            {
                _logger.LogError("Bus is null - cannot send error message");
                return false;
            }

            if (obj is not Message<Error> errorMessage)
                return false;

            await CreateQueue(queueName);

            _logger.LogDebug("Sending error message to {queueName}", queueName);

            // enviamos solo el Error (no Message<Error>)
            await _bus.SendReceive.SendAsync(queueName, errorMessage.Body);

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error sending error message");
            return false;
        }
    }
}
