using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.WmsRepository.Entities;
using Siger.Middlelayer.WmsRepository.Repositories.Interface;
using Siger.Middlelayer.WmsRepository.Request;
using Siger.Middlelayer.WmsRepository.Response;

namespace Siger.ApiWMS.Controllers
{
    /// <summary>
    /// 盘点
    /// </summary>
    public class CheckController : BaseController
    {
        private readonly Isiger_wms_stocktake_orderRepository stocktack;
        private readonly Isiger_wms_stocktake_order_detailRepository detail;
        private readonly Isiger_wms_stock_access_orderRepository stockaccess;
        private readonly Isiger_wms_stockRepository stock;
        private readonly IUnitOfWork _unitOfWork;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="stocktack"></param>
        /// <param name="detail"></param>
        /// <param name="stockaccess"></param>
        /// <param name="stock"></param>
        /// <param name="unitOfWork"></param>
        public CheckController(Isiger_wms_stocktake_orderRepository stocktack, Isiger_wms_stocktake_order_detailRepository detail,
            Isiger_wms_stock_access_orderRepository stockaccess, Isiger_wms_stockRepository stock, IUnitOfWork unitOfWork)
        {
            this.stocktack = stocktack;
            this.detail = detail;
            this.stockaccess = stockaccess;
            this.stock = stock;
            _unitOfWork = unitOfWork;
        }


        /// <summary>
        /// 盘点汇总
        /// </summary>
        /// <returns></returns>
        public IActionResult GetBills(CheckStatu type, int page = 1, int pageSize = 10)
        {
            Utility.CheckPage(page, pageSize);
            IEnumerable<ResponseWaveHousing> result = stocktack.GetBills(type, ProjectId, page, pageSize, out int totalCount);

            return new PagedObjectResult(result, totalCount, page, pageSize);
        }
        /// <summary>
        /// 盘点状态列表
        /// </summary>
        /// <returns></returns>
        public IActionResult GetState()
        {
            var dic = new List<kv>();
            modify(dic, CheckStatu.Waitting);
            modify(dic, CheckStatu.Checked);
            modify(dic, CheckStatu.Checking);
            modify(dic, CheckStatu.Canceled);
            modify(dic, CheckStatu.Failed);
            modify(dic, CheckStatu.Finish);

            return new ObjectResult(dic);
        }
        private void modify(List<kv> dic, CheckStatu state)
        {
            dic.Add(new kv { k = (int)state, v = EnumHelper.GetEnumDesc(state) });
        }

        /// <summary>
        /// 获取单据表头信息
        /// </summary>
        /// <param name="storageid">仓库名称</param>
        /// <param name="type">状态</param>
        /// <param name="sn">单号</param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <returns></returns>
        public IActionResult GetBillList(int storageid, CheckStatu type, string sn, int page = 1, int pageSize = 10)
        {
            Utility.CheckPage(page, pageSize);

            var result = stocktack.GetBillList(storageid, type, sn, page, pageSize, out int totalCount, ProjectId, UserId);
            return new PagedObjectResult(result, totalCount, page, pageSize);
        }
        /// <summary>
        /// 根据单据获取详情
        /// </summary>
        /// <returns></returns>
        public IActionResult GetBillDetail(int id, int page = 1, int pageSize = 10)
        {
            Utility.CheckPage(page, pageSize);
            var data = detail.GetList(f => f.orderid == id && f.status == (int)RowState.Valid);
            var totaoCount = data.Count();
            data=Utility.Paging(data, page, pageSize).ToList().AsQueryable();

            var result = new List<ResponseCheckDetail>();
            //transform 盘盈 盘亏
            var more = EnumHelper.GetEnumDesc(CheckedStatu.MORE);
            var less = EnumHelper.GetEnumDesc(CheckedStatu.LESS);
            foreach (var item in data)
            {
                var tmp = Mapper<siger_wms_stocktake_order_detail, ResponseCheckDetail>.Map(item);
                if (item.stocktake_status != (int)CheckStatu.Finish)
                {
                    tmp.stateName = EnumHelper.GetEnumDesc(((CheckStatu)item.stocktake_status));
                }
                else
                {
                    if (item.stocktaked_quantity < item.quantity)
                    {
                        tmp.stateName = less;
                    }
                    else
                    {
                        tmp.stateName = more;
                    }
                }
                //批次号、序号
                var stockData = stock.Get(f => f.id == tmp.stockid&&f.projectid==ProjectId);
                if(stockData!=null)
                {
                    tmp.batch = stockData.batch_number??"";
                    tmp.serial_number = stockData.serial_number??"";
                }
                result.Add(tmp);
            }
            return new PagedObjectResult(result, totaoCount, page, pageSize);
        }

        /// <summary>
        /// 获取单据号
        /// </summary>
        /// <returns></returns>
        public IActionResult GetBillCode()
        {
            var billcode = Utility.GenSerialNumber();
            while (stocktack.IsExist(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.order_number == billcode))
            {
                System.Threading.Thread.Sleep(10);
                billcode = Utility.GenSerialNumber();
            }
            return new ObjectResult(billcode);
        }

