using Furion.JsonSerialization;
using Furion.RemoteRequest.Extensions;
using Newtonsoft.Json;
using System.Text;

namespace BPA.MES.Base.Application
{
    /// <summary>
    /// 名    称 ：MQTT通信库  
    /// 创 建 人 ：yangxiao  
    /// 创建时间 ：  2022/11/18 15:38:40 
    /// 描    述 ：  
    /// </summary>
    public class MQTTService : IMQTTService, ITransient, IDynamicApiController
    {
        private readonly ISqlSugarClient _dbContext;
        ISysCacheService _sysCacheService;
        public MQTTService(ISqlSugarClient db, ISysCacheService sysCacheService)
        {
            _dbContext = db;
            _sysCacheService = sysCacheService;
        }
        public async Task GetMQTTConfig()
        {
            var entity = await _dbContext.Queryable<MQTTInfoEntity>().FirstAsync();
            if (entity != null)
            {
                MQTTConfig.Address = entity.Address;
                MQTTConfig.Account = entity.Account;
                MQTTConfig.Pwd = entity.Pwd;
                await _sysCacheService.SetAsync("mqtt", entity);
            }
        }
        /// <summary>
        /// Mqtt通用服务
        /// </summary>
        public async Task<bool> MqttPublish(MqttPublishDto input)
        {
            bool result = false;
            MQTTInfoEntity mqttentity = new();
            mqttentity = await _sysCacheService.GetAsync<MQTTInfoEntity>("mqtt");
            if (mqttentity==null)
            {
                mqttentity = await _dbContext.Queryable<MQTTInfoEntity>().FirstAsync();
                await _sysCacheService.SetAsync("mqtt", mqttentity);
            }
            try
            {
                input.Payload.MessageId = input.MessageId;
                input.Payload.MsgVersion = new Version(1, 0, 0, 0);
                MsgPackage mp = new()
                {
                    Message = input.Payload,
                    MessageLen = JSON.Serialize(input.Payload).Length
                };
                //组装MQTT消息
                var tem = await $"http://{mqttentity.Address}{mqttentity.MsgPublishRoute}".SetHeaders(new
                {
                    Authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{mqttentity.Account}:{mqttentity.Pwd}"))
                }).SetBody(new
                {
                    input.Topic,
                    payload = JsonConvert.SerializeObject(mp),
                    qos = 2,
                    retain = false,
                    clientid = "pztj_service"
                }).PostAsStringAsync();
                var res = JSON.Deserialize<MqttResult>(tem);
                if (res.Code == 0 || res.Reason_code<100 || !string.IsNullOrEmpty(res.Id))
                {
                    result = true;
                }
                Console.WriteLine($"_____________________MQTT发消息:{JsonConvert.SerializeObject(mp)}");
            }
            catch
            {
               
            }
           
            return result;
        }
        [AllowAnonymous]
        public async Task<bool> MqttTestPublish(string topic, string msg)
        {
            bool result = false;
            var mqttentity = await _dbContext.Queryable<MQTTInfoEntity>().FirstAsync();
            string mqttAddress = mqttentity.Address;
            try
            {
                //组装MQTT消息
                var tem = await $"http://{mqttAddress}/api/v5/publish".SetHeaders(new
                {
                    Authorization = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes($"{mqttentity.Account}:{mqttentity.Pwd}"))
                }).SetBody(new
                {
                    topic,
                    payload = msg,
                    qos = 2,
                    retain = false,
                    clientid = "pztj_service"
                }).PostAsStringAsync();
                var res = JSON.Deserialize<MqttResult>(tem);
                if (res.Code == 0 || res.Reason_code < 100 || !string.IsNullOrEmpty(res.Id))
                {
                    result = true;
                }
            }
            catch
            {

            }
            return result;
        }

    }

    public class MqttResult
    {
        /// <summary>
        /// code
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// reason_code
        /// </summary>
        public int Reason_code { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string Id { get; set; }
    }

    public class MqttPublishDto
    {
        public IMessage Payload { get; set; }
        public string Topic { get; set; }
        public int MessageId { get; set; }
    }
    public interface IMQTTService
    {
        Task<bool> MqttPublish(MqttPublishDto input);

        Task GetMQTTConfig();
    }
}
