using Microsoft.Data.SqlClient;
using SqlSugar;
using WCS.BLL.Config;
using WCS.BLL.DbModels;
using WCS.BLL.Manager;
using WCS.BLL.Services.IService;
using WCS.BLL.Tool;
using WCS.DAL.Db;
using WCS.DAL.DbModels;
using WCS.Model;
using WCS.Model.ApiModel.InOutRecord;
using WCS.Model.ApiModel.MatInventoryDetail;
using WCS.Model.ApiModel.OutStore;

namespace WCS.BLL.Services.Service
{
    public class OutstoreService : IOutstoreService
    {
        public OutstoreService()
        {

        }
        public async Task<ResponseCommon<List<MatInventorySummaryModel>>> importMat(List<OutImportMatModel> list)
        {
            //数据校验
            if (list == null || list.Count == 0)
            {
                return new ResponseCommon<List<MatInventorySummaryModel>>()
                {
                    Code = 201,
                    Message = "导入失败：导入文件中没有内容！"
                };
            }
            //需求数量
            var errorCount = list.Where(t => t.需求数量 <= 0).ToList();
            if (errorCount != null && errorCount.Count > 0)
            {
                return new ResponseCommon<List<MatInventorySummaryModel>>()
                {
                    Code = 201,
                    Message = "导入失败：需求数量需要大于0！"
                };
            }
            //每一个物料进行搜索库存
            var returnList = new List<MatInventorySummaryModel>();
            foreach (var item in list)
            {
                var inventoryCount = await DbHelp.db.Queryable<InventoryDetail>()
                                              .Where(t => t.MatCode == item.物料编码)
                                              .Where(t => t.MatBatch == item.物料批次)
                                              .Where(t => t.IsLocked == false)
                                              .SumAsync(t => t.MatQty);
                var info = inventoryCount < item.需求数量 ? "库存数量小于需求数量" : string.Empty;
                returnList.Add(new MatInventorySummaryModel()
                {
                    MatCode = item.物料编码,
                    MatName = item.物料名称,
                    MatBatch = item.物料批次,
                    NeedQty = item.需求数量,
                    TotalQty = inventoryCount,
                    Info = info
                });
            }
            return new ResponseCommon<List<MatInventorySummaryModel>>()
            {
                Code = 200,
                Data = returnList
            };
        }
        public async Task<ResponseBase> SysOutOrderByMatCode(SysOutOrderByMatCodeRequest request)
        {
            //参数合法性校验
            if (request.ItemList == null || request.ItemList.Count == 0)
            {
                return new ResponseBase()
                {
                    Code = 201,
                    Message = "出库单据同步失败：缺少需要出库的物料类型！"
                };
            }

            //保存数据
            await DbHelp.db.BeginTranAsync();
            try
            {
                var order = new OutOrder()
                {
                    OrderNumber = request.OrderNumber,
                    OrderSource = request.OrderSource,
                    OrderType = request.OrderType,
                    ShelfTypeId = request.ShelfTypeId,
                    ShelfTypeName = request.ShelfTypeName,
                    SyncType = SyncTypeEnum.ByMatCode,
                    GroupName = LocalFile.Config.GroupName,
                    CreateUser = request.UserName,
                };
                order.Id = await DbHelp.db.Insertable(order).ExecuteReturnIdentityAsync();
                request.ItemList.ForEach(async item =>
                {
                    var orderDetail = new OutOrderDetail()
                    {
                        OrderId = order.Id,
                        OrderNumber = order.OrderNumber,
                        MatCode = item.MatCode,
                        MatName = item.MatName,
                        MatBatch = item.MatBatch,
                        ReqQty = item.ReqQty,
                        OutQty = 0,
                        CreateUser = request.UserName
                    };
                    await DbHelp.db.Insertable(orderDetail).ExecuteCommandAsync();
                });
                await DbHelp.db.CommitTranAsync();
                return new ResponseCommon()
                {
                    Code = 200,
                    Message = $"出库单据同步成功！\r\n出库单据号为{request.OrderNumber}",
                    Data = request.OrderNumber
                }; ;
            }
            catch (Exception ex)
            {
                await DbHelp.db.RollbackTranAsync();
                Console.WriteLine(ex.Message);
                return new ResponseBase()
                {
                    Code = 200,
                    Message = $"出库单据同步失败：{ex.Message}"
                };
            }
        }

