using Khd.Core.Domain.Dto.TaskType;
using Khd.Core.Domain.Models;
using Khd.Core.EntityFramework;
using Khd.Core.Library;
using Khd.Core.Library.Mapper;
using Khd.Core.Plc.S7;
using Khd.Core.Wcs.Global;
using Masuit.Tools;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Z.EntityFramework.Plus;

namespace Khd.Core.Wcs.Wcs
{
    /// <summary>
    /// 三楼接驳位调度
    /// </summary>
    public class ThirdFloorPoint
    {
        private readonly LoggerUtils _logger = new LoggerUtils();
        private readonly IHost _host;
        private readonly BasePlcpoint LineRFID;
        private readonly BasePlcpoint LineSignal;
        int FloorNo { get; set; }
        public ThirdFloorPoint(IHost host, int floor)
        {
            this._host = host;
            FloorNo = floor;
            this.LineRFID = StaticData.BasePlcpointList.First(t => t.plcpointNo == "RFID003");
            this.LineSignal = StaticData.BasePlcpointList.First(t => t.plcpointNo == "linesignal03");
        }
        /// <summary>
        /// 启动上件扫描监听
        /// </summary>
        public void StartPoint()
        {

            Thread FlowPointThread = new Thread(MonitorInLocatorPoint);
            FlowPointThread.IsBackground = true;
            FlowPointThread.Name = "ThirdFloorPoint";
            FlowPointThread.Start();
            Console.WriteLine(DateTime.Now + ":三楼接驳位调度启动成功");
            _logger.Info("三楼接驳位调度启动成功");
        }

