using Admin.Core.IRepository;
using Admin.Core.IService;
using Admin.Core.Model;
using Admin.Core.Model.Model_New;
using Microsoft.IdentityModel.Logging;
using System.Collections.Generic;
using System.Linq.Expressions;
using System;
using System.Threading.Tasks;
using Admin.Core.Common;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Linq;
using log4net;
using StackExchange.Profiling.Internal;
using Admin.Core.Model.Sys;
using Admin.Core.Model.ViewModels;

namespace Admin.Core.Service
{
    /**
     * 货道
     **/
    public class BaseSpaceInfoServices : BaseServices<BaseSpaceInfo>, IBaseSpaceInfoServices
    {
        private static readonly log4net.ILog logHelper = LogManager.GetLogger(typeof(BaseSpaceInfoServices));
        private readonly IBaseRepository<BaseSpaceInfo> _dal;
        private readonly IBaseSpaceInfoRepository _baseSpaceInfoRepository;
        private readonly IBaseBomInfoRepository _baseBomInfoRepository;

        public BaseSpaceInfoServices(IBaseRepository<BaseSpaceInfo> dal, IBaseSpaceInfoRepository baseSpaceInfoRepository, IBaseBomInfoRepository baseBomInfoRepository)
        {
            this._dal = dal;
            base.BaseDal = dal;
            _baseSpaceInfoRepository = baseSpaceInfoRepository;
            _baseBomInfoRepository = baseBomInfoRepository;
        }



        #region 入库通过物料类型获取指定货道,泡前库如果没有对应类型的货道停住
        /// <summary>
        /// 入库通过物料类型获取指定货道
        /// </summary>
        /// <param name="store">物料条码</param>
        /// <param name="materialType">货道类型</param>
        /// <returns>获取合适货道</returns>
        public async Task<List<BaseSpaceInfo>> InStoreGetSpaceInfoByMaterialType(string store, string materialType)
        {

            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                spaceInfos = await _baseSpaceInfoRepository.QueryAsync(x => x.StoreCode == store && (x.MaterialType == materialType || x.typeCodeB == materialType || x.typeCodeC == materialType) && x.SpaceStatus == 1);
                if (spaceInfos == null || spaceInfos.Count == 0) return null;
            }
            catch (Exception ex)
            {
                logHelper.Error("入库通过物料类型获取货道信息异常", ex);
                Console.WriteLine($"入库通过物料类型获取货道信息异常:{ex.Message}");
            }
            return spaceInfos;
        } 
        #endregion


        #region 入库过滤逻辑
        /// <summary>
        /// 入库过滤逻辑
        /// </summary>
        /// <param name="spaceInfos"></param>
        private BaseSpaceInfo InStoreFilter(List<BaseSpaceInfo> spaceInfos)
        {
            BaseSpaceInfo spaceInfo = null;
            if (spaceInfos.Count > 0)
            {
                //获取库存未满库存最多的货道
                var spaceInfosList = spaceInfos.Where(x => x.SpaceCapacity != x.SpaceStock);
                spaceInfosList.OrderByDescending(x => x.SpaceStock);
                spaceInfo = spaceInfosList.FirstOrDefault();
            }
            else
            {
                logHelper.Info("入库过滤未获取到匹配的货道信息");
            }
            return spaceInfo;
        }
        #endregion

