using Microsoft.Extensions.DependencyInjection;
using SlnMesnac.Model.domain;
using SlnMesnac.Model.dto;
using SlnMesnac.Plc;
using SlnMesnac.Rfid;
using SlnMesnac.Serilog;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

#region << 版 本 注 释 >>

/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本：4.0.30319.42000
* 机器名称：LAPTOP-E0N2L34V
* 命名空间：SlnMesnac.Business.base
* 唯一标识：b00d95c1-a164-43a3-9f34-2a5d2efb3f34
*
* 创建者：WenJY
* 电子邮箱：wenjy@mesnac.com
* 创建时间：2024-04-12 17:36:19
* 版本：V1.0.0
* 描述：
*
*--------------------------------------------------------------------
* 修改人：
* 时间：
* 修改说明：
*
* 版本：V1.0.0
*--------------------------------------------------------------------*/

#endregion << 版 本 注 释 >>

namespace SlnMesnac.Business.@base
{
    public class BaseBusiness
    {
        private readonly SerilogHelper _logger;

        private readonly List<PlcAbsractFactory> _plcFactories;

        private readonly List<RfidAbsractFactory> _rfidFactories;

        private readonly ISqlSugarClient sqlSugarClient;

        private IServiceProvider _serviceProvider;

        public BaseBusiness(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
            _logger = serviceProvider.GetRequiredService<SerilogHelper>();
            sqlSugarClient = serviceProvider.GetRequiredService<ISqlSugarClient>();
            using (var scope = _serviceProvider.CreateScope())
            {
                _plcFactories = scope.ServiceProvider.GetRequiredService<List<PlcAbsractFactory>>();
                _rfidFactories = scope.ServiceProvider.GetRequiredService<List<RfidAbsractFactory>>();
            }
        }

        /// <summary>
        /// 根据Key获取PLC连接信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public PlcAbsractFactory GetPlcByKey(string key)
        {
            if (_plcFactories == null)
            {
                throw new ArgumentNullException($"根据Key获取PLC连接信息异常:PLC 连接信息为空");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("根据Key获取PLC连接信息异常:设备Key参数为空");
            }

            try
            {
                var info = _plcFactories.Where(x => x.ConfigKey == key).FirstOrDefault();

                return info;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"根据Key获取PLC连接信息异常:{ex.Message}");
            }
        }

        #region RFID相关

        /// <summary>
        /// 根据Key获取Rfid连接信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidOperationException"></exception>
        public RfidAbsractFactory GetRfidByKey(string key)
        {
            if (_rfidFactories == null)
            {
                throw new ArgumentNullException($"根据Key获取RFID连接信息异常:PLC 连接信息为空");
            }

            if (string.IsNullOrEmpty(key))
            {
                throw new ArgumentNullException("根据Key获取RFID连接信息异常:设备Key参数为空");
            }

            try
            {
                var info = _rfidFactories.Where(x => x.ConfigKey == key).FirstOrDefault();

                return info;
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException($"根据Key获取RFID连接信息异常:{ex.Message}");
            }
        }

        /// <summary>
        /// 使用---根据RFID Key读取RFID信息
        /// </summary>
        /// <param name="rfidKey"></param>
        /// <param name="epcStr"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<string> ReadEpcStrByRfidKeyAsync(string rfidKey)
        {
            try
            {
                string epcStr = string.Empty;
                var rfidEquip = GetRfidByKey(rfidKey);
                if (rfidEquip == null || rfidEquip.GetOnlineStatus() == false)
                {
                    return "";
                }

                List<TagInfo> tagInfoList = await rfidEquip.GetRFIDAsync();
                if (tagInfoList == null || tagInfoList.Count == 0) return "";
                tagInfoList = tagInfoList.Where(X => X.EPCstring.Length == 12).ToList();
                epcStr = tagInfoList.OrderByDescending(x => x.Count).First().EPCstring;
                epcStr = epcStr.Replace(" ", "").Replace("\r\n", "").Replace("\0", "").Replace("\n", "");
                return epcStr;
            }
            catch (Exception ex)
            {
                // throw new InvalidOperationException($"根据RFID Key读取RFID信息异常:{ex.Message}");
                return "";
            }
        }