        public void MonitorInLocatorPoint()
        {
            List<int> ITypes = new List<int> { 1, 3, 5, 7 };
            using var scope = _host.Services.CreateScope();
            using var dbContext = scope.ServiceProvider.GetRequiredService<DefaultDbContext>();
            List<string> canNotIn = new List<string>();
            while (true)
            {
                try
                {
                    dbContext.ChangeTracker.Entries().ToList().ForEach(e => e.Reload());
                    //入库任务
                    var rfid = StaticData.PlcDic[0].ReadRFID(LineRFID.plcpointAddress);
                    var isSignal = StaticData.PlcDic[0].Read(LineSignal.plcpointAddress);
                    if (rfid != null && isSignal != null)
                    {
                        if (Convert.ToInt32(isSignal) == 1)//托盘到位
                        {
                            BaseEquip baseEquip = StaticData.BaseEquip.First(t => t.floorNo == 3 && t.equipType == 1);
                            var wcsTask = dbContext.WcsTask.FirstOrDefault(t => t.nextPointId == baseEquip.objid);
                            var AgvEquip = StaticData.BaseEquip.First(t => t.floorNo == 3 && t.equipType == 4);//背负Agv
                            if (wcsTask != null)//如果不是null
                            {
                                if (wcsTask.taskStatus == 5)//提升机任务是完成状态
                                {
                                    lock (SystemData.ThirdTaskLock)
                                    {
                                        MesBasePalletInfo? mesBasePalletInfo = dbContext.MesBasePalletInfo.Where(t => t.palletInfoCode == rfid).FirstOrDefault();
                                        if (mesBasePalletInfo != null)
                                        {
                                            MesBaseBarcodeInfo? mesBaseBarcodeInfo = dbContext.MesBaseBarcodeInfo.FirstOrDefault(t => t.barcodeInfo == mesBasePalletInfo.materialBarcode);
                                            if (mesBaseBarcodeInfo != null)
                                            {
                                                // 目标库位
                                                WmsBaseLocation? wmsBaseLocation = null;
                                                var wmsBaseLocations = dbContext.WmsBaseLocation
                                                           .Where(t => t.warehouseFloor == FloorNo)
                                                           .Where(t => t.activeFlag == "1")
                                                           .Where(t => t.delFlag == "0")
                                                           .Where(t => t.locationScrapType == "1")
                                                           .Where(t => t.locationStatus == "1")
                                                           .Where(t => t.warehouseId == 311)
                                                           .ToList();//所有未锁定的库位

                                                //深库位有库存的库位
                                                List<string> DeepContainerCodes = wmsBaseLocations
                                                           .Where(t => t.locDeep == 1)
                                                           .Where(t => !string.IsNullOrEmpty(t.containerCode))
                                                           .Select(t => t.containerCode).ToList();

                                                //相同型号及销售订单的深库位库存
                                              
                                                List<WmsRawStock> wmsRawStocks = dbContext.WmsRawStock.Where(t => t.materialId == mesBaseBarcodeInfo.materialId)
                                                  .Where(t => t.saleOrderId == mesBaseBarcodeInfo.saleOrderId)  
                                                   .Where(t => DeepContainerCodes.Contains(t.palletInfoCode))
                                                  .Where(t => t.warehouseId == 311).ToList();
                                                if (wmsRawStocks.Count > 0)
                                                { //优先找同销售订单的有库存的深库位对应的浅库位
                                                    foreach (var wmsRawStock in wmsRawStocks)
                                                    {
                                                        // 深库位库存对用的Location信息
                                                        var deepStockLocation = wmsBaseLocations.Where(t => t.containerCode == wmsRawStock.palletInfoCode).FirstOrDefault();
                                                        wmsBaseLocation = wmsBaseLocations.Where(t => string.IsNullOrEmpty(t.containerCode) && t.locationStatus == "1")
                                                            .Where(t => t.locDeep == 2 && t.locColumn == deepStockLocation.locColumn)
                                                            .Where(t => t.locRow == (deepStockLocation.locRow % 2 == 0 ? (deepStockLocation.locRow - 1) : (deepStockLocation.locRow + 1)))
                                                            .FirstOrDefault();
                                                        if (wmsBaseLocation != null)
                                                        {
                                                            break;
                                                        }
                                                    }
                                                }
                                                if (wmsBaseLocation == null)
                                                {  // 找深库位有库存的库位对应的浅库位
                                                    var stockLocations = wmsBaseLocations.Where(x => !string.IsNullOrEmpty(x.containerCode) && x.locDeep == 1).ToList();
                                                    foreach (var item in stockLocations)
                                                    {
                                                        wmsBaseLocation = wmsBaseLocations.Where(t => string.IsNullOrEmpty(t.containerCode) && t.locationStatus == "1")
                                                          .Where(t => t.locDeep == 2 && t.locColumn == item.locColumn)
                                                          .Where(t => t.locRow == (item.locRow % 2 == 0 ? (item.locRow - 1) : (item.locRow + 1)))
                                                          .FirstOrDefault();
                                                        if (wmsBaseLocation != null)
                                                        {
                                                            break;
                                                        }
                                                    }
                                                }
                                                if (wmsBaseLocation == null)
                                                {  // 在所有符合条件的库位里，找一个库位，优先深库位,但是如果是深库位，需要判断浅库位状态是否正常
                                                    var searchLocations = wmsBaseLocations.Where(x => string.IsNullOrEmpty(x.containerCode) && x.locationStatus == "1").OrderBy(x => x.locDeep).ToList();
                                                    foreach (var item in searchLocations)
                                                    {
                                                        if (item.locDeep == 1)
                                                        {
                                                            //浅库位能否使用
                                                            var shallowLocation = wmsBaseLocations.Where(t => string.IsNullOrEmpty(t.containerCode) && t.locationStatus == "1")
                                                            .Where(t => t.locDeep == 2 && t.locColumn == item.locColumn)
                                                            .Where(t => t.locRow == (item.locRow % 2 == 0 ? (item.locRow - 1) : (item.locRow + 1)))
                                                            .FirstOrDefault();
                                                            if (shallowLocation != null)
                                                            {
                                                                wmsBaseLocation = item;
                                                                break;
                                                            }
                                                        }
                                                        else
                                                        {
                                                            wmsBaseLocation = item;
                                                            break;
                                                        }

                                                    }
                                                }

                                                if ( wmsBaseLocation != null)
                                                {
                                                   
                                                    dbContext.Remove(wcsTask);
                                                    WcsTask newTask = CoreMapper.Map<WcsTask>(wcsTask);
                                                    newTask.objid = StaticData.SnowId.NextId();
                                                    newTask.taskStatus = 0;//创建状态
                                                    newTask.updateTime = DateTime.Now;
                                                    newTask.currPointId = baseEquip.objid;
                                                    newTask.currPointNo = baseEquip.equipNo;
                                                    newTask.nextPointId = AgvEquip.objid;
                                                    newTask.nextPointNo = AgvEquip.equipNo;
                                                    newTask.endPointId = wmsBaseLocation.locationId;
                                                    newTask.endPointNo = wmsBaseLocation.locationCode;
                                                    newTask.taskType = StaticTaskType.ThirdRawIn;
                                                    newTask.useFlag = 1;
                                                    wmsBaseLocation.locationStatus = "2";
                                                    SystemData.LockOutLocation(wmsBaseLocation, dbContext);
                                                    dbContext.Update(wmsBaseLocation);
                                                    dbContext.Add(newTask);
                                                    WcsTaskLog wcsTaskLog = CoreMapper.Map<WcsTaskLog>(newTask);
                                                    dbContext.Add(wcsTaskLog);
                                                    dbContext.SaveChanges();
                                                    canNotIn.Clear();
                                                    Console.WriteLine(DateTime.Now + $":三楼接驳位调度入库任务,物料{mesBaseBarcodeInfo.materialId},托盘{rfid},库位{wmsBaseLocation.locationCode}");
                                                    _logger.Info($"三楼接驳位调度入库任务,物料{mesBaseBarcodeInfo.materialId},托盘{rfid},库位{wmsBaseLocation.locationCode}");
                                                }
                                                else
                                                {
                                                    Console.WriteLine(DateTime.Now + ":三楼楼接驳位调度入库任务,未找到库位");
                                                    _logger.Info("三楼接驳位调度入库任务,未找到库位");
                                                    // TODO: 没有找到库位,添加报警处理
                                                    Thread.Sleep(1000 * 5);
                                                   
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (wcsTask.taskStatus == 6)//小车任务是完成状态，说明是出库
                                {
                                    BaseEquip nextEquip = StaticData.BaseEquip.First(t => t.equipType == 2);//提升机
                                    dbContext.Remove(wcsTask);
                                    WcsTask newTask = CoreMapper.Map<WcsTask>(wcsTask);
                                    newTask.objid = StaticData.SnowId.NextId();
                                    newTask.containerNo = rfid;
                                    newTask.nextPointId = nextEquip.objid;
                                    newTask.nextPointNo = nextEquip.equipNo;
                                    newTask.currPointId = baseEquip.objid;
                                    newTask.currPointNo = baseEquip.equipNo;
                                    newTask.fromFloorNo = FloorNo;
                                    newTask.taskStatus = 0;
                                    newTask.updateTime = DateTime.Now;
                                    dbContext.Add(newTask);
                                    WcsTaskLog wcsTaskLog = CoreMapper.Map<WcsTaskLog>(newTask);
                                    dbContext.Add(wcsTaskLog);
                                    dbContext.SaveChanges();
                                }
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (ex is PlcException)
                    {

                    }
                    else
                    {
                        _logger.Error(ex.Message + "\n" + ex.StackTrace);
                    }
                }
                finally
                {
                    Thread.Sleep(1000);
                }
            }
        }
    }
}