        #region 出库通过物料类型获取指定货道
        /// <summary>
        /// 出库通过物料类型获取指定货道
        /// </summary>
        /// <param name="store"></param>
        /// <param name="materialType"></param>
        /// <returns></returns>
        public async Task<List<BaseSpaceInfo>> OutStoreGetSpaceInfoByMaterialCode(string store, string materialType)
        {
            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                //Expression<Func<BaseSpaceInfo, bool>> exp = s1 => true;
                spaceInfos = await _baseSpaceInfoRepository.QueryAsync(x => x.StoreCode == store && x.MaterialType == materialType && x.SpaceStatus == 1 && x.SpaceStock > 0);//相同型号、启用状态、库存不为空的货道信息

                logHelper.Info($"根据仓库{store};物料:{materialType};获取到的货道信息:{spaceInfos.ToJson()}");
                logHelper.Info($"仓库{store};物料:{materialType};匹配的入库货道信息:{spaceInfos.ToJson()}");
            }
            catch (Exception ex)
            {
                logHelper.Error("出库通过物料类型获取货道信息异常", ex);
            }
            return spaceInfos;
        }
        #endregion

        #region 出库过滤逻辑
        /// <summary>
        /// 出库过滤逻辑
        /// </summary>
        /// <param name="spaceInfos"></param>
        public BaseSpaceInfo outStoreFilter(List<BaseSpaceInfo> spaceInfos)
        {
            BaseSpaceInfo spaceInfo = null;
            if (spaceInfos.Count > 0)
            {
                //获取库存最少的货道(优先清空货道)
                spaceInfo = spaceInfos.Where(x => x.SpaceStock > 0).OrderBy(x => x.SpaceStock).First();
            }
            else
            {
                logHelper.Info("出库过滤未获取到匹配的货道信息");
            }

            return spaceInfo;
        }
        #endregion

        #region 通过货道编号获取货道信息
        /// <summary>
        /// 通过货道编号获取货道信息
        /// </summary>
        /// <param name="store"></param>
        /// <param name="spaceCode"></param>
        /// <returns></returns>
        public async Task<BaseSpaceInfo> GetSpaceInfoBySpaceCode(string store, string spaceCode)
        {
            BaseSpaceInfo spaceInfo = null;
            try
            {
                spaceInfo = await _baseSpaceInfoRepository.FirstAsync(x => x.StoreCode == store && x.SpaceCode == spaceCode);
            }
            catch (Exception ex)
            {
                logHelper.Error("通过货道编号获取货道信息异常", ex);
            }
            return spaceInfo;
        }
        #endregion

        #region 更新货道信息
        /// <summary>
        /// 更新货道信息
        /// </summary>
        /// <param name="spaceInfo"></param>
        /// <returns></returns>
        public async Task<bool> UpdateSpaceInfo(BaseSpaceInfo spaceInfo)
        {
            bool result = false;
            try
            {
                result = await _baseSpaceInfoRepository.UpdateAsync(spaceInfo);
            }
            catch (Exception ex)
            {
                logHelper.Error("更新货道信息异常", ex);
            }
            return result;
        }


        #endregion


        public async Task<List<dynamic>> GetMaterialStock(string shellStoreCode, string linerStoreCode)
        {
            List<dynamic> result = null;

            try
            {
                List<dynamic> query =await _baseSpaceInfoRepository.GetStoreMaterialStock(shellStoreCode, linerStoreCode);
                if (query.Count > 0)
                {
                    result = query.GroupBy(s => s.PARENT_NAME)
                            .Select(g => (dynamic)new 
                            {
                                parentMaterialName = g.Key,
                                shellStock = g.Where(x => x.STORE_CODE == shellStoreCode).Select(x => x.SPACE_STOCK).FirstOrDefault(),
                                linerStock = g.Where(x => x.STORE_CODE == linerStoreCode).Select(x => x.SPACE_STOCK).FirstOrDefault()
                            }).ToList();

                }
            }
            catch (Exception ex)
            {
                logHelper.Error("获取物料库存异常", ex);
            }
            return result;
        }

        public async Task<List<BaseSpaceInfo>> GetBaseSpaceInfosByMaterialType(string storeCode, string materialType)
        {
            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                Expression<Func<BaseSpaceInfo, bool>> exp = s1 => true;
                exp = exp.And(x => x.StoreCode == storeCode && x.MaterialType == materialType && x.SpaceStatus == 1); //相同型号、启用状态的货道信息

                spaceInfos =await _dal.QueryAsync(exp);

                if (spaceInfos.Count == 0) //没有指定该类型物料的货道信息,需获取空白货道信息进行分配
                {
                    spaceInfos =await GetEmptySpaceInfo(storeCode);
                }
                logHelper.Info($"根据仓库{storeCode};物料:{materialType};获取到的货道信息:{spaceInfos.ToJson()}");
            }
            catch (Exception ex)
            {
                logHelper.Error("获取货道信息异常", ex);
            }
            return spaceInfos;
        }


        public async Task<List<BaseSpaceInfo>> GetSpaceInfosByStoreCode(string storeCode)
        {
            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                var baseSpaceInfoList = await _dal.QueryAsync();
                var BaseBomInfoList = await _baseBomInfoRepository.QueryAsync();
                spaceInfos = (from s in baseSpaceInfoList
                              join b in BaseBomInfoList on s.MaterialType equals b.MaterialCode
                              where s.StoreCode == storeCode
                              select new BaseSpaceInfo
                              {
                                  ObjId = s.ObjId,
                                  SpaceCode = s.SpaceCode,
                                  SpaceName = s.SpaceName,
                                  SpaceCapacity = s.SpaceCapacity,
                                  SpaceStock = s.SpaceStock,
                                  SpaceStatus = s.SpaceStatus,
                                  SpaceType = s.SpaceType,
                                  IsFlag = s.IsFlag,
                                  MaterialType = b.MaterialName,
                                  OnRouteAmount = s.OnRouteAmount,
                                  InStoreFlag = s.InStoreFlag,
                                  OutRouteAmount = s.OutRouteAmount,
                                  OutStoreFlag = s.OutStoreFlag,
                                  UnusualFlag = s.UnusualFlag
                              }).ToList();
            }
            catch (Exception ex)
            {
                logHelper.Error("获取货道信息异常", ex);
            }
            return spaceInfos;
        }
       
        /// <summary>
        /// 获取空货道:未分配物料型号的空白货道
        /// </summary>
        /// <param name="store"></param>
        /// <returns></returns>
        public async Task<List<BaseSpaceInfo>> GetEmptySpaceInfo(string store)
        {
            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                spaceInfos =await _dal.QueryAsync(x => x.MaterialType == null && x.StoreCode == store && x.SpaceCapacity != x.SpaceStock);
            }
            catch (Exception ex)
            {
                logHelper.Error("获取空货道异常", ex);
            }
            return spaceInfos;
        }

        public List<BaseSpaceInfo> GetSpaceInfos(string storeCode)
        {
            List<BaseSpaceInfo> spaceInfos = null;
            try
            {
                spaceInfos =  _dal.Query(x=>x.StoreCode == storeCode);
            }
            catch (Exception ex)
            {
                logHelper.Error("获取货道信息异常", ex);
            }
            return spaceInfos;
        }

        /// <summary>
        /// 获取指定的货道信息
        /// </summary>
        /// <param name="spaceinfos"></param>
        /// <param name="whereExpression"></param>
        /// <exception cref="InvalidOperationException"></exception>
        public void GetSpaceInfosByExpression(out List<BaseSpaceInfo> spaceinfos, Expression<Func<BaseSpaceInfo, bool>> whereExpression = null)
        {
            try
            {
                var exp = whereExpression != null ? whereExpression : x => 1 == 1;
                spaceinfos = _dal.Query(exp);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"获取所有已下线成品信息异常:{e.Message}");
            }
        }

        /// <summary>
        /// 根据物料类型获取指定仓库的货道信息
        /// </summary>
        /// <param name="spaceinfo"></param>
        /// <param name="storeCode"></param>
        /// <param name="materialType"></param>
        /// <exception cref="ArgumentException"></exception>
        public void GetSpaceInfoByMaterialType(out List<BaseSpaceInfo> spaceinfos, string storeCode, string materialType)
        {
            if (string.IsNullOrEmpty(storeCode))
            {
                throw new ArgumentException($"根据物料类型获取指定仓库的货道信息异常:仓库编号为空");
            }

            if (string.IsNullOrEmpty(materialType))
            {
                throw new ArgumentException($"根据物料类型获取指定仓库的货道信息异常:物料类型为空");
            }

            try
            {
                spaceinfos = _dal.Query(x => x.StoreCode == storeCode && x.MaterialType == materialType);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"根据物料类型获取指定仓库的货道信息异常:{e.Message}");
            }
        }

        /// <summary>
        /// 更新货道信息
        /// </summary>
        /// <param name="spaceinfos"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool UpdateSpaceInfo(List<BaseSpaceInfo> spaceinfos)
        {
            bool result = false;
            try
            {
                result = _dal.Update(spaceinfos);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"更新货道信息异常:{e.Message}");
            }

            return result;
        }
    }
}