using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Request;

namespace Siger.ApiWMS.Controllers
{
    /// <summary>
    /// 调拨
    /// </summary>
    public class AllocationController : BaseController
    {
        private readonly Isiger_wms_transfer_order_detailRepository detail;
        private readonly Isiger_wms_transfer_orderRepository bill;
        private readonly Isiger_wms_stock_detailRepository trace;
        private readonly IUnitOfWork _unitOfWork;
        private readonly Isiger_wms_storageRepository storage;
        private readonly Isiger_wms_storage_locationRepository location;
        private readonly Isiger_wms_stockRepository stock;
        private readonly object lockObj = new object();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="detail"></param>
        /// <param name="bill"></param>
        /// <param name="trace"></param>
        /// <param name="unitOfWork"></param>
        /// <param name="storage"></param>
        /// <param name="location"></param>
        /// <param name="stock"></param>
        public AllocationController(Isiger_wms_transfer_order_detailRepository detail, Isiger_wms_transfer_orderRepository bill, Isiger_wms_stock_detailRepository trace, IUnitOfWork unitOfWork, Isiger_wms_storageRepository storage, Isiger_wms_storage_locationRepository location, Isiger_wms_stockRepository stock)
        {
            this.detail = detail;
            this.bill = bill;
            this.trace = trace;
            _unitOfWork = unitOfWork;
            this.storage = storage;
            this.location = location;
            this.stock = stock;
        }

        /// <summary>
        /// 新增调拨单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddAllocationBill([FromBody]RequestAddAllocationBill req)
        {
            if (req.waveHouseID == req.endWaveHouseID)
            {
                throw new BadRequestException(RequestEnum.StartEndWavehouseEquals);
            }
            //检测单据号
            if (bill.IsExist(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.order_number == req.billcode))
            {
                throw new BadRequestException(RequestEnum.DataExist);
            }
            bill.AddAllocationBill(req.waveHouseID, req.endWaveHouseID, req.stockids, ProjectId, UserId, req.billcode);

            return Ok();
        }
        /// <summary>
        /// 更新单据信息
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult UpdateAllocationBill([FromBody]RequestUpdateAllocationBill req)
        {
            if (bill.IsExist(f => f.id == req.id && f.status == (int)RowState.Valid && f.order_status == (int)AlloactionStatu.Waitting && f.projectid == ProjectId))
            {
                bill.UpdateBill(req.id, req.stockids, ProjectId, UserId);
                return Ok();
            }
            throw new BadRequestException(CommonEnum.RecordNotFound);
        }


        /// <summary>
        /// 审核
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult CheckWaveHousing([FromBody]RequestCheck req)
        {
            //只审核未审核的数据
            if (!bill.IsExist(f => f.status == (int)RowState.Valid && f.id == req.id && f.order_status == (int)AlloactionStatu.Waitting && f.projectid == ProjectId))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var entity = bill.Get(f => f.id == req.id && f.projectid == ProjectId);

            var list = detail.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.orderid == entity.id).ToList();

            if (req.pass)
            {
                entity.order_status = (int)AlloactionStatu.Checked;
                foreach (var item in list)
                {
                    item.transfer_status = (int)AlloactionStatu.Checked;
                    detail.Update(item);
                }
            }
            else
            {
                entity.order_status = (int)AlloactionStatu.Failed;
                foreach (var item in list)
                {
                    item.transfer_status = (int)AlloactionStatu.Failed;
                    detail.Update(item);
                }
            }
            entity.audit_desc = req.des;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            entity.auditor = UserId;
            entity.audite_time = DateTime.Now;

            bill.Update(entity);

            if (_unitOfWork.Commit() > 0)
                return Ok();
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 反审
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult UnCheckWaveHousing([FromBody]RequestUncheck req)
        {
            //只反审核已审核的数据
            if (!bill.IsExist(f => f.status == (int)RowState.Valid && f.id == req.id && f.projectid == ProjectId))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var entity = bill.Get(f => f.id == req.id && f.projectid == ProjectId);

            if (entity.order_status != (int)AlloactionStatu.Checked && entity.order_status != (int)AlloactionStatu.Failed)
            {
                throw new BadRequestException(RequestEnum.UncheckDeny);
            }

            entity.order_status = (int)AlloactionStatu.Waitting;
            entity.auditor = UserId;
            entity.audit_desc = req.des;
            entity.audite_time = DateTime.Now;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            bill.Update(entity);

            var list = detail.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.orderid == entity.id).ToList();
            foreach (var item in list)
            {
                item.transfer_status = (int)AlloactionStatu.Waitting;
                detail.Update(item);
            }

