using ServiceCenter.Extensions;
using ServiceCenter.SqlSugars;
using SqlSugar;
using System.ComponentModel;
using WCS.Core;
using WCS.Entity;
using WCS.Entity.Protocol.Station;
using WCS.WorkEngineering.Extensions;
using WCS.WorkEngineering.WebApi.Controllers;
using WCS.WorkEngineering.WebApi.Models.WMS.Response;
using WCS.WorkEngineering.Worlds;
using DeviceFlags = WCS.WorkEngineering.Extensions.DeviceFlags;
using TaskStatus = WCS.Entity.TaskStatus;

namespace WCS.WorkEngineering.Systems
{
    /// <summary>
    ///  环形库码垛区补空托盘任务生成
    /// </summary>
    [BelongTo(typeof(PalletizingWorld))]
    [Description("码垛区域生成空托盘任务")]
    public class 码垛区域生成空托盘任务 : DeviceSystem<Device<IStation520>>
    {
        protected override bool ParallelDo => true;

        public override void Do(Device<IStation520> objDev)
        {
            var lastIsTruss = objDev.Entity.GetFlag<int>("LastIsTruss");

            if (lastIsTruss == 0) //桁架用空托
            {
                objDev.Entity.SetFlag("LastIsTruss", 1);
                WCS_Palletizing palletizing = null;
                SqlSugarHelper.Do(_db =>
                {
                    var db = _db.Default;
                    //取一个时间最靠前的,没有绑定码垛工位的码垛记录
                    var palletizingInfoList = db.Queryable<WCS_Palletizing>().Where(x => x.PalletizingStation == null && !x.Finish && !x.isItHalf).OrderBy(x => x.AddTime).ToList();
                    if (!palletizingInfoList.Any())
                    {
                        World.Log("没有码垛信息可用!");
                        return;
                    }
                    foreach (var palletizingInfo in palletizingInfoList)
                    {
                        if (palletizing != null) continue;
                        //获取可以使用的放货站台信息
                        var taskAddNext = Device.All.FirstOrDefault(x => x.Code == palletizingInfo.TaskAddNext)?.Targets.FirstOrDefault()?.Targets.Where(x => x.HasFlag(DeviceFlags.桁架码垛位));
                        if (taskAddNext == null)
                        {
                            World.Log($"未找到{palletizingInfo.TaskAddNext}可去的码垛工位:{palletizingInfo.Id}");
                            continue;
                        }
                        var devs = Device.All.Where(x => taskAddNext.Contains(x)).Select(x => new Device<IStation520, IStation521, IStation523>(x, World)).ToList();
                        //获取所有的未结束且有码垛工位的码垛记录
                        var palletizingStation = db.Queryable<WCS_Palletizing>().Where(x => !x.Finish && x.PalletizingStation != null).Select(x => x.PalletizingStation).ToList();

                        //取一个可用用于码垛的地方
                        var dev = devs.Where(x => !palletizingStation.Contains(x.Entity.Code)).FirstOrDefault(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status));
                        if (dev == null)
                        {
                            World.Log("没有可用码垛工");
                            continue;
                        }

                        var addrFromCode = palletizingInfo.WarehouseCode switch
                        {
                            "1N" => "1602",
                            "1S" => "1612",
                            "2N" => "1622",
                            "2S" => "1632",
                            "3N" => "1642",
                            "3S" => "1652",
                            _ => "9999"
                        };

                        var endDev = Device.All.Where(x => x.Code == addrFromCode).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
                        if (endDev.Data.TaskNumber != 0 || endDev.Data.GoodsEnd != 0)
                        {
                            World.Log($"{endDev.Entity.Code}有残留任务信息{endDev.Data.TaskNumber}-{endDev.Data.GoodsEnd}，请确认处理!");
                            continue;
                        }

                        palletizingInfo.PalletizingStation = dev.Entity.Code;
                        db.UpdateableRowLock(palletizingInfo).UpdateColumns(x => new { x.PalletizingStation }).ExecuteCommand();
                        palletizing = palletizingInfo;
                    }
                });
                if (palletizing == null) return;
                var addrFromCode = palletizing.WarehouseCode switch
                {
                    "1N" => "1602",
                    "1S" => "1612",
                    "2N" => "1622",
                    "2S" => "1632",
                    "3N" => "1642",
                    "3S" => "1652",
                    _ => "9999"
                };
                var dev = Device.All.Where(x => x.Code == addrFromCode).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
                dev.Data.TaskNumber = palletizing.Id;
                dev.Data.GoodsEnd = palletizing.PalletizingStation!.ToShort();
            }
            else if (lastIsTruss == 1)//芯股用空托
            {
                objDev.Entity.SetFlag("LastIsTruss", 2);
                SqlSugarHelper.Do(db =>
                {
                    var taskInfo = db.Default.Queryable<WCS_TaskInfo>().Where(x => x.Status == TaskStatus.NewBuild && x.BusType == "芯股用空托盘入库").ToList();
                    var isEnd = false;
                    foreach (var info in taskInfo)
                    {
                        if (isEnd) return;
                        try
                        {
                            //通过仓库号获取对应的拆盘机位置
                            info.AddrFrom = info.WarehouseCode switch
                            {
                                "1N" => "1602",
                                "1S" => "1612",
                                "2N" => "1622",
                                "2S" => "1632",
                                "3N" => "1642",
                                "3S" => "1652",
                                _ => "9999"
                            };
                            info.Device = info.WarehouseCode switch
                            {
                                "1N" => "SRM1",
                                "1S" => "SRM2",
                                "2N" => "SRM3",
                                "2S" => "SRM4",
                                "3N" => "SRM5",
                                "3S" => "SRM6",
                                _ => info.Device
                            };

                            info.AddrNext = info.WarehouseCode switch
                            {
                                "1N" => "1604",
                                "1S" => "1614",
                                "2N" => "1624",
                                "2S" => "1634",
                                "3N" => "1644",
                                "3S" => "1654",
                                _ => info.AddrNext
                            };
                            info.SrmStation = info.WarehouseCode switch
                            {
                                "1N" => "1603",
                                "1S" => "1613",
                                "2N" => "1623",
                                "2S" => "1633",
                                "3N" => "1643",
                                "3S" => "1653",
                                _ => info.SrmStation
                            };
                            var dev = Device.All.Where(x => x.Code == info.AddrFrom).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
                            if (dev.Data.TaskNumber != 0 || dev.Data.GoodsEnd != 0)
                            {
                                World.Log($"{dev.Entity.Code}有残留任务信息 {dev.Data.TaskNumber} - {dev.Data.GoodsEnd} ，请确认处理!");
                                return;
                            }
                            info.AddrTo = "SRM";
                            info.Height = 1;
                            info.Status = TaskStatus.WaitingToExecute;
                            db.Default.UpdateableRowLock(info).UpdateColumns(x => new { x.AddrFrom, x.Device, x.AddrNext, x.SrmStation, x.Status, x.AddrTo, x.Height }).ExecuteCommand();
                            info.AddWCS_TASK_DTL(db.Default, info.Device, $"初始化芯股用空托盘入库任务信息");
                            dev.Data.TaskNumber = info.ID;
                            dev.Data.GoodsEnd = info.AddrNext.ToShort();
                            isEnd = true;
                        }
                        catch (Exception e)
                        {
                            World.Log(e.Message);
                        }
                    }
                });
            }
            else //机械臂用空托
            {
                objDev.Entity.SetFlag("LastIsTruss", 0);
                var devs = Device.All.Where(x => x.HasFlag(DeviceFlags.环形库码垛工位)).Select(x => new Device<IStation520, IStation521, IStation523>(x, World));
                devs = devs.Where(x => !x.Data3.Status.HasFlag(StationStatus.PH_Status));
                WCS_TaskInfo deliveryTask = null;
                foreach (var obj in devs)
                {
                    if (deliveryTask != null)
                    {
                        continue;
                    }
                    SqlSugarHelper.Do(_db =>
                    {
                        var db = _db.Default;
                        //检查是否有待执行状态放货点是自己的出库任务
                        var ringTask = db.Queryable<WCS_TaskInfo>().NoLock().First(x => x.Type == TaskType.OutDepot && x.Status <= TaskStatus.WaitingToExecute && x.SrmStation == obj.Entity.Code);
                        if (ringTask == null)
                        {
                            var code = obj.Entity.Code.GetWareCode();
                            var wareHouse = db.Queryable<BaseWarehouse>().First(x => x.Code == code);
                            if (wareHouse == null)
                            {
                                World.Log($"无对应仓库--[{code}]");
                                return;
                            }
                            //检查是否有满跺记录
                            var ringPalletizingInfo = db.Queryable<BillRingPalletizingInfo>().Where(x => x.WareHouseId == wareHouse.Id && x.HaveQty > 0 && !x.Out).ToList()
                                                                                             .OrderBy(x => x.AddTime).FirstOrDefault(x => x.HaveQty == x.HWCountQty || x.AddTime < DateTime.Now.AddHours(-6));
                            if (ringPalletizingInfo == null)
                            {
                                World.Log("无满跺码垛信息");
                                return;
                            }
                            //开始申请码垛任务
                            var resData = WmsApi.ApplyPalletizingStockOut(obj.Entity.Code, obj.Entity.Sources.Single(x => x.HasFlag(DeviceFlags.Robot)).Code);
                            if (resData.ResCode != ResponseStatusCodeEnum.Sucess)
                            {
                                World.Log(resData.ResMsg, ServiceCenter.Logs.LogLevelEnum.Mid);
                            }
                            return;
                        }
                        var task = db.Queryable<WCS_TaskInfo>().NoLock().First(x => x.Type == TaskType.Delivery && x.AddrTo == obj.Entity.Code && x.Status < TaskStatus.Finish);
                        if (task != null) return;
                        //开始获取当前地址上个设备的上一个设备中的非零九托盘拆机
                        var addrFrom = obj.Entity.Sources.SelectMany(x => x.Sources).Single(x => x.HasFlag(DeviceFlags.拆盘机));
                        var dev = Device.All.Where(x => x.Code == addrFrom.Code).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
                        if (dev.Data.TaskNumber != 0 || dev.Data.GoodsEnd != 0)
                        {
                            World.Log($"{dev.Entity.Code}有残留任务信息 {dev.Data.TaskNumber} - {dev.Data.GoodsEnd} ，请确认处理!");
                            return;
                        }

                        //开始创建搬运任务
                        task = new WCS_TaskInfo()
                        {
                            AddrFrom = addrFrom.Code,
                            AddrTo = obj.Entity.Code,
                            BarCode = "码垛托盘搬运-" + obj.Entity.Code,
                            Status = Entity.TaskStatus.NewBuild,
                            PalletType = ringTask.PalletType,
                            FullQty = ringTask.FullQty,
                            Type = TaskType.Delivery,
                            AddWho = "WCS",
                            AddTime = DateTime.Now
                        };
                        var res = db.InsertableRowLock(task).ExecuteReturnEntity();
                        var taskOld = res.Mapper<WCS_TaskOld, WCS_TaskInfo>();
                        taskOld.Id = res.ID;
                        taskOld.AddTime = DateTime.Now;
                        db.InsertableRowLock(taskOld).SplitTable().ExecuteCommand();
                        res.AddWCS_TASK_DTL(db, obj.Entity.Code, task.AddrTo, "初始化码垛托盘搬运任务");
                        deliveryTask = res;
                    });
                }

                if (deliveryTask == null) return;
                var dev = Device.All.Where(x => x.Code == deliveryTask.AddrFrom).Select(x => new Device<IStation520>(x, World)).FirstOrDefault();
                dev.Data.TaskNumber = deliveryTask.ID;
                dev.Data.GoodsEnd = deliveryTask.AddrTo.ToShort();
            }
        }

