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.Request;

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

        public void CheckOut(int id, List<Stock> inventories, int userId, int projectId, managemodel type, string code)
        {
            int totalCount = 0;

            switch (type)
            {
                case managemodel.Batch:
                    break;
                case managemodel.No:
                    totalCount = 1;
                    break;
                case managemodel.Group:
                    break;
                default:
                    throw new BadRequestException(RequestEnum.ManageModeNotMatching);
            }
            if (dbContext.siger_wms_stock_access_order_detail.Count(f => f.id == id && f.status == (int)RowState.Valid && f.projectid == projectId) == 0)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            //类型为出库单
            siger_wms_stock_access_order_detail orderdetail = dbContext.siger_wms_stock_access_order_detail.FirstOrDefault(f => f.id == id && f.status == (int)RowState.Valid && f.projectid == projectId);
            switch (type)
            {
                case managemodel.Batch:
                    if (!string.IsNullOrEmpty(code))
                    {
                        if (dbContext.siger_wms_stock.Count(f => f.batch_number == code) < 0)
                        {
                            throw new BadRequestException(RequestEnum.BatchNull);
                        }
                    }
                    break;
                case managemodel.No:
                    if (!string.IsNullOrEmpty(code))
                    {
                        if (dbContext.siger_wms_stock.Count(f => f.serial_number == code) < 0)
                        {
                            throw new BadRequestException(RequestEnum.NoNull);
                        }
                    }
                    break;
                case managemodel.Group:
                    break;
                default:
                    throw new BadRequestException(RequestEnum.ManageModeNotMatching);
            }
            if (orderdetail == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var orderData = dbContext.siger_wms_stock_access_order.FirstOrDefault(f => f.status == (int)RowState.Valid && f.id == orderdetail.orderid &&
                                            f.access_type == (int)WaveHouseType.Out && f.projectid == projectId);
            if (orderData == null)
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            if (orderData.order_status != (int)WaveHousingState.Checked && orderData.order_status != (int)WaveHousingState.WaveHousingOut)
            {
                throw new BadRequestException(RequestEnum.ErrorState);
            }

            foreach (var item in inventories)
            {
                totalCount += item.count;
                if (dbContext.siger_wms_stock.Count() < 0)
                {
                    throw new BadRequestException(RequestEnum.StockNotExist);
                }
            }
            if (orderdetail.quantity - orderdetail.access_quantity - totalCount < 0)
            {
                //count error
                throw new BadRequestException(RequestEnum.CountInsufficient);
            }
            var stockOuts = new List<int>();//出库的物料id列表
            if (type == managemodel.No)
            {
                var stock = dbContext.siger_wms_stock.FirstOrDefault(f => f.status == (int)RowState.Valid && f.serial_number == code &&
                                                                                    f.stock_state == (int)StockEnum.InWavehouse && f.projectid == projectId);
                if (stock == null)
                {
                    throw new BadRequestException(RequestEnum.StockNotExist);
                }
                if(orderdetail.material_id!=stock.material_id)
                {
                    throw new BadRequestException(RequestEnum.MaterialeError);
                }
                if (orderdetail.businessid != stock.businessid)
                {
                    throw new BadRequestException(RequestEnum.BusinessNotMatch);
                }
                //检测是否为出库单上的仓库
                var locationdata = dbContext.siger_wms_storage_location.FirstOrDefault(f => f.id == stock.storage_location_id && f.status == (int)RowState.Valid);
                if (locationdata == null)
                {
                    throw new BadRequestException(RequestEnum.LocationError);
                }
                if (locationdata.storageid != orderData.storageid)
                {
                    throw new BadRequestException(RequestEnum.LocationError);
                }
                //check管理模式
                var entity = dbContext.siger_tr_materials.FirstOrDefault(f => f.id == stock.material_id && f.status == (int)RowState.Valid && f.projectId == projectId);
                if (entity == null)
                {
                    throw new BadRequestException(RequestEnum.MaterialNotExist);
                }
                if (int.TryParse(entity.manage_mode, out int mode))
                {
                    if ((int)type != mode)
                    {
                        throw new BadRequestException(RequestEnum.ManageModeNotMatching);
                    }
                }
                var location = dbContext.siger_wms_storage_location.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid == projectId &&
                            f.id==stock.storage_location_id);
                if (location == null)
                {
                    throw new BadRequestException(CommonEnum.NoData);
                }
                //添加trace
                var tracedata = new siger_wms_stock_detail();
                tracedata.type = (int)traceType.WaveHousingOut;
                tracedata.billID = orderData.order_number;
                tracedata.inventory = stock.material_id;
                tracedata.inventorySN = stock.material_pn;
                tracedata.inventoryName = orderdetail.material_name;
                tracedata.allqty = orderdetail.quantity;
                tracedata.qty = 1;
                tracedata.userid = userId;
                tracedata.username = GetUserName(userId);
                tracedata.updatetime = DateTime.Now;
                tracedata.state = (int)RowState.Valid;
                tracedata.locationid = stock.storage_location_id;
                tracedata.locationname = location.name;
                tracedata.inventorySpec = stock.material_spec;
                tracedata.state = (int)RowState.Valid;
                tracedata.projectid = projectId;
                tracedata.no = code;

                //供应商信息
                tracedata.businessid = stock.businessid;
                tracedata.businessName = GetBusinessName(stock.businessid, projectId);

                dbContext.siger_wms_stock_detail.Add(tracedata);


                //更新stock中的数量
                stock.quantity -= 1;
                //更新状态为出库
                if (stock.quantity == 0)
                {
                    stock.stock_state = (int)StockEnum.OutWavehouse;                    
                }
                stockOuts.Add(stock.material_id);
                dbContext.siger_wms_stock.Update(stock);
            }
            else
            {
                //更新orderdetail中的数量
                foreach (var item in inventories)
                {
                    var stock = dbContext.siger_wms_stock.FirstOrDefault(f => f.status == (int)RowState.Valid && f.id == item.stockid &&
                                                                                    f.stock_state == (int)StockEnum.InWavehouse && f.projectid == projectId);
                    if (stock == null)
                    {
                        throw new BadRequestException(RequestEnum.StockNotExist);
                    }

                    //检测是否为出库单上的仓库
                    var locationdata = dbContext.siger_wms_storage_location.FirstOrDefault(f => f.id == stock.storage_location_id && f.status == (int)RowState.Valid);
                    if (locationdata == null)
                    {
                        throw new BadRequestException(RequestEnum.LocationError);
                    }
                    if (locationdata.storageid != orderData.storageid)
                    {
                        throw new BadRequestException(RequestEnum.LocationError);
                    }

                    if (item.count > stock.quantity)
                    {
                        throw new BadRequestException(RequestEnum.CountInsufficient);
                    }
                    //check管理模式
                    var entity = dbContext.siger_tr_materials.FirstOrDefault(f => f.id == stock.material_id && f.status == (int)RowState.Valid && f.projectId == projectId);
                    if (entity == null)
                    {
                        throw new BadRequestException(RequestEnum.MaterialNotExist);
                    }
                    if (int.TryParse(entity.manage_mode, out int mode))
                    {
                        if ((int)type != mode)
                        {
                            throw new BadRequestException(RequestEnum.ManageModeNotMatching);
                        }
                    }

                    //添加trace
                    var tracedata = new siger_wms_stock_detail();
                    tracedata.type = (int)traceType.WaveHousingOut;
                    tracedata.billID = orderData.order_number;
                    tracedata.inventory = stock.material_id;
                    tracedata.inventorySN = stock.material_pn;
                    tracedata.inventoryName = orderdetail.material_name;
                    tracedata.allqty = orderdetail.quantity;
                    tracedata.qty = item.count;
                    tracedata.userid = userId;
                    tracedata.username = GetUserName(userId);
                    tracedata.updatetime = DateTime.Now;
                    tracedata.state = (int)RowState.Valid;
                    tracedata.locationid = locationdata.id;
                    tracedata.locationname = locationdata.name;
                    tracedata.inventorySpec = stock.material_spec;
                    tracedata.state = (int)RowState.Valid;
                    tracedata.projectid = projectId;
                    if (type == managemodel.Batch)
                    {
                        tracedata.batch = code;
                    }
                    //供应商信息
                    tracedata.businessid = stock.businessid;
                    tracedata.businessName = GetBusinessName(stock.businessid, projectId);
                    dbContext.siger_wms_stock_detail.Add(tracedata);

                    //更新stock中的数量
                    stock.quantity -= item.count;
                    //更新状态为出库
                    if (stock.quantity == 0)
                    {
                        stock.stock_state = (int)StockEnum.OutWavehouse;
                    }
                    stockOuts.Add(stock.material_id);
                    dbContext.siger_wms_stock.Update(stock);
                }
            }
            //更新单据详情数量
            orderdetail.access_quantity += totalCount;
            orderData.auditor = userId;
            orderData.audit_time = DateTime.Now;
            orderData.audit_desc = "";
            orderData.audit_fail_reason = "";
            orderdetail.update_time = DateTime.Now;
            orderdetail.updator = userId;
            dbContext.siger_wms_stock_access_order_detail.Update(orderdetail);

            //汇总库存
            SubtractStockChange(orderData.storageid, orderdetail.material_id, totalCount, projectId);


            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            //更新单据状态
            if (orderData.order_status == (int)WaveHousingState.Checked)
            {
                orderData.order_status = (int)WaveHousingState.WaveHousingOut;
            }
            if (!IsExist(f => f.orderid == orderData.id && f.status == (int)RowState.Valid && f.projectid == projectId && f.quantity != f.access_quantity))
            {
                orderData.order_status = (int)WaveHousingState.WaveHousingOutFinish;
            }

            orderData.updator = userId;
            orderData.update_time = DateTime.Now;
            dbContext.siger_wms_stock_access_order.Update(orderData);

            if (dbContext.SaveChanges() <= 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            else
            {
                var materialids = new List<int>();
                foreach(var material_id in stockOuts)
                {
                    if (materialids.Contains(material_id))
                    {
                        continue;
                    }
                    materialids.Add(material_id);
                    var material = GetMaterial(material_id, projectId);
                    if(material == null)
                    {
                        continue;
                    }
                    var stock_Alarm = dbContext.siger_wms_stock_alarm.FirstOrDefault(t => t.material_id == material.id && t.projectid == projectId
                        && t.status == (int)AlarmStatus.Operating);
                    if (stock_Alarm != null)
                    {
                        stock_Alarm.trigger_time = UnixTimeHelper.GetNow();
                        dbContext.siger_wms_stock_alarm.Update(stock_Alarm);
                        dbContext.SaveChanges();
                        continue;
                    }
                    var stockTotal = dbContext.siger_wms_stock.Where(t => t.material_id == material.id && t.status == (int)RowState.Valid &&
                        t.projectid == projectId && t.stock_state == (int)StockEnum.InWavehouse).Sum(t => t.quantity);
                    if (stockTotal < material.min_stock || (material.min_stock == 0 && stockTotal == material.min_stock))
                    {
                        var alarm = new siger_wms_stock_alarm
                        {
                            material_id = material.id,
                            material_pn = material.pn,
                            information_type = (int)AlarmInfoType.StockAlarm,
                            creator = userId,
                            create_time = UnixTimeHelper.GetNow(),
                            projectid = projectId,
                            status = (int)RowState.Valid,
                            trigger_time = UnixTimeHelper.GetNow()
                        };
                        dbContext.siger_wms_stock_alarm.Add(alarm);
                        dbContext.SaveChanges();
                    }                    
                }
            }
        }

        public IEnumerable<siger_tr_materials> GetInventoryList(int projectId)
        {
            return dbContext.siger_tr_materials.Where(f => f.status == (int)RowState.Valid && f.projectId == projectId);
        }
    }
}