        /// <summary>
        /// 新增盘点单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddCheckBill([FromBody]RequestAddCheckBill req)
        {
            //检测单据号
            if (stocktack.IsExist(f => f.projectid == ProjectId && f.status == (int)RowState.Valid && f.order_number == req.billcode))
            {
                throw new BadRequestException(RequestEnum.DataExist);
            }
            stocktack.AddCheckBill(req.waveHouseID, req.stockids, ProjectId, UserId,req.billcode);

            return Ok();
        }

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

        }

        /// <summary>
        /// 删除盘点单
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult DeleteBill([FromBody]RequestDelBusiness req)
        {
            //只删除未审核的数据
            if (!stocktack.IsExist(f => f.status == (int)RowState.Valid && f.id == req.id && f.order_status == (int)CheckStatu.Waitting && f.projectid == ProjectId))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var entity = stocktack.Get(f => f.id == req.id && f.projectid == ProjectId);
            entity.status = (int)RowState.Invalid;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            stocktack.Update(entity);

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

        /// <summary>
        /// 审核
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult CheckWaveHousing([FromBody]RequestCheck req)
        {
            //只审核未审核的数据
            if (!stocktack.IsExist(f => f.status == (int)RowState.Valid && f.id == req.id && f.order_status == (int)CheckStatu.Waitting && f.projectid == ProjectId))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var entity = stocktack.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)CheckStatu.Checked;
                foreach (var item in list)
                {
                    item.stocktake_status = (int)CheckStatu.Checked;
                    detail.Update(item);
                }
            }
            else
            {
                entity.order_status = (int)CheckStatu.Failed;
                foreach (var item in list)
                {
                    item.stocktake_status = (int)CheckStatu.Failed;
                    detail.Update(item);
                }
            }
            entity.audit_desc = req.des;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            entity.auditor = UserId;
            entity.audit_time = DateTime.Now;
            stocktack.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 (!stocktack.IsExist(f => f.status == (int)RowState.Valid && f.id == req.id && f.projectid == ProjectId))
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

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

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

            entity.order_status = (int)CheckStatu.Waitting;
            entity.auditor = UserId;
            entity.audit_desc = req.des;
            entity.audit_time = DateTime.Now;
            entity.update_time = DateTime.Now;
            entity.updator = UserId;
            stocktack.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.stocktake_status = (int)CheckStatu.Waitting;
                detail.Update(item);
            }
            if (_unitOfWork.Commit() > 0)
                return Ok();
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 盘点手动完成
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Manual(RequestManual req)
        {
            var entity = stocktack.Get(f => f.status == (int)RowState.Valid && f.projectid == ProjectId);
            if (entity == null)
            {
                throw new BadRequestException(CommonEnum.NoData);
            }

            //检测现有状态
            switch ((CheckStatu)entity.order_status)
            {
                case CheckStatu.Waitting:
                case CheckStatu.Finish:
                case CheckStatu.Canceled:
                case CheckStatu.Failed:
                    throw new BadRequestException(RequestEnum.CheckStatuError);
                default:
                    break;
            }
            entity.order_status = (int)CheckStatu.Finish;
            if(!string.IsNullOrEmpty(req.manual))
            {
                entity.manual = req.manual;
            }
            stocktack.Update(entity);
            var detailsList = detail.GetList(f => f.status == (int)RowState.Valid && f.projectid == ProjectId && f.order_number == entity.order_number).ToList();
            foreach (var item in detailsList)
            {
                item.stocktake_status = (int)CheckStatu.Finish;
                detail.Update(item);
            }
            if (_unitOfWork.Commit() > 0)
                return Ok();
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 报表->盘点单据信息汇总
        /// </summary>
        /// <param name="storageid"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="state">1 盘亏、0 盘盈</param>
        /// <returns></returns>
        public IActionResult GetCheckSummary(int storageid, DateTime start, DateTime end,int page,int pageSize, CheckedStatu state)
        {
            var result = stocktack.GetBillList(storageid,CheckStatu.Finish, "", page, pageSize, out int totalCount, ProjectId, UserId, state,false, start, end);

            return new ObjectResult(result);
        }

        /// <summary>
        /// 报表->盘点单据信息导出
        /// </summary>
        /// <param name="storageid"></param>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <param name="page"></param>
        /// <param name="pageSize"></param>
        /// <param name="state">1 盘亏、0 盘盈</param>
        /// <returns></returns>
        public IActionResult ExportCheckSummary(int storageid, DateTime start, DateTime end, int page, int pageSize, CheckedStatu state)
        {
            var result = stocktack.GetBillList(storageid, CheckStatu.Finish, "", page, pageSize, out int totalCount, ProjectId, UserId, state, true,start,end);
            //获取配置信息
            
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            string temporaryFileName = $"checksummaryinfo_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            //绑定数据并导出
            var index = 1;
            var exportData = new List<ExportCheckSummary>();

            foreach (var item in result)
            {
                var tmp = Mapper<ResponseGetBillList, ExportCheckSummary>.Map(item);
                tmp.id = index++;
                exportData.Add(tmp);
            }

            var helper = new EpPlusExcelHelper<ExportCheckSummary>();
            try
            {
                helper.GenerateExcel(exportData, fileName);

                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("ExportStock failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }
    }
}