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.Repository.Entities;
using Siger.Middlelayer.WmsRepository.Entities;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Response;

namespace Siger.Middlelayer.WmsRepository.Repositories
{
    internal class siger_wms_receive_useRepository : WMSRepositoryBase<siger_wms_receive_use>, Isiger_wms_receive_useRepository
    {
        private readonly ApiWmsDbContext dbContext;
        public siger_wms_receive_useRepository(ApiWmsDbContext context) : base(context)
        {
            dbContext = context;
        }

        public IEnumerable<ResponseReceive> GetList(UseType type, string sn, DateTime start, DateTime end, int pid, int page, int pageSize, out int total)
        {

            var data = GetList(f => f.is_returned == (int)type && f.status == (int)RowState.Valid && f.projectid == pid);
            if (!string.IsNullOrEmpty(sn))
            {
                data = data.Where(f => f.serial_number.Contains(sn));
            }
            switch (type)
            {
                case UseType.Use:
                    if (start != null && start != DateTime.MinValue)
                    {
                        data = data.Where(f => f.create_time >= start);
                    }
                    if (end != null && end != DateTime.MinValue)
                    {
                        data = data.Where(f => f.return_operate_time <= end);
                    }
                    break;
                case UseType.SendBack:
                    if (start != null && start != DateTime.MinValue)
                    {
                        data = data.Where(f => f.return_time >= start);
                    }
                    if (end != null && end != DateTime.MinValue)
                    {
                        data = data.Where(f => f.return_time <= end);
                    }
                    break;
                default:
                    break;
            }
            total = data.Count();
            data = data.Skip((page - 1) * pageSize).Take(pageSize);
            var receiveids = data.Select(f => f.receive_person).ToList();
            var retids = data.Select(f => f.return_person).ToList();
            var retopids = data.Select(f => f.return_operator).ToList();
            var recopids = data.Select(f => f.receive_operator).ToList();
            var recDic = dbContext.siger_project_user.Where(f => f.projectid == pid && f.status == (int)RowState.Valid && receiveids.Contains(f.mid)).ToDictionary(f => f.mid, f => f.name);
            var retDic = dbContext.siger_project_user.Where(f => f.projectid == pid && f.status == (int)RowState.Valid && retids.Contains(f.mid)).ToDictionary(f => f.mid, f => f.name);
            var retopDic = dbContext.siger_project_user.Where(f => f.projectid == pid && f.status == (int)RowState.Valid && retopids.Contains(f.mid)).ToDictionary(f => f.mid, f => f.name);
            var recopDic = dbContext.siger_project_user.Where(f => f.projectid == pid && f.status == (int)RowState.Valid && recopids.Contains(f.mid)).ToDictionary(f => f.mid, f => f.name);

            var result = new List<ResponseReceive>();
            foreach (var item in data)
            {
                try
                {
                    var tmp = Mapper<siger_wms_receive_use, ResponseReceive>.Map(item);
                    tmp.return_time = item.return_time == DateTime.MinValue ? "" : item.return_time.ToString(UnixTimeHelper.DateTimeFormat);
                    if(recDic.TryGetValue(item.receive_person,out string receive_person_name))
                    {
                        tmp.receive_person_name = receive_person_name;
                    }
                    else
                    {
                        tmp.receive_person_name = "";
                    }
                    if (retDic.TryGetValue(item.return_person, out string return_person_name))
                    {
                        tmp.return_person_name = return_person_name;
                    }
                    else
                    {
                        tmp.return_person_name = "";
                    }
                    if (retopDic.TryGetValue(item.return_operator, out string return_oper_person_name))
                    {
                        tmp.return_oper_person_name = return_oper_person_name;
                    }
                    else
                    {
                        tmp.return_oper_person_name = "";
                    }
                    if (recopDic.TryGetValue(item.receive_operator, out string receive_oper_person_name))
                    {
                        tmp.receive_oper_person_name = receive_oper_person_name;
                    }
                    else
                    {
                        tmp.receive_oper_person_name = "";
                    }
                    result.Add(tmp);
                }
                catch (Exception)
                {

                }
            }
            return result;
        }

        public IList<siger_tr_materials> GetMaterialsList(int pid)
        {
            return dbContext.siger_tr_materials.Where(f=>f.status==(int)RowState.Valid && f.projectId==pid).ToList();
        }