            if (_unitOfWork.Commit() > 0)
                return Ok();
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 删除调拨单
        /// </summary>
        /// <param name="req"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Delete([FromBody]RequestDelStorage req)
        {
            var entity = bill.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.id == req.id);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }
            entity.order_status = (int)AlloactionStatu.Canceled;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            bill.Update(entity);
            var details = detail.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.orderid == entity.id);
            foreach (var item in details)
            {
                item.transfer_status = (int)AlloactionStatu.Canceled;
                detail.Update(item);
            }
            if (_unitOfWork.Commit() <= 0)
                throw new BadRequestException(CommonEnum.Fail);
            return Ok();
        }

        /// <summary>
        /// 查询调拨单
        /// </summary>
        /// <param name="fromWavehouseid"></param>
        /// <param name="toWavehouseid"></param>
        /// <param name="state"></param>
        /// <param name="billCode"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IActionResult GetBillList(int fromWavehouseid, int toWavehouseid, AlloactionStatu state, string billCode, int page = 1, int pageSize = 10)
        {
            Utility.CheckPage(page, pageSize);

            var result = bill.GetBillList(ProjectId, fromWavehouseid, toWavehouseid, state, billCode, page, pageSize, out int totalValue);

            return new PagedObjectResult(result, totalValue, page, pageSize);
        }

        /// <summary>
        /// 获取调拨单详情
        /// </summary>
        /// <param name="businessid"></param>
        /// <param name="id"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="start">调拨仓</param>
        /// <param name="end">目标仓</param>
        /// <param name="pn">料号</param>
        /// <param name="showAll"></param>
        /// <returns></returns>
        public IActionResult GetDetails(int showAll, int businessid, int id, int page, int pageSize, int start, int end, string pn)
        {
            Utility.CheckPage(page, pageSize);
            var result = detail.GetDetails(showAll, businessid, id, ProjectId, page, pageSize, out int totalValue, start, end, pn);

            return new PagedObjectResult(result, totalValue, page, pageSize);
        }

        //查询库存情况

        /// <summary>
        /// 调拨发出
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Allocation([FromBody]RequestAllocation req)
        {
            detail.Allocation(req.id, req.nodes, ProjectId, UserId, req.no);
            return Ok();
        }

        /// <summary>
        /// 调拨状态列表
        /// </summary>
        /// <returns></returns>
        public IActionResult GetState()
        {
            var dic = new List<kv>();
            modify(dic, AlloactionStatu.Waitting);
            modify(dic, AlloactionStatu.Checked);
            //modify(dic, AlloactionStatu.Alloaction);
            modify(dic, AlloactionStatu.Alloactioning);
            modify(dic, AlloactionStatu.WaittingReceiving);
            modify(dic, AlloactionStatu.Receiving);
            modify(dic, AlloactionStatu.Canceled);
            modify(dic, AlloactionStatu.Failed);
            modify(dic, AlloactionStatu.Finish);
            return new ObjectResult(dic);
        }
        private void modify(List<kv> dic, AlloactionStatu state)
        {
            dic.Add(new kv { k = (int)state, v = EnumHelper.GetEnumDesc(state) });
        }



        #region 下拉列表
        /// <summary>
        /// 获取所有调拨仓
        /// </summary>
        /// <returns></returns>
        public IActionResult GetWavehouse(int getAll)
        {
            if (getAll == 1)
            {
                var r = storage.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid).Select(f => new
                {
                    f.id,
                    f.name
                }).ToList();
                return new ObjectResult(r);
            }

            var storageids = bill.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid).Select(f => f.start_storage_id).ToList();
            var result = storage.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && storageids.Contains(f.id)).Select(f => new
            {
                f.id,
                f.name
            }).ToList();
            return new ObjectResult(result);
        }
        /// <summary>
        /// 查询目标仓
        /// </summary>
        /// <param name="start"></param>
        /// <returns></returns>
        public IActionResult GetWavehouseEnd(int start)
        {
            List<int> storageids;
            if (start == 0)
            {
                storageids = bill.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid).Select(f => f.end_storage_id).ToList();
            }
            else
            {
                storageids = bill.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.start_storage_id == start).Select(f => f.end_storage_id).ToList();
            }
            var result = storage.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && storageids.Contains(f.id)).Select(f => new
            {
                f.id,
                f.name
            }).ToList();
            return new ObjectResult(result);
        }

        /// <summary>
        /// 获取单号
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public IActionResult GetBillcode(int start, int end)
        {

            var data = bill.GetList(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.order_status != (int)AlloactionStatu.Canceled);
            if (start != 0)
            {
                data = data.Where(f => f.start_storage_id == start);
            }
            if (end != 0)
            {
                data = data.Where(f => f.end_storage_id == end);
            }
            var result = data.Select(f => new
            {
                f.id,
                name = f.order_number
            }).ToList();
            return new ObjectResult(result);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public IActionResult GetInventorySN(string billCode)
        {
            var result = stock.GetAllocationInventoryList(ProjectId, billCode);
            return new ObjectResult(result);
        }
        #endregion

        /// <summary>
        /// 调拨汇总
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public IActionResult GetAllocationBills(AlloactionStatu type)
        {
            var result = bill.GetAllocationBills(type, ProjectId);

            return new ObjectResult(result);
        }
    }
}