        public async Task<ResponseBase> SysOutOrderByMatSn(SysOutOrderByMatSnRequest request)
        {

            //参数合法性校验
            if (request.SnList == null || request.SnList.Count == 0)
            {
                return new ResponseBase()
                {
                    Code = 201,
                    Message = "出库单据同步失败：缺少物料明细！"
                };
            }
            //标准版逻辑-库存有无校验 & 库存已锁校验
            if (!LocalFile.Config.IsMx)
            {
                try
                {
                    await DbHelp.db.BeginTranAsync();
                    var inventoryDetails = await DbHelp.db.Queryable<InventoryDetail>()
                                                .Where(t => request.SnList.Contains(t.MatSN))
                                                .TranLock(DbLockType.Wait)
                                                .ToListAsync();
                    if (inventoryDetails.Count < request.SnList.Count)//库存的物料少于需求的物料数量
                    {
                        var existsSns = inventoryDetails.Select(t => t.MatSN).ToList();
                        request.SnList.RemoveAll(t => existsSns.Contains(t));
                        await DbHelp.db.RollbackTranAsync();
                        //返回提示哪些物料库存不存在
                        return new ResponseCommon()
                        {
                            Code = 201,
                            Message = "出库单据同步失败：存在物料不在库存中！",
                            Data = request.SnList

                        };
                    }
                    else if (inventoryDetails.Where(t => t.IsLocked).Any())
                    {
                        await DbHelp.db.RollbackTranAsync();
                        //返回提示哪些物料库存已被锁定
                        return new ResponseCommon()
                        {
                            Code = 201,
                            Message = "出库单据同步失败：存在物料被锁定！",
                            Data = inventoryDetails.Where(t => t.IsLocked).Select(t => t.MatSN).ToList()
                        };
                    }

                    #region 保存数据

                    //锁库存
                    inventoryDetails.ForEach(t =>
                    {
                        t.IsLocked = true;
                    });
                    var lockTask = DbHelp.db.Updateable(inventoryDetails).ExecuteCommandAsync();

                    //保存数据
                    var order = new OutOrder()
                    {
                        OrderNumber = request.OrderNumber,
                        OrderSource = request.OrderSource,
                        OrderType = request.OrderType,
                        SyncType = SyncTypeEnum.ByMatSn,
                        CreateUser = request.UserName,
                        GroupName = LocalFile.Config.GroupName,
                    };
                    order.Id = await DbHelp.db.Insertable(order).ExecuteReturnIdentityAsync();

                    //通过库存数据保存出库物料明细表
                    var matDetailTasks = inventoryDetails.Select(async t =>
                    {
                        var orderMatDetail = new OutOrderMatDetail()
                        {
                            OrderId = order.Id,
                            OrderNumber = order.OrderNumber,
                            InventoryDetailId = t.Id,
                            StoreId = t.StoreId,
                            StoreCode = t.StoreCode,
                            MatSN = t.MatSN,
                            MatCode = t.MatCode,
                            MatName = t.MatName,
                            MatSpec = t.MatSpec,
                            MatBatch = t.MatBatch,
                            MatQty = t.MatQty,
                            MatSupplier = t.MatSupplier,
                            MatCustomer = t.MatCustomer,
                            CreateUser = request.UserName,
                        };
                        await DbHelp.db.Insertable(orderMatDetail).ExecuteCommandAsync();
                    }).ToList();

                    await lockTask;
                    await Task.WhenAll(matDetailTasks);

                    await DbHelp.db.CommitTranAsync();
                    return new ResponseCommon()
                    {
                        Code = 200,
                        Message = $"出库单据同步成功！\r\n出库单据号为{request.OrderNumber}",
                        Data = order.Id
                    };
                    #endregion
                }
                catch (Exception ex)
                {
                    await DbHelp.db.RollbackTranAsync();
                    return new ResponseBase()
                    {
                        Code = 201,
                        Message = $"出库单据同步失败：{ex.Message}"
                    };
                }
            }
            //盟讯公司逻辑 不锁库存 直接保存数据/清除未发送的
            else
            {
                try
                {
                    DbHelp.db.BeginTran();
                    //1. 获取库存物料明细
                    var inventoryDetails = await DbHelp.db.Queryable<InventoryDetail>()
                                .Where(t => request.SnList.Contains(t.MatSN))
                                .ToListAsync();
                    if (inventoryDetails == null || inventoryDetails.Count == 0)
                    {
                        return new ResponseCommon()
                        {
                            Code = 201,
                            Message = "保存出库单失败！请重试!",
                            Data = request.SnList
                        };
                    }
                    //2. 先获取对应单号是否已经保存
                    var outOrder = DbHelp.db.Queryable<OutOrder>()
                        .Where(t => t.OrderNumber == request.OrderNumber)
                        .Where(t => t.GroupName == LocalFile.Config.GroupName)
                        .First();
                    //数据库中没有才添加
                    if (outOrder == null)
                    {
                        //OutOrder
                        outOrder = new OutOrder()
                        {
                            OrderNumber = request.OrderNumber,
                            OrderType = request.OrderType,
                            OutOrderExeStatus = OutOrderExeStatus.开始发料,
                            OrderSource = "WCS前端",
                            SyncType = SyncTypeEnum.ByMatSn,
                            ShelfTypeName = "智能货架",
                            ShelfTypeId = 0,
                            GroupName = LocalFile.Config.GroupName,
                            IsMXPD = request.IsMXPD,
                        };
                        outOrder.Id = await DbHelp.db.Insertable(outOrder).ExecuteReturnIdentityAsync();
                        outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.OrderNumber == request.OrderNumber)
                                                                  .Where(t => t.Id == outOrder.Id)
                                                                  .FirstAsync();
                        //保存单据失败了
                        if (outOrder == null)
                            return new ResponseCommon()
                            {
                                Code = 201,
                                Message = "保存出库单失败！保存Order失败！",
                                Data = request.SnList
                            };

                        //出库物料明细
                        foreach (var item in inventoryDetails)
                        {
                            var orderMatDetail = new OutOrderMatDetail()
                            {
                                OrderId = outOrder.Id,
                                OrderNumber = outOrder.OrderNumber,
                                InventoryDetailId = item.Id,
                                StoreId = item.StoreId,
                                StoreCode = item.StoreCode,
                                MatSN = item.MatSN,
                                MatCode = item.MatCode,
                                MatName = item.MatName,
                                MatSpec = item.MatSpec,
                                MatBatch = item.MatBatch,
                                MatQty = item.MatQty,
                                MatSupplier = item.MatSupplier,
                                MatCustomer = item.MatCustomer,
                                CreateUser = request.UserName,
                                IsMXPD = request.IsMXPD,
                            };
                            await DbHelp.db.Insertable(orderMatDetail).ExecuteCommandAsync();
                        }
                        DbHelp.db.CommitTran();
                    }
                    //数据库已有该Order
                    else
                    {
                        outOrder.CreateTime = DateTime.Now;
                        DbHelp.db.Updateable(outOrder).ExecuteCommand();
                        //删除未出库的
                        var outOrderDetails = DbHelp.db.Deleteable<OutOrderMatDetail>()
                                                       .Where(t => t.OrderId == outOrder.Id)
                                                       .Where(t => t.IsSended == false)
                                                       .ExecuteCommand();
                        //当前已出库的 //已出库的也不在库存中了 应该查询不到了
                        //避免影响效率 就不查重了
                        foreach (var item in inventoryDetails)
                        {
                            var orderMatDetail = new OutOrderMatDetail()
                            {
                                OrderId = outOrder.Id,
                                OrderNumber = outOrder.OrderNumber,
                                InventoryDetailId = item.Id,
                                StoreId = item.StoreId,
                                StoreCode = item.StoreCode,
                                MatSN = item.MatSN,
                                MatCode = item.MatCode,
                                MatName = item.MatName,
                                MatSpec = item.MatSpec,
                                MatBatch = item.MatBatch,
                                MatQty = item.MatQty,
                                MatSupplier = item.MatSupplier,
                                MatCustomer = item.MatCustomer,
                                CreateUser = request.UserName,
                                IsMXPD = request.IsMXPD,
                            };
                            await DbHelp.db.Insertable(orderMatDetail).ExecuteCommandAsync();
                        }
                        DbHelp.db.CommitTran();

                        //更新订单状态
                        Task.Run(() =>
                        {
                            if (outOrder != null)
                            {
                                #region 物料明细表是否已发完
                                var orderMatDetails = DbHelp.db.Queryable<OutOrderMatDetail>()
                                                              .Where(t => t.OrderId == outOrder.Id)
                                                              .ToList();
                                var isExistNoSendMat = orderMatDetails.Where(t => t.IsSended == false)
                                                                   .Any();
                                if (isExistNoSendMat)
                                {
                                    outOrder.OrderStatus = OutOrderStatus.部分发料;
                                }
                                else
                                {
                                    outOrder.OrderStatus = OutOrderStatus.全部发料;
                                    outOrder.OutOrderExeStatus = OutOrderExeStatus.发料完成;
                                }
                                #endregion
                                DbHelp.db.Updateable(outOrder).ExecuteCommand();
                            }
                        });
                    }
                    return new ResponseCommon()
                    {
                        Code = 200,
                        Message = outOrder.OrderNumber,
                        Data = request.SnList
                    };

                }
                catch (Exception ex)
                {
                    DbHelp.db.RollbackTran();
                    Logs.Write($"同步出库单据发生异常{ex.Message}", LogsType.Info);
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"保存出库单失败！{ex.Message}！",
                        Data = request.SnList
                    };
                }

            }

        }

        public async Task<ResponseBase> GetOutOrderList(GetOutOrderListRequest request)
        {
            //直接查询
            var recordsQueryable = DbHelp.db.Queryable<OutOrder>()
                                            .WhereIF(!string.IsNullOrEmpty(request.OrderNumber), t => t.OrderNumber.Contains(request.OrderNumber))
                                            .WhereIF(!string.IsNullOrEmpty(request.OrderSource), t => t.OrderSource.Contains(request.OrderSource))
                                            .WhereIF(!string.IsNullOrEmpty(request.OrderType), t => t.OrderType.Contains(request.OrderType))
                                            .WhereIF(request.ShelfTypeId != 0, t => t.ShelfTypeId == request.ShelfTypeId);

            var totalCount = await recordsQueryable.CountAsync();
            var records = await recordsQueryable
                                .OrderByDescending(t => t.Id)
                                .Skip((request.PageNumber - 1) * request.PageSize).Take(request.PageSize)
                                .ToListAsync();
            //生成序号
            for (int i = 0; i < records.Count; i++)
            {
                records[i].RowNumber = (request.PageNumber - 1) * request.PageSize + i + 1;
            }

            return new PageQueryResponse<OutOrder>()
            {
                Code = 200,
                Message = $"success",
                Data = new PageQueryResponseData<OutOrder>()
                {
                    TotalCount = totalCount,
                    MaxPage = request.PageSize == 0 ? 0 : (int)Math.Ceiling((decimal)totalCount / request.PageSize),
                    Count = records.Count,
                    Lists = records.ToList()
                }
            };
        }

        public async Task<ResponseBase> GetOutOrderListByStatus(GetOutOrderListByStatusRequest request)
        {
            if (request.OrderExeStatus == null || request.OrderExeStatus.Count == 0)
            {
                //不传入状态不显示
                return new PageQueryResponse<OutOrder>()
                {
                    Code = 200,
                    Message = $"success",
                    Data = new PageQueryResponseData<OutOrder>()
                    {
                        Lists = new List<OutOrder>()
                    }
                };
            }
            //直接查询
            var recordsQueryable = DbHelp.db.Queryable<OutOrder>()
                                            .Where(t => request.OrderExeStatus.Contains(t.OutOrderExeStatus))
                                            .WhereIF(request.IsMXPD != null, t => t.IsMXPD == request.IsMXPD)
                                            .WhereIF(LocalFile.Config.IsMx, t => t.CreateTime > DateTime.Now.AddDays(-3))
                                            .WhereIF(!string.IsNullOrEmpty(LocalFile.Config.GroupName), t => t.GroupName == LocalFile.Config.GroupName);

            var totalCount = await recordsQueryable.CountAsync();
            var records = await recordsQueryable
                                .OrderByDescending(t => t.CreateTime)
                                .ToListAsync();

            //获取后台当前正在进行出库的订单 将出库状态反馈给前端
            var outingOrderNumbers = ShelfManager.Shelves
                                                .Where(t => t.CurrentMode == HardWare.Mode.出库模式)
                                                .Select(t => t.OrderNumber)
                                                .ToList();
            foreach (var record in records)
            {
                if (outingOrderNumbers.Contains(record.OrderNumber))
                    record.IsOuting = true;
            }

            return new PageQueryResponse<OutOrder>()
            {
                Code = 200,
                Message = $"success",
                Data = new PageQueryResponseData<OutOrder>()
                {
                    Lists = records.ToList()
                }
            };
        }
        public async Task<ResponseBase> GetOutOrderDetail(GetOutOrderDetailRequest request)
        {
            OutOrder outOrder = null;

            #region 查询出库单
            if (request.OrderId != 0)
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.Id == request.OrderId).FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在Id为{request.OrderId}的出库单！",
                    };
                }
            }
            else if (!string.IsNullOrEmpty(request.OrderNumber))
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.OrderNumber == request.OrderNumber)
                                                                .FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在出库单据号为{request.OrderNumber}的出库单！",
                    };
                }
            }
            else
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"查询失败：缺少必要参数！",
                };
            }
            #endregion

            #region 查询出库单明细
            var orderDetailTask = DbHelp.db.Queryable<OutOrderDetail>()
                                        .Where(t => t.OrderId == outOrder.Id)
                                        .ToListAsync();
            var orderDetail = await orderDetailTask;
            //生成序号
            for (int i = 0; i < orderDetail.Count; i++)
            {
                orderDetail[i].RowNumber = i + 1;
            }
            #endregion

            return new ResponseCommon<List<OutOrderDetail>>()
            {
                Code = 200,
                Message = "Success",
                Data = orderDetail
            };
        }

        /// <summary>
        /// 单灯查询物料明细  PDA要求返回数据种data需要增加一层details
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<ResponseBase> GetOutOrderDetailSingleLight(GetOutOrderDetailRequest request)
        {
            OutOrder outOrder = null;

            #region 查询出库单
            if (request.OrderId != 0)
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.Id == request.OrderId).FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在Id为{request.OrderId}的出库单！",
                    };
                }
            }
            else if (!string.IsNullOrEmpty(request.OrderNumber))
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.OrderNumber == request.OrderNumber)
                                                                .FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在出库单据号为{request.OrderNumber}的出库单！",
                    };
                }
            }
            else
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"查询失败：缺少必要参数！",
                };
            }
            #endregion

            #region 查询出库单明细
            var orderDetailTask = DbHelp.db.Queryable<OutOrderDetail>()
                                        .Where(t => t.OrderId == outOrder.Id)
                                        .ToListAsync();
            var orderDetail = await orderDetailTask;
            //生成序号
            for (int i = 0; i < orderDetail.Count; i++)
            {
                orderDetail[i].RowNumber = i + 1;
            }
            #endregion

            return new ResponseCommonModify<OutOrderDetail>()
            {
                Code = 200,
                Message = "Success",
                Data = new ResponseCommonDataDetail<OutOrderDetail>
                {
                    Details = orderDetail
                }
            };
        }

        public async Task<ResponseBase> GetOutOrderMatDetail(GetOutOrderDetailRequest request)
        {
            OutOrder outOrder = null;

            #region 查询出库单
            if (request.OrderId != 0)
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.Id == request.OrderId).FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在Id为{request.OrderId}的出库单！",
                    };
                }
            }
            else if (!string.IsNullOrEmpty(request.OrderNumber))
            {
                outOrder = await DbHelp.db.Queryable<OutOrder>().Where(t => t.OrderNumber == request.OrderNumber)
                                                                .FirstAsync();
                if (outOrder == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"查询失败：不存在出库单据号为{request.OrderNumber}的出库单！",
                    };
                }
            }
            else
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"查询失败：缺少必要参数！",
                };
            }
            #endregion

            #region 出库物料明细
            var orderMatDetailTask = DbHelp.db.Queryable<OutOrderMatDetail>()
                            .Where(t => t.OrderId == outOrder.Id)
                            .ToListAsync();
            var orderMatDetail = await orderMatDetailTask;
            //生成序号
            for (int i = 0; i < orderMatDetail.Count; i++)
            {
                orderMatDetail[i].RowNumber = i + 1;
            }
            #endregion


            return new ResponseCommon<List<OutOrderMatDetail>>
            {
                Code = 200,
                Message = outOrder.OrderStatus.ToString(),
                Data = orderMatDetail
            };
        }

        public async Task<ResponseBase> GoInOutstore(GetOutOrderDetailRequest request)
        {
            try
            {
                //获取出库单
                var order = await DbHelp.db.Queryable<OutOrder>()
                                     .WhereIF(request.OrderId != 0, t => t.Id == request.OrderId)
                                     .WhereIF(!string.IsNullOrEmpty(request.OrderNumber), t => t.OrderNumber == request.OrderNumber)
                                     .FirstAsync();
                if (order == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"不存在对应的出库单据{request.OrderNumber}！",
                        Data = null
                    };
                }


                //如果是按物料编码出库  需要计算物料明细、并进行物料锁定
                if (order.SyncType == SyncTypeEnum.ByMatCode)
                {
                    var result = CaculateOutOrderMatDetails(order, request.UserName);
                    if (result.Code != 200)
                    {
                        return result;
                    }
                }

                //获取需要出库的物料明细
                var outOrderMatDetails = DbHelp.db.Queryable<OutOrderMatDetail>()
                                                  .Where(t => t.OrderId == order.Id)
                                                  .Where(t => t.IsSended == false)
                                                  .Includes(t => t.StoreInfo)
                                                  .ToList();
                if (outOrderMatDetails == null || outOrderMatDetails.Count == 0)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"出库单据{request.OrderNumber}物料已全部完成出库！",
                        Data = null
                    };
                }

                if (request.IsStart)
                {
                    order.OutOrderExeStatus = OutOrderExeStatus.开始发料;
                    DbHelp.db.Updateable(order).ExecuteCommand();
                }

                //按货架分组 按物料找到对应的货架
                var shelfIds = outOrderMatDetails.Select(t => t.StoreInfo.ShelfId)
                                                 .Distinct()
                                                 .ToList();
                var shelfs = ShelfManager.Shelves.Where(t => shelfIds.Contains(t.ShelfId)).ToList(); ;

                var outherModeShelfs = shelfs.Where(t => t.CurrentMode != HardWare.Mode.待机模式).Select(t => t.ShelfCode).ToList();
                if (outherModeShelfs != null && outherModeShelfs.Count > 0)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"进入出库模式失败：货架{string.Join("", outherModeShelfs)}不在待机模式",
                        Data = null
                    };
                }
                //看是否是分批次出库的情况 分批次亮灯
                if (LocalFile.Config.IsSameMatCodeOut)
                {
                    //最先亮的颜色为绿色
                    LocalStatic.CurrentOutStoreColor = 0x02;

                    var outOrderDetailCount = outOrderMatDetails.GroupBy(t => t.MatCode)
                                             .Select(o => new { count = o.Count(), bb = o })
                                             .Where(o => o.count >= 2)
                                             .OrderByDescending(o => o.count)
                                             .ToList();
                    //相同物料存在盘数超过2的情况，亮下一个盘数多的物料
                    if (outOrderDetailCount.Count > 0)
                    {
                        var matCode = outOrderDetailCount.First().bb.Key;
                        outOrderMatDetails = outOrderMatDetails.Where(t => t.MatCode == matCode)
                                                         .ToList();
                        Logs.Write($"出库单{order.OrderNumber}，本次亮灯物料{matCode}！", LogsType.Outstore);

                        //分批次亮灯再计算一次出哪些货架 以免亮大灯不亮小灯
                        shelfIds = outOrderMatDetails.Select(t => t.StoreInfo.ShelfId)
                                                         .Distinct()
                                                         .ToList();
                        shelfs = ShelfManager.Shelves.Where(t => shelfIds.Contains(t.ShelfId)).ToList();
                    }
                    //相同物料不存在盘数超过n的情况，剩余物料全部亮灯
                    else
                    {
                        //剩余物料全出
                        Logs.Write($"出库单{order.OrderNumber}，剩余物料灯全亮！", LogsType.Outstore);
                    }


                }

                //对应的货架对应位置 进入出库模式 亮灯
                shelfs.ForEach(shelf =>
                {
                    var matDetails = outOrderMatDetails.Where(t => t.StoreInfo.ShelfCode == shelf.ShelfCode)
                                                        .Distinct()
                                                        .ToList();
                    shelf.GoInOutstore(matDetails, order, request.UserName);
                    shelf.OrderNumber = order.OrderNumber;
                    Logs.Write($"出库单{order.OrderNumber}，货架{shelf.ShelfCode}进入出库模式！", LogsType.Outstore);
                });

                //返回
                return new ResponseCommon()
                {
                    Code = 200,
                    Message = "Success",
                    Data = null
                };
            }
            catch (Exception ex)
            {
                Logs.Write($"本次发料发生异常！{ex.Message}", LogsType.Outstore);
                await GoOutOutstore(request);
                throw ex;
            }
        }

        //计算、加锁
        private ResponseBase CaculateOutOrderMatDetails(OutOrder order, string createUser = "")
        {
            try
            {
                DbHelp.db.BeginTran();
                //第一步 物料需求表
                var outOrderDetails = DbHelp.db.Queryable<OutOrderDetail>()
                                                 .Where(t => t.OrderId == order.Id)
                                                 .ToList();
                if (outOrderDetails == null || outOrderDetails.Count == 0)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"计算物料失败，{order.OrderNumber}没有出库单据明细！"
                    };
                }
                //第二步 开始计算物料
                List<OutOrderMatDetail> outOrderMatDetails = new List<OutOrderMatDetail>();
                foreach (var outOrderDetail in outOrderDetails)
                {
                    //2.1筛选 满足 物料编码、批次的库存
                    var matInventoryDetails = DbHelp.db.Queryable<InventoryDetail>()
                             .Where(t => t.MatCode == outOrderDetail.MatCode)
                             .WhereIF(!string.IsNullOrEmpty(outOrderDetail.MatBatch), t => t.MatBatch == outOrderDetail.MatBatch)
                             .Where(t => t.IsLocked == false)//未锁定的物料
                             .Where(t => t.StoreInfo.ShelfTypeId == order.ShelfTypeId)
                             .OrderBy(t => t.MatBatch)//按批次先进先出
                                                      //(t => t.MatQty)//零散料先出
                             .ToList();

                    //2.2按照搜索出来的库存和当前未出的数量 计算需要出的SN
                    for (int i = 0; i < matInventoryDetails.Count && outOrderDetail.ReqQty - outOrderDetail.OutQty > 0; i++)
                    {
                        if (outOrderDetail.ReqQty - outOrderDetail.OutQty <= matInventoryDetails[i].MatQty)
                        {
                            outOrderMatDetails.Add(new OutOrderMatDetail()
                            {
                                OrderId = order.Id,
                                OrderNumber = order.OrderNumber,
                                OutOrderDetailId = outOrderDetail.Id,
                                InventoryDetailId = matInventoryDetails[i].Id,
                                StoreId = matInventoryDetails[i].StoreId,
                                StoreCode = matInventoryDetails[i].StoreCode,
                                MatSN = matInventoryDetails[i].MatSN,
                                MatCode = matInventoryDetails[i].MatCode,
                                MatName = matInventoryDetails[i].MatName,
                                MatSpec = matInventoryDetails[i].MatSpec,
                                MatBatch = matInventoryDetails[i].MatBatch,
                                MatQty = matInventoryDetails[i].MatQty,
                                MatSupplier = matInventoryDetails[i].MatSupplier,
                                MatCustomer = matInventoryDetails[i].MatCustomer,
                                IsSended = false,
                                CreateUser = createUser,
                            });
                            outOrderDetail.ReqQty = 0;

                            matInventoryDetails[i].IsLocked = true;
                            DbHelp.db.Updateable(matInventoryDetails[i]).ExecuteCommand();
                        }
                        else
                        {
                            outOrderDetail.ReqQty = outOrderDetail.ReqQty - matInventoryDetails[i].MatQty;

                            outOrderMatDetails.Add(new OutOrderMatDetail()
                            {
                                OrderId = order.Id,
                                OrderNumber = order.OrderNumber,
                                OutOrderDetailId = outOrderDetail.Id,
                                InventoryDetailId = matInventoryDetails[i].Id,
                                StoreId = matInventoryDetails[i].StoreId,
                                StoreCode = matInventoryDetails[i].StoreCode,
                                MatSN = matInventoryDetails[i].MatSN,
                                MatCode = matInventoryDetails[i].MatCode,
                                MatName = matInventoryDetails[i].MatName,
                                MatSpec = matInventoryDetails[i].MatSpec,
                                MatBatch = matInventoryDetails[i].MatBatch,
                                MatQty = matInventoryDetails[i].MatQty,
                                MatSupplier = matInventoryDetails[i].MatSupplier,
                                MatCustomer = matInventoryDetails[i].MatCustomer,
                                IsSended = false,
                                CreateUser = createUser,
                            });

                            matInventoryDetails[i].IsLocked = true;
                            DbHelp.db.Updateable(matInventoryDetails[i]).ExecuteCommand();
                        }
                    }
                }
                DbHelp.db.Insertable(outOrderMatDetails).ExecuteCommand();
                DbHelp.db.CommitTran();
                if (outOrderMatDetails.Count == 0)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"计算物料失败，没有满足条件的物料进行出库！（请检查对应物料是否已被锁定）"
                    };
                }
                else

                    return new ResponseCommon()
                    {
                        Code = 200,
                        Message = $"Success"
                    };
            }
            catch (Exception ex)
            {
                DbHelp.db.RollbackTran();
                return new ResponseCommon()
                {
                    Code = 300,
                    Message = $"发生异常：{ex.Message}"
                };
            }
        }

        //删除 解锁 
        private ResponseBase CancelOutOrderMatDetails(OutOrder order)
        {
            try
            {
                DbHelp.db.BeginTran();
                var outOrderMatDetails = DbHelp.db.Queryable<OutOrderMatDetail>()
                                                 .Where(t => t.OrderId == order.Id)
                                                 .Where(t => t.IsSended == false)
                                                 .ToList();

                var inventoryIds = outOrderMatDetails.Select(t => t.InventoryDetailId).ToList();
                var inventoryDetails = DbHelp.db.Queryable<InventoryDetail>()
                                                 .Where(t => inventoryIds.Contains(t.Id))
                                                 .ToList();
                inventoryDetails.ForEach(t => { t.IsLocked = false; });
                DbHelp.db.Deleteable(outOrderMatDetails).ExecuteCommand();
                DbHelp.db.Updateable(inventoryDetails).ExecuteCommand();

                DbHelp.db.CommitTran();
                return new ResponseCommon()
                {
                    Code = 200,
                    Message = $"Success"
                };
            }
            catch (Exception ex)
            {
                DbHelp.db.RollbackTran();
                return new ResponseCommon()
                {
                    Code = 300,
                    Message = $"解锁物料时发生异常：{ex.Message}"
                };
            }
        }

        public async Task<ResponseBase> GoOutOutstore(GetOutOrderDetailRequest request)
        {

            //获取出库单
            var order = await DbHelp.db.Queryable<OutOrder>()
                                 .WhereIF(request.OrderId != 0, t => t.Id == request.OrderId)
                                 .WhereIF(!string.IsNullOrEmpty(request.OrderNumber), t => t.OrderNumber == request.OrderNumber)
                                 .FirstAsync();
            if (order == null)
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"不存在对应的出库单据{request.OrderNumber}！",
                    Data = null
                };
            }

            //执行状态改为暂停
            if (request.IsPause && order.OutOrderExeStatus != OutOrderExeStatus.发料完成)
            {
                order.OutOrderExeStatus = OutOrderExeStatus.暂停发料;
                DbHelp.db.Updateable(order).ExecuteCommand();
            }

            //解锁物料 删除物料明细
            if (order.SyncType == SyncTypeEnum.ByMatCode)
                CancelOutOrderMatDetails(order);

            //找到正在出对应出库单的货架
            var shelves = ShelfManager.Shelves.Where(t => t.OrderNumber == request.OrderNumber)
                                              .Where(t => t.CurrentMode == HardWare.Mode.出库模式)
                                              .ToList();

            if (shelves == null || shelves.Count == 0)
            {
                return new ResponseCommon()
                {
                    Code = 201,
                    Message = $"出库单据【{request.OrderNumber}】不在出库中！",
                    Data = null
                };
            }

            //退出出库模式
            shelves.ForEach(t =>
            {
                t.GoOutOutstore();
            });

            return new ResponseCommon()
            {
                Code = 200,
                Message = "Success",
                Data = null
            };

        }


        public async Task<ResponseBase> SingleLightConfirmOutstore(OutOrderMatDetailModelSingle request)
        {
            try
            {
                //单据校验
                var order = await DbHelp.db.Queryable<OutOrder>()
                    .Where(it => it.Id == request.OrderId)
                    .Where(it => it.OrderNumber == request.OrderNumber)
                    .FirstAsync();
                if (order == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"系统不存在单据[{request.OrderNumber}]!",
                        Data = null
                    };
                }

                //物料校验
                var invetoryDetail = await DbHelp.db.Queryable<InventoryDetail>()
                    .Where(it => it.Id == request.MatId)
                    .Where(it => it.MatSN == request.MatSn)
                    .FirstAsync();
                if (invetoryDetail == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"库存中不存在物料[{request.MatSn}]!",
                        Data = null
                    };
                }


                //物料需求明细校验
                var outOrderDetail = await DbHelp.db.Queryable<OutOrderDetail>().Where(it => it.OrderNumber == request.OrderNumber)
                                                     .Where(it => it.MatCode == invetoryDetail.MatCode)
                                                     .FirstAsync();
                if (outOrderDetail == null)
                {
                    return new ResponseCommon()
                    {
                        Code = 201,
                        Message = $"单据[{request.OrderNumber}]需求不包含物料[{invetoryDetail.MatCode}]!",
                        Data = null
                    };
                }

                var inOutRecord = new InOutRecord();
                inOutRecord.StoreId = invetoryDetail.StoreId;
                inOutRecord.StoreCode = invetoryDetail.StoreCode;
                inOutRecord.MatSN = invetoryDetail.MatSN;
                inOutRecord.MatCode = invetoryDetail.MatCode;
                inOutRecord.MatName = invetoryDetail.MatName;
                inOutRecord.MatSpec = invetoryDetail.MatSpec;
                inOutRecord.MatBatch = invetoryDetail.MatBatch;
                inOutRecord.MatQty = invetoryDetail.MatQty;
                inOutRecord.MatSupplier = invetoryDetail.MatSupplier;
                inOutRecord.MatCustomer = invetoryDetail.MatCustomer;
                inOutRecord.OrderNumber = order.OrderNumber;
                inOutRecord.Direction = DirectionEnum.出库;
                inOutRecord.OperateUser = request.UserName;
                inOutRecord.OperateTime = DateTime.Now;
                inOutRecord.GroupName = invetoryDetail.GroupName;

                //保存出库记录
                int count = DbHelp.db.Insertable(inOutRecord).ExecuteCommand();
                //删除库存
                DbHelp.db.Deleteable<InventoryDetail>().Where(it => it.MatSN == request.MatSn).ExecuteCommand();
                //更新需求表
                outOrderDetail.OutQty += invetoryDetail.MatQty;
                DbHelp.db.Updateable(outOrderDetail).ExecuteCommand();



                return new ResponseCommon()
                {
                    Code = 200,
                    Message = $"出库成功",
                    Data = null
                };
            }
            catch (Exception ex)
            {
                return new ResponseCommon()
                {
                    Code = 300,
                    Message = $"出库发生异常！",
                    Data = null
                };
            }
        }

    }
}