        public override bool Select(Device dev)
        {
            return dev.Code == nameof(PalletizCreateEmptyTray);
        }
    }

    //
    // 摘要:
    //     环形库码垛缓存信息
    [Tenant("fj")]
    [SugarTable("Bill_RingPalletizingInfo")]
    public class BillRingPalletizingInfo : BaseModel
    {
        //
        // 摘要:
        //     仓库ID
        [SugarColumn(IsNullable = false, ColumnDescription = "仓库ID")]
        public long WareHouseId { get; set; }

        //
        // 摘要:
        //     任务
        [Navigate(NavigateType.OneToOne, "WareHouseId")]
        public BaseWarehouse WareHouse { get; set; }

        //
        // 摘要:
        //     垛形主表ID
        [SugarColumn(IsNullable = false, ColumnDescription = "垛形主表ID")]
        public long BomSetGrpId { get; set; }

        //
        // 摘要:
        //     工字轮个数
        [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "工字轮个数")]
        public int HWCountQty { get; set; }

        //
        // 摘要:
        //     BomCode（投料信息）/物料号
        [SugarColumn(ColumnDataType = "nvarchar", Length = 200, IsNullable = false, ColumnDescription = "BomCode（投料信息）")]
        public string BomCode { get; set; }

        //
        // 摘要:
        //     已有工字轮个数
        [SugarColumn(ColumnDataType = "int", IsNullable = false, ColumnDescription = "已有工字轮个数")]
        public int HaveQty { get; set; }

        //
        // 摘要:
        //     是否出库
        [SugarColumn(IsNullable = false, ColumnDescription = "是否出库")]
        public bool Out { get; set; }

        //
        // 摘要:
        //     上一次分配时的放置位信息
        [SugarColumn(ColumnDataType = "int", IsNullable = true)]
        public int LastXYNO { get; set; }
    }

    //
    // 摘要:
    //     仓库表
    [Tenant("fj")]
    [SugarTable("Base_Warehouse")]
    public class BaseWarehouse : BaseModel
    {
        //
        // 摘要:
        //     是否停用
        [SugarColumn(ColumnDataType = "int", IsNullable = false)]
        public int IsStop { get; set; }

        //
        // 摘要:
        //     编号
        [SugarColumn(ColumnDataType = "nvarchar", Length = 50, IsNullable = false)]
        public string Code { get; set; }

        //
        // 摘要:
        //     名称
        [SugarColumn(ColumnDataType = "nvarchar", Length = 100, IsNullable = false)]
        public string Name { get; set; }

        ////
        //// 摘要:
        ////     类型
        //[SugarColumn(IsNullable = false)]
        //public FjLocationType TypeNum { get; set; }

        //
        // 摘要:
        //     ConfigId
        [SugarColumn(ColumnName = "ConfigId", ColumnDescription = "ConfigId")]
        public long ConfigId { get; set; }
    }
}