using MQTTnet;
using MQTTnet.Client;
using SlnMesnac.Serilog;
using System;
using System.Security.Authentication;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

#region << 版 本 注 释 >>

/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本：4.0.30319.42000
* 机器名称：LAPTOP-E0N2L34V
* 命名空间：SlnMesnac.Mqtt
* 唯一标识：496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
*
* 创建者：WenJY
* 电子邮箱：wenjy@mesnac.com
* 创建时间：2024-03-27 21:58:35
* 版本：V1.0.0
* 描述：
*
*--------------------------------------------------------------------
* 修改人：
* 时间：
* 修改说明：
*
* 版本：V1.0.0
*--------------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

namespace SlnMesnac.Mqtt
{
    /// <summary>
    /// MQTT客户端
    /// </summary>
    public class MqttClient
    {
        public readonly SerilogHelper _logger;

        private IMqttClient _client;

        public MqttClient(SerilogHelper logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 链接服务器
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <param name="clientId"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        public async void Connect(string ip, int port, string clientId, string username, string password)
        {
            try
            {
                MqttClientOptions options = new MqttClientOptionsBuilder()
                .WithTcpServer(ip, port)
                .WithClientId(clientId)
                .WithCredentials(username, password)
                .WithTls(o =>   //开启ssl
                {
                    o.CertificateValidationHandler = _ => true;

                    o.SslProtocol = SslProtocols.Tls12;
                })
                .Build();
                _client = new MqttFactory().CreateMqttClient();

                _client.ApplicationMessageReceivedAsync += MqttClient_ApplicationMessageReceived;

                MqttClientConnectResult result = await _client.ConnectAsync(options);

                if (result != null)
                {
                    if (result.ResultCode == MQTTnet.Client.MqttClientConnectResultCode.Success)
                    {
                        _logger.Info($"连接服务器成功{ip}:{port}");
                    }
                    else
                    {
                        _logger.Info($"连接服务器失败");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error("连接服务器异常", ex);
            }
        }

        /// <summary>
        /// 断开链接
        /// </summary>
        public void DisConnect()
        {
            _client.DisconnectAsync();
            _logger.Info($"断开连接");
        }

        /// <summary>
        /// 订阅主题
        /// </summary>
        /// <param name="topic"></param>
        public async void SubscriptionAsync(string topic)
        {
            try
            {
                var mqttFactory = new MqttFactory();
                var mqttSubscribeOptions = mqttFactory.CreateSubscribeOptionsBuilder()
                    .WithTopicFilter(
                        f =>
                        {
                            f.WithTopic(topic);
                        })
                    .Build();

                MqttClientSubscribeResult result = await _client.SubscribeAsync(mqttSubscribeOptions, CancellationToken.None);

                _logger.Info($"订阅主题:{topic}");
            }
            catch (Exception ex)
            {
                _logger.Error("订阅主题异常", ex);
            }
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        /// <param name="topic"></param>
        public void Unsubscribe(string topic)
        {
            _client.UnsubscribeAsync(topic);
            _logger.Info($"取消订阅，主题：{topic}");
        }

        /// <summary>
        /// 推送消息
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="message"></param>
        public void Publish(string topic, string message)
        {
            try
            {
                var msg = new MqttApplicationMessageBuilder().WithTopic(topic).WithPayload(message)
                .Build();
                _client.PublishAsync(msg, CancellationToken.None);
                _logger.Info($"向服务端推送成功，主题：{topic}；内容：{message}");
            }
            catch (Exception ex)
            {
                _logger.Error("向服务端推送消息异常", ex);
            }
        }

        private async Task MqttClient_ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs eventArgs)
        {
            var info = $"接收到主题：{eventArgs.ApplicationMessage.Topic}的消息，内容：{Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)}";
            _logger.Info(info);
        }
    }
}