using System;
using System.Collections.Generic;
using System.Linq;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.WmsRepository.Entities;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Request;
using Siger.Middlelayer.WmsRepository.Response;

namespace Siger.Middlelayer.WmsRepository.Repositories
{
    internal class siger_wms_transfer_orderRepository : WMSRepositoryBase<siger_wms_transfer_order>, Isiger_wms_transfer_orderRepository
    {
        private readonly ApiWmsDbContext dbContext;
        public siger_wms_transfer_orderRepository(ApiWmsDbContext context) : base(context)
        {
            dbContext = context;
        }
        /// <summary>
        /// 新增调拨单
        /// </summary>
        /// <param name="waveHouseID"></param>
        /// <param name="endWaveHouseID"></param>
        /// <param name="inventory"></param>
        /// <param name="projectId"></param>
        /// <param name="userId"></param>
        /// <param name="billcode"></param>
        public void AddAllocationBill(int waveHouseID, int endWaveHouseID, List<StockNode> inventory, int projectId, int userId, string billcode)
        {
            var groupData = inventory.GroupBy(f => new { f.id, f.businessid });
            foreach (var item in groupData)
            {
                if (item.Count() > 1)
                {
                    throw new BadRequestException(RequestEnum.InventoryDuplicate);
                }
            }

            //获取指定仓库的所有储位
            var allLocations = dbContext.siger_wms_storage_location.Where(f => f.status == (int)RowState.Valid && f.projectid == projectId && f.storageid == waveHouseID).Select(f => f.id).ToList();

            //检测库中指定物料的数量是否充足
            foreach (var item in inventory)
            {
                var qty = dbContext.siger_wms_stock.Where(f => f.projectid == projectId && f.status == (int)RowState.Valid && f.material_id == item.id &&
                                                  allLocations.Contains(f.storage_location_id) && f.businessid == item.businessid).Sum(f => f.quantity);
                if (qty < item.count)
                {
                    throw new BadRequestException(RequestEnum.CountError);
                }
            }

            //添加单据表头
            var order = new siger_wms_transfer_order
            {
                order_number = billcode,
                order_status = (int)AlloactionStatu.Waitting,
                projectid = projectId,
                status = (int)RowState.Valid,
                start_storage_id = waveHouseID,
                end_storage_id = endWaveHouseID,
                create_time = DateTime.Now,
                creator = userId,
                update_time = DateTime.Now,
                updator = userId
            };
            Insert(order);
            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            //添加详情
            foreach (var item in inventory)
            {
                var tmp = new siger_wms_transfer_order_detail
                {
                    orderid = order.id,
                    quantity = item.count,
                    stockCount = item.stockCount,
                    transfer_quantity = 0,
                    order_number = billcode,
                    create_time = DateTime.Now,
                    creator = userId,
                    update_time = DateTime.Now,
                    updator = userId,
                    projectid = projectId,
                    status = (int)RowState.Valid,
                    transfer_status = (int)AlloactionStatu.Waitting,
                    businessid = item.businessid,
                    businessName = GetBusinessName(item.businessid, projectId)
                };
                var inventoryData = dbContext.siger_tr_materials.FirstOrDefault(f => f.id == item.id && f.status == (int)RowState.Valid && f.projectId == projectId);
                if (inventoryData == null)
                {
                    throw new BadRequestException(RequestEnum.MaterialNotExist);
                }
                tmp.material_id = inventoryData.id;
                tmp.material_name = inventoryData.name;
                tmp.material_pn = inventoryData.pn;
                tmp.material_spec = inventoryData.spec;
                dbContext.siger_wms_transfer_order_detail.Add(tmp);
            }

            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }
        /// <summary>
        /// 汇总
        /// </summary>
        /// <param name="type"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public IEnumerable<ResponseWaveHousing> GetAllocationBills(AlloactionStatu type, int projectId)
        {
            //获取指定状态的单据
            var data = GetList(f => f.status == (int)RowState.Valid && f.projectid == projectId && f.order_status == (int)type);
            var result = from order in data
                         join user in dbContext.siger_user on order.updator equals user.id into tmp1
                         from userInfo in tmp1.DefaultIfEmpty()
                         join storage in dbContext.siger_wms_storage on order.start_storage_id equals storage.id into tmp2
                         from storageInfo in tmp2.DefaultIfEmpty()
                         join details in dbContext.siger_wms_transfer_order_detail on order.id equals details.orderid into tmp3
                         from r in tmp2.DefaultIfEmpty()
                         select new ResponseWaveHousing
                         {
                             id = order.id,
                             order_number = order.order_number,
                             name = userInfo.nickname,
                             storageName = storageInfo.name,
                             time = order.update_time,
                             count = tmp3.Count()
                         };
            return result;
        }