        /// <summary>
        /// 连廊使用---根据RFID Key读取RFID信息，并返回读取类型:type-0读取失败; type-1读取ok；type-2串读
        /// </summary>
        /// <param name="rfidKey"></param>
        /// <param name="epcStr"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public string ReadEpcStrByRfidKeyAndReturnType(string rfidKey, out int type)
        {
            try
            {
                type = 0;
                string epcStr = string.Empty;
                var rfidEquip = GetRfidByKey(rfidKey);
                if (rfidEquip == null || rfidEquip.GetOnlineStatus() == false)
                {
                    return "";
                }

                List<TagInfo> tagInfoList = rfidEquip.GetRFID();
                if (tagInfoList == null || tagInfoList.Count == 0) return "";
                //读取到不同RFID的个数
                int codeDistinctCount = tagInfoList.Select(x => x.EPCstring).Distinct().Count();
                if (codeDistinctCount == 0)
                {
                    type = 0;
                }
                else if (codeDistinctCount == 1)
                {
                    type = 1;
                }
                else if (codeDistinctCount > 1)
                {
                    //串读
                    type = 2;
                }
                epcStr = tagInfoList.OrderByDescending(x => x.Count).First().EPCstring;
                epcStr = epcStr.Replace(" ", "").Replace("\r\n", "").Replace("\0", "").Replace("\n", "");
                return epcStr;
            }
            catch (Exception ex)
            {
                // throw new InvalidOperationException($"根据RFID Key读取RFID信息异常:{ex.Message}");
                type = 0;
                return "";
            }
        }

        /// <summary>
        /// 使用---根据RFID Key读取RFID信息
        /// </summary>
        /// <param name="rfidKey"></param>
        /// <param name="epcStr"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public string ReadEpcStrByRfidKey(string rfidKey)
        {
            try
            {
                string epcStr = string.Empty;
                var rfidEquip = GetRfidByKey(rfidKey);
                if (rfidEquip == null || rfidEquip.GetOnlineStatus() == false)
                {
                    return "";
                }

                List<TagInfo> tagInfoList = rfidEquip.GetRFID();
                if (tagInfoList == null || tagInfoList.Count == 0) return "";
                epcStr = tagInfoList.OrderByDescending(x => x.Count).First().EPCstring;
                epcStr = epcStr.Replace(" ", "").Replace("\r\n", "").Replace("\0", "").Replace("\n", "");
                return epcStr;
            }
            catch (Exception ex)
            {
                // throw new InvalidOperationException($"根据RFID Key读取RFID信息异常:{ex.Message}");
                return "";
            }
        }

        /// <summary>
        /// 使用---根据RFID Key读取光电信号
        /// 有物体返回true
        /// </summary>
        /// <param name="rfidKey"></param>
        /// <param name="epcStr"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public async Task<bool> ReadSignalByRfidKeyAsync(string rfidKey)
        {
            try
            {
                var rfidEquip = GetRfidByKey(rfidKey);
                if (rfidEquip == null || rfidEquip.GetOnlineStatus() == false)
                {
                    return false;
                }

                bool result = await rfidEquip.GetSignalAsync();
                return result;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        #endregion RFID相关

        ///// <summary>
        ///// 寻找可用agv算法  --   //根据电量计算，选取在线，电量最低的未处于充电状态的，正常状态的agv
        ///// </summary>
        ///// <returns></returns>
        //public WcsBaseEquip? GetCanUseAgv()
        //{
        //    List<WcsBaseEquip> agvList = sqlSugarClient.Queryable<WcsBaseEquip>()
        //   .LeftJoin<WcsTask>((equip, task) => equip.EquipNo == task.NextPointNo)
        //   .Where((equip, task) => equip.EquipType == 1 && task.NextPointNo == null)
        //   .Select((equip, task) => equip)
        //   .ToList();

        //    try
        //    {
        //        if (agvList.Count == 0)
        //        {
        //            return null;
        //        }

        //        List<string> equipNos = agvList.Select(it => it.EquipNo).ToList();
        //        //查询在线的，不在充电状态的agv
        //        List<WcsAgvStatus>? agvStatusList = sqlSugarClient.Queryable<WcsAgvStatus>().Where(x => equipNos.Contains(x.EquipNo) && x.Online == "true" && x.Status != "7").ToList();
        //        if (agvStatusList == null || agvStatusList.Count == 0)
        //        {
        //            return null;
        //        }
        //        WcsBaseEquip targetAgv = agvList.First(x => x.EquipNo == agvStatusList.OrderBy(x => x.Battery).First().EquipNo);
        //        return targetAgv;
        //    }
        //    catch (Exception ex)
        //    {
        //        _logger.Error($"寻找可用agv算法GetCanUseAgv 异常{ex.Message}");
        //        return null;
        //    }
        //}
    }
}