using Microsoft.AspNetCore.Connections;
using RabbitMQ.Client.Events;
using RabbitMQ.Client;
using System.Text;

namespace OpenAuth.WebApi.Model.RabbitMQService
{
    public class RabbitMqListenerService : BackgroundService
    {
        private readonly ConnectionFactory _factory;
        private IConnection _connection;
        private IChannel _channel;
        private readonly Dictionary<string, string> _queueRoutingMap = new();
        private readonly object _lock = new();
        private readonly List<QueueBinding> _bindings = new();
        public RabbitMqListenerService()
        { 
            _factory = new ConnectionFactory
            {
                HostName = "123.132.248.154",
                UserName = "DHCloudg1",
                Password = "Cloud0#4fCraQrm",
                Port = 9103
                //HostName = "localhost",
                //UserName = "guest",
                //Password = "guest",
                //Port = 5672
            };
        }
        public async Task AddQueueBindingAsync(string exchange, string exchangeType, string routingKey)
        {
            _bindings.Add(new QueueBinding
            {
                Exchange = exchange,
                ExchangeType = exchangeType,
                RoutingKey = routingKey
            });

            if (_channel != null)
            {
                await BindQueueAsync(_channel, exchange, exchangeType, routingKey);
            }
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _connection = await _factory.CreateConnectionAsync(stoppingToken);
            _channel = await _connection.CreateChannelAsync();
            //await BindQueueAsync(_channel, "processing_event", "topic", "event.trafficJunction.1.sdhc");
            foreach (var binding in _bindings)
            {
                await BindQueueAsync(_channel, binding.Exchange, binding.ExchangeType, binding.RoutingKey);
            }
        }

        private async Task BindQueueAsync(IChannel channel, string exchange, string exchangeType, string routingKey)
        {
            await channel.ExchangeDeclareAsync(exchange, exchangeType, durable: true);  
            await channel.QueueDeclareAsync("", durable: true, exclusive: false, autoDelete: false);
            await channel.QueueBindAsync("", exchange, routingKey);

            var consumer = new AsyncEventingBasicConsumer(channel);
            consumer.ReceivedAsync += async (sender, ea) =>
            {
                
                var body = ea.Body.ToArray();
                var message = Encoding.UTF8.GetString(body);
                Console.WriteLine($"[processing_event]: {message}");
                //   Exchange 来做不同处理
                switch (ea.Exchange)
                {
                    case "processing_event":
                        Console.WriteLine($"[processing_event]: {message}");
                        break;
                    case "thing_event":
                        Console.WriteLine($"[thing_event] {message}");
                        break;
                    default:
                        Console.WriteLine($"[Other:{ea.RoutingKey}] {message}");
                        break;
                }

                await Task.Yield();
            };

            await channel.BasicConsumeAsync("", autoAck: true, consumer);
        } 
        //public async Task AddListenerAsync(string exchange, string exchangeType, string routingKey)
        //{
        //    _connection = await _factory.CreateConnectionAsync();

        //    foreach (var binding in _bindings)
        //    {
        //        var channel = await _connection.CreateChannelAsync();

        //        // 声明交换机
        //        await channel.ExchangeDeclareAsync(binding.Exchange, binding.ExchangeType, durable: true);
        //        await channel.QueueDeclareAsync("", durable: true, exclusive: false, autoDelete: false);
        //        // 绑定队列到交换机
        //        await channel.QueueBindAsync(queue: "", exchange: binding.Exchange, routingKey: binding.RoutingKey);

        //        var consumer = new AsyncEventingBasicConsumer(channel);
        //        consumer.ReceivedAsync += async (model, ea) =>
        //        {
        //            var body = ea.Body.ToArray();
        //            var message = Encoding.UTF8.GetString(body);

        //            using var scope = _serviceProvider.CreateScope();

        //            foreach (var handler in handlers)
        //            {
        //                await handler.HandleMessageAsync(binding.Exchange, ea.RoutingKey, message);
        //            }

        //            await channel.BasicAckAsync(ea.DeliveryTag, multiple: false);
        //        };
        //        await channel.BasicConsumeAsync(queue: "", autoAck: false, consumer: consumer);

        //        _channels.Add(channel);
        //    }
        //}

        //public async ValueTask DisposeAsync()
        //{
        //    foreach (var channel in _channels)
        //    {
        //        if (channel != null)
        //            await channel.CloseAsync();
        //    }
        //    if (_connection != null)
        //        await _connection.CloseAsync();
        //}
        private class QueueBinding
        {
            public string Exchange { get; set; } = "";
            public string ExchangeType { get; set; } = "";
            public string RoutingKey { get; set; } = "";
        }
    }
}