        public IEnumerable<ResponseGetAllocationList> GetBillList(int pid, int fromWavehouseid, int toWavehouseid, AlloactionStatu state, string billCode, int page, int pageSize, out int totalValue)
        {
            //var data = GetList(f => f.order_status != (int)AlloactionStatu.Canceled && f.status == (int)RowState.Valid && f.projectid == pid);

            var data = GetList(f =>  f.status == (int)RowState.Valid && f.projectid == pid);
            if (fromWavehouseid != 0)
            {
                data = data.Where(f => f.start_storage_id == fromWavehouseid);
            }
            if (toWavehouseid != 0)
            {
                data = data.Where(f => f.end_storage_id == toWavehouseid);
            }
            switch (state)
            {
                case AlloactionStatu.Waitting:
                case AlloactionStatu.Checked:
                case AlloactionStatu.Alloaction:
                case AlloactionStatu.WaittingReceiving:
                case AlloactionStatu.Finish:
                case AlloactionStatu.Canceled:
                case AlloactionStatu.Failed:
                case AlloactionStatu.Alloactioning:
                    data = data.Where(f => f.order_status == (int)state);
                    break;
                default:
                    break;
            }
            if (!string.IsNullOrEmpty(billCode))
            {
                data = data.Where(f => f.order_number == billCode.Trim());
            }
            totalValue = data.Count();
            var fromIDs = data.Select(f => f.start_storage_id).ToList();
            var toIDs = data.Select(f => f.end_storage_id).ToList();
            var checkIDs = data.Select(f => f.auditor).ToList();
            var createIDs = data.Select(f => f.creator).ToList();

            var dicFrom = dbContext.siger_wms_storage.Where(f => f.status == (int)RowState.Valid && f.projectid == pid && fromIDs.Contains(f.id)).ToDictionary(f => f.id, f => f.name);
            var dicTo = dbContext.siger_wms_storage.Where(f => f.status == (int)RowState.Valid && f.projectid == pid && toIDs.Contains(f.id)).ToDictionary(f => f.id, f => f.name);
            var dicCheck = dbContext.siger_user.Where(f => f.status == (int)RowState.Valid && checkIDs.Contains(f.id)).ToDictionary(f => f.id, f => f.nickname);
            var dicCreate = dbContext.siger_user.Where(f => f.status == (int)RowState.Valid && createIDs.Contains(f.id)).ToDictionary(f => f.id, f => f.nickname);

            var result = new List<ResponseGetAllocationList>();
            data = Paging(data, page, pageSize);
            foreach (var item in data)
            {
                var tmp = Mapper<siger_wms_transfer_order, ResponseGetAllocationList>.Map(item);
                if (dicFrom.TryGetValue(tmp.start_storage_id, out string fromStr))
                {
                    tmp.from = fromStr;
                }
                if (dicTo.TryGetValue(tmp.end_storage_id, out string toStr))
                {
                    tmp.end = toStr;
                }
                if (dicCheck.TryGetValue(tmp.auditor, out string checkStr))
                {
                    tmp.checker = checkStr;
                }
                if (dicCreate.TryGetValue(tmp.creator, out string createStr))
                {
                    tmp.creater = createStr;
                }
                try
                {
                    tmp.statuName = EnumHelper.GetEnumDesc((AlloactionStatu)tmp.order_status);
                }
                catch (Exception)
                {

                }
                result.Add(tmp);
            }
            return result;
        }


        public void UpdateBill(int id, List<StockNode> inventory, int projectId, int userId)
        {
            var groupData = inventory.GroupBy(f => new { f.id, f.businessid });
            foreach (var item in groupData)
            {
                if (item.Count() > 1)
                {
                    throw new BadRequestException(RequestEnum.InventoryDuplicate);
                }
            }

            var order = Get(f => f.status == (int)RowState.Valid && f.id == id);
            //删除旧数据
            var existData = dbContext.siger_wms_transfer_order_detail.Where(f => f.orderid == id && f.status == (int)RowState.Valid && f.projectid == projectId).ToList();
            existData.ForEach(f =>
            {
                f.status = (int)RowState.Invalid;
            });
            dbContext.siger_wms_transfer_order_detail.UpdateRange(existData);
            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            //获取指定仓库的所有储位
            var locationids = dbContext.siger_wms_storage_location.Where(f => f.status == (int)RowState.Valid && f.projectid == projectId && f.storageid == order.start_storage_id).Select(f => f.id).ToList();
            //检测库中指定物料的数量是否充足
            foreach (var item in inventory)
            {
                var qty = dbContext.siger_wms_stock.Where(f => f.projectid == projectId && f.status == (int)RowState.Valid && f.material_id == item.id &&
                                                  locationids.Contains(f.storage_location_id) && f.businessid == item.businessid).Sum(f => f.quantity);
                if (qty < item.count)
                {
                    throw new BadRequestException(RequestEnum.StorageLocationNotMatch);
                }
            }

            //创建新数据
            //添加详情
            foreach (var item in inventory)
            {
                var tmp = new siger_wms_transfer_order_detail
                {
                    orderid = order.id,
                    order_number = order.order_number,
                    quantity = item.count,
                    stockCount = item.stockCount,
                    transfer_quantity = 0,
                    create_time = DateTime.Now,
                    creator = userId,
                    update_time = DateTime.Now,
                    updator = userId,
                    projectid = projectId,
                    status = (int)RowState.Valid,
                    transfer_status = (int)AlloactionStatu.Waitting,
                    businessid = item.businessid,
                    businessName = GetBusinessName(item.businessid, projectId)
                };
                var inventoryData = dbContext.siger_tr_materials.FirstOrDefault(f => f.id == item.id && f.status == (int)RowState.Valid && f.projectId == projectId);
                if (inventoryData == null)
                {
                    throw new BadRequestException(RequestEnum.MaterialNotExist);
                }
                tmp.material_id = inventoryData.id;
                tmp.material_name = inventoryData.name;
                tmp.material_pn = inventoryData.pn;
                tmp.material_spec = inventoryData.spec;
                dbContext.siger_wms_transfer_order_detail.Add(tmp);
            }
            order.update_time = DateTime.Now;
            order.updator = userId;
            Update(order);

            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
        }
    }
}