        public void SendBack(string workCode, int locationID, string sn, int projectId, int userId)
        {
            var entity = Get(f => f.status == (int)RowState.Valid && f.serial_number == sn && f.projectid == projectId&&f.is_returned==(int)UseType.Use);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var user = dbContext.siger_project_user.FirstOrDefault(f => f.status == (int)RowState.Valid && f.work_code == workCode && f.projectid == projectId);
            if (user == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var stock = dbContext.siger_wms_stock.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == projectId && f.serial_number == sn &&
                                                                f.stock_state == (int)StockEnum.Use && f.manage_model == ((int)managemodel.No).ToString());
            if (stock == null)
            {
                throw new BadRequestException(RequestEnum.StockNotExist);
            }
            //check location
            if (dbContext.siger_wms_storage_location.Count(f => f.status == (int)RowState.Valid && f.id == locationID && f.projectid == projectId) <= 0)
            {
                throw new BadRequestException(RequestEnum.LocationError);
            }
            //stock中状态修改为在库
            stock.stock_state = (int)StockEnum.InWavehouse;
            stock.updator = userId;
            stock.update_time = DateTime.Now;
            stock.storage_location_id = locationID;
            dbContext.siger_wms_stock.Update(stock);


            entity.return_operate_time = DateTime.Now;
            entity.return_operator = userId;
            entity.return_person = user.mid;
            entity.return_time = DateTime.Now;
            entity.update_time = DateTime.Now;
            entity.updator = userId;
            entity.is_returned = (int)UseType.SendBack;
            Update(entity);

            var location = dbContext.siger_wms_storage_location.FirstOrDefault(f => f.projectid == projectId && f.status == (int)RowState.Valid && f.id == stock.storage_location_id);
            if (location == null)
            {
                throw new BadRequestException(RequestEnum.LocationNull);
            }
            //trace
            dbContext.siger_wms_stock_detail.Add(new siger_wms_stock_detail
            {
                type = (int)traceType.Return,
                inventory = stock.material_id,
                inventoryName = stock.material_name,
                inventorySpec = stock.material_spec,
                inventorySN = stock.material_pn,
                locationid = stock.storage_location_id,
                locationname = location.name,
                allqty = 1,
                qty = 1,
                no = stock.serial_number,
                batch=stock.batch_number,
                userid = userId,
                username = GetUserName(userId),
                state = (int)RowState.Valid,
                projectid = projectId,
                updatetime=DateTime.Now
            });

            //汇总库存
            AddStockChange(location.storageid, stock.material_id, 1, projectId);

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

        public void Use(string workCode, string useAddress, string sn, int projectId, int UserID)
        {
            var user = dbContext.siger_project_user.FirstOrDefault(f => f.status == (int)RowState.Valid && f.work_code == workCode && f.projectid == projectId);
            if (user == null)
            {
                throw new BadRequestException(RequestEnum.UserNotFound);
            }
            var stock = dbContext.siger_wms_stock.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == projectId && f.serial_number == sn &&
                                                f.stock_state == (int)StockEnum.InWavehouse && f.manage_model == ((int)managemodel.No).ToString());
            if (stock == null)
            {
                throw new BadRequestException(RequestEnum.StockNotExist);
            }
            //stock中状态修改为use
            stock.stock_state = (int)StockEnum.Use;
            stock.updator = UserID;
            stock.update_time = DateTime.Now;
            dbContext.siger_wms_stock.Update(stock);

            var location = dbContext.siger_wms_storage_location.FirstOrDefault(f => f.projectid == projectId && f.status == (int)RowState.Valid && f.id == stock.storage_location_id);
            if (location == null)
            {
                throw new BadRequestException(RequestEnum.LocationNull);
            }
            Insert(new siger_wms_receive_use
            {
                stockid = stock.id,
                serial_number = stock.serial_number,
                material_id = stock.material_id,
                material_name = stock.material_name,
                material_pn = stock.material_pn,
                material_spec = stock.material_spec,
                use_location = useAddress,
                is_returned = (int)UseType.Use,
                receive_person = user.mid,
                receive_operator = UserID,
                creator = UserID,
                create_time = DateTime.Now,
                update_time = DateTime.Now,
                updator = UserID,
                projectid = projectId,
                status = (int)RowState.Valid
            });
            //trace
            dbContext.siger_wms_stock_detail.Add(new siger_wms_stock_detail
            {
                type=(int)traceType.Use,
                inventory= stock.material_id,
                inventoryName= stock.material_name,
                inventorySpec= stock.material_spec,
                inventorySN=stock.material_pn,
                locationid= stock.storage_location_id,
                locationname= location.name,
                batch=stock.batch_number,
                allqty=1,
                qty=1,
                no=stock.serial_number,
                userid=UserID,
                username=GetUserName(UserID),
                state=(int)RowState.Valid,
                projectid=projectId,
                updatetime = DateTime.Now
            });

            //汇总库存
            SubtractStockChange(location.storageid, stock.material_id, 1, projectId);

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

