using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using Siger.Middlelayer.QmsRepository.Request;
using Siger.Middlelayer.QmsRepository.Response;
using Siger.Middlelayer.QmsRepository.Entities;
using Siger.ApiCommon.Result;
using Siger.ApiCommon;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Repository.Repositories.Interface;

using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Utility.ImportEntities;
using Siger.Middlelayer.Utility.Helpers;
using System.IO;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Common.AppSettings;
using Siger.ApiCommon.Utilities;
using System.Linq.Expressions;
using Siger.Middlelayer.Repository.Extensions;
using OfficeOpenXml.FormulaParsing.Excel.Functions.DateTime;
using NPOI.SS.Formula.Functions;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Repository.Paged;
using Siger.Middlelayer.Common.Helpers;

namespace Siger.ApiQMS.Controllers
{
  

    public class RepairDataController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IQmsReworkDataRepository _reworkDataRepository;
        private readonly ISigerProjectProductRepository _sigerProjectProduct;
        private readonly IQmsReworkReferenceRepository _reworkReferenceRepository;
        private readonly IQmsReworkReferenceTypeRepository _qmsReworkReferenceType;
        private readonly IQmsReworkDataMaterialRepository _qmsReworkDataMaterial;
        private readonly IQmsReworkDataTotalRepository _qmsReworkDataTotalRepository;
        private readonly ISigerTrMaterialsRepository _sigerTrMaterialsRepository;
        private readonly ISigerProjectLevelSectionRepository _sigerProjectLevelSection;
        private readonly IInspectStandardRepository _inspectStandard;
        private readonly IQmsReworkPositionSetting _reworkPositionSetting;

        public RepairDataController(IUnitOfWork unitOfWork, IQmsReworkDataRepository reworkDataRepository, ISigerProjectProductRepository sigerProjectProduct, IQmsReworkReferenceRepository qmsReworkReference, IQmsReworkReferenceTypeRepository qmsReworkReferenceType,IQmsReworkDataMaterialRepository qmsReworkDataMaterial,
            IQmsReworkDataTotalRepository reworkDataTotalRepository, ISigerTrMaterialsRepository sigerTrMaterials, ISigerProjectLevelSectionRepository sigerProjectLevelSection, IInspectStandardRepository inspectStandard, IQmsReworkPositionSetting reworkPositionSetting)
        {
            _unitOfWork = unitOfWork;
            _reworkDataRepository = reworkDataRepository;
            _sigerProjectProduct = sigerProjectProduct;
            _reworkReferenceRepository = qmsReworkReference;
            _qmsReworkReferenceType = qmsReworkReferenceType;
            _qmsReworkDataMaterial = qmsReworkDataMaterial;
            _qmsReworkDataTotalRepository = reworkDataTotalRepository;
            _sigerTrMaterialsRepository = sigerTrMaterials;
            _sigerProjectLevelSection = sigerProjectLevelSection;
            _inspectStandard = inspectStandard;
            _reworkPositionSetting = reworkPositionSetting;
        }
        /// <summary>
        /// 列表
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult Getlist([FromBody]RequestRepairlist param)
        {
            var staions = _sigerProjectLevelSection.GetLevelSectionIds(param.Section, ProjectId).Distinct().ToList();

            IPagedCollectionResult<ResponseRepairData> data;
            if (param.reworkDataType== ReworkDataType.Rework)
                data= _reworkDataRepository.GetReworkPagedList(staions, param.MaterialId, param.ProductId, param.PreRoute, param.Route, 0, param.Sn, param.BeginTime, param.EndTime, ProjectId, param.Page, param.PageSize);
            else
                data = _reworkDataRepository.GetWastePagedList(staions, param.MaterialId, param.ProductId, param.PreRoute, param.Route, 0, param.Sn, param.BeginTime, param.EndTime, ProjectId, param.Page, param.PageSize);
            
       
            return new PagedLongTotalObjectResult(data.Data, data.Total, param.Page, param.PageSize);
        }
        private string GetAllTitle(int sectionId)
        {
            var titles = _sigerProjectLevelSection.GetLevelSectionTitles(sectionId, ProjectId);
            var list = titles.ToList();
            return list.Any() ? string.Join('-', list) : string.Empty;
        }
        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ExporExcel([FromBody]RequestRepairlist param)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var staions = _sigerProjectLevelSection.GetLevelSectionIds(param.Section, ProjectId).Distinct().ToList();

            IPagedCollectionResult<ResponseRepairData> data;
            if (param.reworkDataType == ReworkDataType.Rework)
                data = _reworkDataRepository.GetReworkPagedList(staions, param.MaterialId, param.ProductId, param.PreRoute, param.Route, 0, param.Sn, param.BeginTime, param.EndTime, ProjectId, 1, 9999999);
            else
                data = _reworkDataRepository.GetWastePagedList(staions, param.MaterialId, param.ProductId, param.PreRoute, param.Route, 0, param.Sn, param.BeginTime, param.EndTime, ProjectId, 1, 9999999);

            if (data.Data.Any())
                throw new BadRequestException(CommonEnum.Fail);

            var dataList = new List<ScrapReworkRepairData>();
            var datalistRework = new List<ReworkRepairData>();
            foreach (var item in data.Data)
            {
                var StationDesc = GetAllTitle(item.SectionId);
                var routeDesc = GetAllTitle(item.Route);
                dataList.Add(new ScrapReworkRepairData
                {
                    Sn = item.Sn,
                    ProductCode = item.ProductCode,
                    ProductName = item.ProductName,
                    Qty = item.Qty,
                    Material = item.MaterialName,
                    Pn = item.Pn,
                    MaterialSpec = item.MaterialSpec,
                    //PreRoute = item.PreRouteDesc,
                    Route = routeDesc,
                    DateTime = item.Datetime,
                    Remark = item.Remark,
                    User = item.User,
                    RouteType = item.ReferTypeDesc,
                    BadItem = item.OItem,
                    Count = item.Count
                });

                datalistRework.Add(new ReworkRepairData
                {
                    PreRoute = StationDesc,
                    Sn = item.Sn,
                    ProductCode = item.ProductCode,
                    ProductName = item.ProductName,
                    Qty = item.Qty,
                    Material = item.MaterialName,
                    Pn = item.Pn,
                    MaterialSpec = item.MaterialSpec,

                    Route = routeDesc,
                    DateTime = item.Datetime,
                    Remark = item.Remark,
                    User = item.User,
                    BadItem = item.OItem,
                    Count = item.Count
                });
            }

            if (param.reworkDataType == ReworkDataType.Waste)
            {
                EpPlusExcelHelper<ScrapReworkRepairData> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ScrapReworkRepairData>();
                    var temporaryFileName = $"报废管理_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName), true);
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("Export scrapData Standard Info failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }
            else
            {
                EpPlusExcelHelper<ReworkRepairData> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ReworkRepairData>();
                    var temporaryFileName = $"返工管理_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(datalistRework, Path.Combine(rootDir, temporaryFileName), true);
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("Export Reworkdata Info failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        ///  查询二维码 产品
        /// </summary>
        /// <param name="sn"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetProductRoute(string sn)
        {
            var result = _reworkDataRepository.GetOQCItemBysn(ProjectId, sn);
            return new ObjectResult(result);
        }
        [HttpGet]
        public IActionResult GetProductRouteNotSn(int productId)
        {
           var data= _reworkDataRepository.GetRouteBySn("", productId,ProjectId).ToList();
            return new ObjectResult(data);
        }

        /// <summary>
        /// 添加维修
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddRepair([FromBody] RequestAddRepair param)
        {
            var product = _sigerProjectProduct.Get(param.ProductId);
            if (product == null)
                throw new BadRequestException(RequestEnum.ProductNotFound);

            var repairSetting = _reworkPositionSetting.Get(f => f.id == param.SettingId);
            if (repairSetting==null)
                throw new BadRequestException(CommonEnum.RecordNotFound);

            var maxObj = _reworkDataRepository.GetList(f => f.projectid == ProjectId).LastOrDefault();
            int key = 1;
            key += maxObj!=null?maxObj.id:0;

            _reworkDataRepository.Insert(new siger_qms_rework_data
            {
                id=key,
                projectid = ProjectId,
                //Section_Id = param.SectionId,
                Section_Id= repairSetting.Prestation,
                Sn = param.Sn,
                Product_Id = param.ProductId,
                Material_Id = param.Materail,
                preroute_id = param.PreRoute,
                Route_Id=repairSetting.Station,
                //Route_Id = param.Route,
                SnType = param.SnType,
                OQC_Id = param.QID,
                Remark = param.Remark,
                DateTime = DateTime.Now,
                status = (int) RowState.Valid,
                Type = (int) ReworkDataType.Rework,
                User_Id = UserId,
                Count = param.Count
            });
            _qmsReworkDataMaterial.Insert(new siger_qms_rework_data_material
            {
                projectid = ProjectId,
                reworkid = key,
                material_id = param.Materail,
                qty = param.Count,
                status = (int)RowState.Valid
            });

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

        /// <summary>
        /// 编辑
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ModifyRepair([FromBody] RequestAddRepair param)
        {
            var product = _sigerProjectProduct.Get(param.ProductId);
            if (product == null)
                throw new BadRequestException(RequestEnum.ProductNotFound);
            var reworkData = _reworkDataRepository.Get(f => f.projectid == ProjectId && f.id == param.Id);
            if (reworkData == null)
                throw new BadRequestException(CommonEnum.RecordNotFound);

            if (reworkData.Type == (int)ReworkDataType.Rework)
            {
                //检查返修工站设置
                var repairSetting = _reworkPositionSetting.Get(f => f.id == param.SettingId);
                if (repairSetting == null)
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                reworkData.Sn = param.Sn;
                reworkData.Section_Id = repairSetting.Prestation;
                reworkData.Product_Id = param.ProductId;
                reworkData.Material_Id = param.Materail;
                reworkData.Route_Id = repairSetting.Station;
                reworkData.SnType = param.SnType;
                reworkData.OQC_Id = param.QID;
                reworkData.DateTime = DateTime.Now;
                reworkData.Count = param.Count;
                reworkData.Remark = param.Remark;
            }else
            {   //报废
                reworkData.Sn = param.Sn;
                reworkData.Section_Id = param.SectionId;
                reworkData.Product_Id = param.ProductId;
                //reworkData.Material_Id = param.Materail;
                reworkData.Route_Id = param.Route;
                reworkData.OQC_Id = param.QID;
                reworkData.DateTime = DateTime.Now;
                reworkData.Count = param.Qty;
                reworkData.Remark = param.Remark;
                var dtsMaterial = _qmsReworkDataMaterial.Get(param.DetailsId);
                if (dtsMaterial==null)
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                dtsMaterial.material_id = param.Materail;
                dtsMaterial.qty = param.Count;
            }
            _reworkDataRepository.Update(reworkData);

            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 添加报废
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddWaste([FromBody]RequestAddRepariData param)
        {            
            var product = _sigerProjectProduct.Get(param.ProductId);
            if (product == null)
                throw new BadRequestException(RequestEnum.ProductNotFound);

            if(param.Materail == null || !param.Materail.Any())
                throw new BadRequestException(RequestEnum.MaterialeError);

            var maxObj = _reworkDataRepository.GetList(f => f.projectid == ProjectId).LastOrDefault();
            int key = 1;
          
            key += maxObj==null?0: maxObj.id;
            _reworkDataRepository.Insert(new siger_qms_rework_data
            {
                id=key,
                projectid = ProjectId,
                Section_Id = param.SectionId,
                Sn = param.Sn,
                Product_Id = param.ProductId,
                preroute_id = param.PreRoute,
                Route_Id = param.Route,
                SnType = param.SnType,
                OQC_Id = param.QID,
                Remark = param.Remark,
                Type = (int)ReworkDataType.Waste,
                DateTime = DateTime.Now,
                User_Id = UserId,
                status = (int)RowState.Valid,
                Count = param.Count
            });
            foreach (var material in param.Materail)
            {
                _qmsReworkDataMaterial.Insert(new siger_qms_rework_data_material {
                   projectid=ProjectId,
                   reworkid=key,
                   material_id=material.id,
                   qty=material.qty,
                   status=(int)RowState.Valid
                });
            }
            if (_unitOfWork.Commit() > 0)
                return new ObjectResult(CommonEnum.Succefull);
            throw new BadRequestException(CommonEnum.Fail);

        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="details"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult DelRecord(int id,int details)
        {
            var reworkData = _reworkDataRepository.Get(f => f.projectid == ProjectId && f.id == id);
            if (reworkData == null)
                throw new BadRequestException(CommonEnum.RecordNotFound);
            if (reworkData.Type == (int)ReworkDataType.Waste)
            {
                var dtsObj = _qmsReworkDataMaterial.Get(f => f.id == details);
                if (dtsObj==null)
                    throw new BadRequestException(CommonEnum.RecordNotFound);

                var dtslist = _qmsReworkDataMaterial.GetList(f => f.reworkid == reworkData.id);
                if (dtslist.Count() == 1)
                {
                    _reworkDataRepository.Delete(reworkData.id); // 删除主表
                }
                _qmsReworkDataMaterial.Delete(details);

            }
            else
            {
                _reworkDataRepository.Delete(reworkData.id);
            }

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

        private bool InsertWaste(RequestAddRepariData param, WasteMaterail materialid)
        {
            _reworkDataRepository.Insert(new siger_qms_rework_data
            {
                projectid = ProjectId,
                Section_Id = param.SectionId,
                Sn = param.Sn,
                Product_Id = param.ProductId,
             
                Material_Id = materialid.id,
                preroute_id = param.PreRoute,
                Route_Id = param.Route,
                SnType = param.SnType,
                OQC_Id = param.QID,
                Remark = param.Remark,
                Type = (int)ReworkDataType.Waste,
                DateTime = DateTime.Now,
                User_Id = UserId,
                status = (int)RowState.Valid,
                Count = materialid.qty
            });
            if (!_reworkReferenceRepository.IsExist(f => f.projectid == ProjectId && f.Remark == param.Remark))
            {
                _reworkReferenceRepository.Insert(new Middlelayer.QmsRepository.Entities.siger_qms_rework_reference
                {
                    projectid = ProjectId,
                    Type = (int)ReworkDataType.Waste,
                    Remark = param.Remark,
                    DateTime = DateTime.Now,
                    status = (int)RowState.Valid,
                });
            }
            GrandTotal(param.ProductId, materialid.qty, param.Route, (int)ReworkDataType.Waste, param.Count);
            if (_unitOfWork.Commit() > 0)
            {
                return true;
            }
            else
            {
                return false;
            }            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetReference(int type)
        {
            var reference= _reworkReferenceRepository.GetList(f => f.projectid == ProjectId && f.Type == type);
            return new ObjectResult(reference);
        }

        /// <summary>
        /// 报废率 分析 (废弃)
        /// </summary>
        /// <param name="section"></param>
        /// <param name="productId"></param>
        /// <param name="materialId"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetRateWate(int section,int productId,int materialId,DateTime stime,DateTime etime)
        {
            //Expression<Func<siger_qms_rework_data_ttl, bool>> funcSection = f => true;
            //Expression<Func<siger_qms_rework_data_ttl, bool>> funcProduct = f => true;
            //Expression<Func<siger_qms_rework_data_ttl, bool>> funcMaterial = f => true;
            //Expression<Func<siger_qms_rework_data_ttl, bool>> funcTrue = f => true;
            ////Expression<Func<siger_qms_rework_data_ttl, bool>> funcYear = f => true;
            //if (section!=0)
            //    funcSection = f => f.Section == section;
            //if (productId != 0)
            //    funcProduct = f => f.ProductId == productId;
            //if (materialId != 0)
            //    funcMaterial = f => f.MaterialId == materialId;
            //当前 -前两年

            //var sYdate = stime.Year-2;
            //var eYdate = etime.Year;
            //funcTrue = f => f.projectid == ProjectId && f.Type==(int)ReworkDataType.Waste && f.status == (int)RowState.Valid && f.Year>=sYdate && f.Year<=eYdate;
            //funcYear = f => f.projectid == ProjectId && f.Type == (int)ReworkDataType.Waste && f.status == (int)RowState.Valid && f.Year >= sYdate && f.Year <= eYdate;
            //funcTrue = f => f.projectid == ProjectId && f.Type == (int)ReworkDataType.Waste && f.status == (int)RowState.Valid && f.Busidate >= stime && f.Busidate <= etime;
            //var predicate = funcSection.And(funcProduct).And(funcMaterial).And(funcTrue);
            var reponse = new ResponseReworkDataEcharts();
            //var alldata = _qmsReworkDataTotalRepository.GetList(predicate);
            //var yearTotal= _qmsReworkDataTotalRepository.GetList(funcYear);
            //var allData = _reworkDataRepository.GetRepairAllData(new List<int> { section }, materialId, productId,0,0);
            //var yStep = eYdate - sYdate;
            //double preYearTtl = yearTotal.Sum(s => s.Count);
            //for (int i=0;i <= yStep; i++)
            //{
            //    var yearData = yearTotal.Where(f => f.Year == sYdate + i);
            //    reponse.X.Add($"{sYdate + i}年");
            //    reponse.Y.Add(yearData.Sum(s => s.Count));
            //    if (preYearTtl>0)
            //    {
            //        var YearPercent= yearData.Sum(s => s.Count) / preYearTtl;
            //        reponse.Rate.Add(Math.Round(YearPercent, 2) * 100);
            //    }else
            //    {
            //        reponse.Rate.Add(0d);
            //    }
            //}
            //当年12个月
            //var currYearData = alldata.Where(f => f.Year == etime.Year);
            //double curYearTtl = currYearData.Sum(s => s.Count);
            //for (int i=0; i<12;i ++)
            //{
            //    var monthData = currYearData.Where(f =>f.Month == i+1);
            //    reponse.X.Add( $"{ i + 1 }月");
            //    reponse.Y.Add(monthData.Sum(s=>s.Count));
            //    if (curYearTtl > 0)
            //    {
            //        var YearPercent = monthData.Sum(s => s.Count) / curYearTtl;
            //        reponse.Rate.Add(Math.Round(YearPercent, 2) * 100);
            //    }
            //    else
            //    {
            //        reponse.Rate.Add(0d);
            //    }
            //}
            return new ObjectResult(reponse);
        }
        /// <summary>
        /// Top N 报废数据
        /// </summary>
        /// <param name="section"></param>
        /// <param name="productId"></param>
        /// <param name="materialId"></param>
        /// <param name="stime"></param>
        /// <param name="etime"></param>
        /// <param name="top"></param>
        /// <param name="type">1:物料 2：不良项目 3：报废原因 4 通道工位</param>
        /// <param name="export"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetRateWateTop(int section,int productId, int materialId, DateTime stime, DateTime etime,int top,int type,int export)
        {
            var reponse = new ResponseReworkDataEcharts();
            var staions = _sigerProjectLevelSection.GetLevelSectionIds( section,ProjectId).Distinct().ToList();
            var wasteData = _reworkDataRepository.GetResponseWaste(staions, productId, ProjectId, stime, etime.AddDays(1).AddMinutes(-1)).ToList();
            double ttl = wasteData.Sum(s => s.Count);
            //统计维度
            switch (type)
            {
                case 0:
                case 1: //物料
                    {
     
                        var grpCondition = wasteData.GroupBy(g => g.Material);
                        var listData = new List<ReworkWasteList>();
                        foreach (var c in grpCondition)
                        {
                            var material = _sigerTrMaterialsRepository.Get(f => f.id == c.Key);
                            var productlst = c.ToList();
                            listData.Add(new ReworkWasteList
                            {
                                Material = material == null ? c.Key.ToString() : $"[{material.pn}]+{material.name}",
                                Count = productlst.Sum(f => f.Count)
                            });
                        }
                        var topData = listData.OrderByDescending(d => d.Count).Skip(0).Take(top);
                        foreach (var t in topData)
                        {
                            reponse.X.Add(t.Material);
                            reponse.Y.Add(t.Count);
                            var tableobj = new ResponseWasteAnalysisEchartTable
                            {
                                Item = t.Material,
                                Val = t.Count,
                            };
                            if (ttl > 0)
                            {
                                var percent = t.Count / ttl;
                                var percentage = Math.Round(percent * 100, 4);
                                reponse.Rate.Add(percentage);
                                tableobj.Rate = percentage ;
                            }
                            else
                            {
                                reponse.Rate.Add(0d);
                            }
                            reponse.Tables.Add(tableobj);
                        }

                        break;
                    }
                case 2://不良项目
                    {
                        var grpCondition = wasteData.GroupBy(g => g.Item);
                        var listData = new List<ReworkWasteList>();
                        foreach (var c in grpCondition)
                        {
                            var oqc = _inspectStandard.Get(f => f.id == c.Key);
                            var productlst = c.ToList();
                            listData.Add(new ReworkWasteList
                            {
                                Material = oqc == null ? c.Key.ToString() : oqc.item,
                                Count = productlst.Sum(f => f.Count)
                            });
                        }
                        var topData = listData.OrderByDescending(d => d.Count).Skip(0).Take(top);
                        foreach (var t in topData)
                        {
                            reponse.X.Add(t.Material);
                            reponse.Y.Add(t.Count);
                            var tableobj = new ResponseWasteAnalysisEchartTable
                            {
                                Item = t.Material,
                                Val = t.Count,
                            };
                            if (ttl > 0)
                            {
                                var percent = t.Count / ttl;
                                var percentage = Math.Round(percent * 100, 4);
                                reponse.Rate.Add(percentage);
                                tableobj.Rate = percentage;
                            }
                            else
                            {
                                reponse.Rate.Add(0d);
                            }
                            reponse.Tables.Add(tableobj);
                        }
                        break;
                    }
                case 3: //报废原因
                    {
                     
                        var grpCondition = wasteData.GroupBy(g => g.Cause);
                        var listData = new List<ReworkWasteList>();
                        foreach (var c in grpCondition)
                        {
                            var productlst = c.ToList();
                            listData.Add(new ReworkWasteList
                            {
                                Material = c.Key,
                                Count = productlst.Sum(f => f.Count)
                            });
                        }
                        var topData = listData.OrderByDescending(d => d.Count).Skip(0).Take(top);
                        foreach (var t in topData)
                        {
                            reponse.X.Add(t.Material);
                            reponse.Y.Add(t.Count);
                            var tableobj = new ResponseWasteAnalysisEchartTable
                            {
                                Item = t.Material,
                                Val = t.Count,
                            };
                            if (ttl > 0)
                            {
                                var percent = t.Count / ttl;
                                var percentage = Math.Round(percent * 100, 4);
                                reponse.Rate.Add(percentage);
                                tableobj.Rate = percentage;
                            }
                            else
                            {
                                reponse.Rate.Add(0d);
                            }
                            reponse.Tables.Add(tableobj);
                        }
                        break;
                    }
                case 4: //工位
                    {
                      
                        var grpCondition = wasteData.GroupBy(g => g.Section);
                        var listData = new List<ReworkWasteList>();
                        foreach (var c in grpCondition)
                        {
                            var stationObj = _sigerProjectLevelSection.Get(f => f.id == c.Key);
                            var productlst = c.ToList();
                            listData.Add(new ReworkWasteList
                            {
                                Material = stationObj==null?c.Key.ToString():stationObj.title,
                                Count = productlst.Sum(f => f.Count)
                            });
                        }
                        var topData = listData.OrderByDescending(d => d.Count).Skip(0).Take(top);
                        foreach (var t in topData)
                        {
                            reponse.X.Add(t.Material);
                            reponse.Y.Add(t.Count);
                            var tableobj = new ResponseWasteAnalysisEchartTable
                            {
                                 Item=t.Material,
                                 Val=t.Count,
                            };
                            if (ttl > 0)
                            {
                                var percent = t.Count / ttl;
                                var percentage = Math.Round(percent * 100, 4);
                                reponse.Rate.Add(percentage);
                                tableobj.Rate = percentage;
                            }
                            else
                            {
                                reponse.Rate.Add(0d);
                            }
                            reponse.Tables.Add(tableobj);
                        }
                        break;
                    }
            }

       
            return new ObjectResult(reponse);
        }



        /// <summary>
        /// 报废统计
        /// </summary>
        /// <param name="productId"></param>
        /// <param name="materialId"></param>
        /// <param name="section"></param>
        /// <param name="type"></param>
        /// <param name="count"></param>
        void GrandTotal(int productId,int materialId,int section,int type,int count)
        {
            var busidate = DateTimeHelper.GetTodayStartTime();
            var materialObj = _sigerTrMaterialsRepository.Get(f => f.id == materialId);
            if (materialObj == null)
                return;
            var materialTtlObj = _qmsReworkDataTotalRepository.Get(f => f.projectid == ProjectId && f.Busidate==busidate && f.ProductId == productId && f.MaterialId == materialId && f.Type==type);
            if (materialTtlObj == null)
            {
                _qmsReworkDataTotalRepository.Insert(new siger_qms_rework_data_ttl
                {
                    Busidate = busidate,
                    Year = busidate.Year,
                    Month = busidate.Month,
                    ProductId = productId,
                    MaterialId = materialId,
                    Section = section,
                    Type = type,
                    Price = materialObj.price,
                    projectid = ProjectId,
                    status = (int)RowState.Valid,
                    Count=count
                    
                });
            }else
            {
                materialTtlObj.Count += count;
                materialTtlObj.Price += materialObj.price;
                _qmsReworkDataTotalRepository.Update(materialTtlObj);
            }
        }

        /// <summary>
        /// 20200605
        /// 报废品分析
        /// </summary>
        /// <param name="section">产线层级</param>
        /// <param name="productId">产品ID</param>
        /// <param name="starttime">时间</param>
        /// <param name="endtime">时间</param>
        /// <param name="chartType">统计类型：1 通道，2 工位，3 报废项目，4 报废类别，5 报废原因</param>
        /// <param name="xType">统计维度 1 金额，2 报废率</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetWasteAnalysis(int section,int productId,string starttime, string endtime, int chartType, int xType)
        {
            var staions = _sigerProjectLevelSection.GetLevelSectionIds(section, ProjectId).Distinct().ToList();
            var reWorkData = _reworkDataRepository.GetResponseWaste(staions,productId,ProjectId, 
                starttime.ToDateTime(), endtime.ToDateTime().AddDays(1).AddMilliseconds(-1)).ToList();
 
            var eChartData = GetEchartData(reWorkData,chartType,xType);
            return new ObjectResult(eChartData);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="section"></param>
        /// <param name="productId"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <param name="chartType"></param>
        /// <param name="xType"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult ExportEexcel(int section, int productId, string starttime, string endtime, int chartType, int xType)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);

            var staions = _sigerProjectLevelSection.GetLevelSectionIds(section, ProjectId).Distinct().ToList();
            var reWorkData = _reworkDataRepository.GetResponseWaste(staions, productId, ProjectId, starttime.ToDateTime(), endtime.ToDateTime().AddDays(1).AddMilliseconds(-1)).ToList();
           if (!reWorkData.Any())
                throw new BadRequestException(CommonEnum.RecordNotFound); 
            
            var eChartData = GetEchartData(reWorkData, chartType, xType);
            var data = eChartData.tables;
            var dataList = new List<ImportReworkAnalysis>();
            var step = 0;
            foreach (var item in data)
            {
                step += 1;
                dataList.Add(new ImportReworkAnalysis
                {
                   No=step,
                   xData=item.Item,
                   yData=item.Val.ToString()
                });
            }
            if (dataList.Any())
            {
                EpPlusExcelHelper<ImportReworkAnalysis> helper = null;
                try
                {
                    helper = new EpPlusExcelHelper<ImportReworkAnalysis>();
                    var temporaryFileName = $"报废率统计_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
                    helper.GenerateExcel(dataList, Path.Combine(rootDir, temporaryFileName));
                    return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
                }
                catch (Exception e)
                {
                    Logger.WriteLineError("Export reworkDataAnalysis failed, error:" + e);
                    throw new BadRequestException(RequestEnum.ExportFailed);
                }
                finally
                {
                    helper?.Dispose();
                }
            }

            throw new BadRequestException(CommonEnum.Fail);

        }


        /// <summary>
        /// 拼接Echart
        /// </summary>
        /// <param name="datas">统计类型：1 通道，2 工位，3 报废项目，4 报废类别，5 报废原因</param>
        /// <param name="chartType"></param>
        /// <param name="xType">统计维度 1 金额，2 报废率</param>
        /// <returns></returns>
        ResponseWasteAnalysisEchart GetEchartData(IEnumerable<ResponseWasteData> datas, int chartType, int xType)
        {
            var eChartData = new ResponseWasteAnalysisEchart();
            switch(chartType)
            {
                case 1: //通道
                    {
                        var chanelData = datas.GroupBy(f => f.SectionParent).OrderBy(g=>g.Key);

                        var listData = new List<ResponseWasteAnalysisEchartTable>();
                        foreach (var c in chanelData)
                        {
                            var xVal = c.FirstOrDefault().SectionParentDesc;
                            var lstData = c.ToList();
                            var yVal = GetTotalPrice(lstData);
                            if (xType==1) //金额
                            {
                                listData.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = yVal
                                });
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice==0?0: ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000)))/100;
                                listData.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = rate
                                });
                          
                            }
                            
                        }
                        var orderbyData = listData.OrderBy(o => o.Item);
                        foreach (var obj in orderbyData)
                        {
                            eChartData.X.Add(obj.Item);
                            eChartData.Y.Add(obj.Val);
                            eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                            {
                                Item = obj.Item,
                                Val = obj.Val
                            });
                        }
                        break;
                    }
                case 2://工位
                    {
                        var listData = new List<ResponseWasteAnalysisEchartTable>();
                        var sectionData = datas.GroupBy(f => f.Section);
                        foreach (var s in sectionData)
                        {
                            var xVal = s.FirstOrDefault().SectionDesc;
                            var lstData = s.ToList();
                            var yVal = GetTotalPrice(lstData);
                            if (xType == 1) //金额
                            {
                                listData.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = yVal
                                });

                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                listData.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = rate
                                });
                
                            }
                            
                            //eChartData.X.Add(xVal);
                           
                        }
                        var orderbyData = listData.OrderByDescending(o => o.Val);
                        foreach (var obj in orderbyData)
                        {
                            eChartData.X.Add(obj.Item);
                            eChartData.Y.Add(obj.Val);
                            eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                            {
                                Item = obj.Item,
                                Val = obj.Val
                            });
                        }
                        break;
                    }
                case 3://报废项目  //柏拉图
                    {
                        var itemData = datas.GroupBy(f => f.Item);
                        var listData = new List<ResponseWasteAnalysisEchartTable>();
                        foreach (var it in itemData)
                        {
                            var lstData = it.ToList();
                            var yVal = GetTotalPrice(lstData);
                            var item = new ResponseWasteAnalysisEchartTable();
                            item.Item = it.FirstOrDefault().ItemDesc;
                            if (xType == 1) //金额
                            {
                                item.Val = yVal;
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                item.Val = rate;
                            }
                            listData.Add(item);
                        }

                        var orderbyData = listData.OrderByDescending(o => o.Val);
                        var total = orderbyData.Sum(s => s.Val);
                        var stepVal = 0d;
                        foreach (var o in orderbyData)
                        {
                            stepVal += o.Val;
                            var percent = total == 0 ? 0 : Math.Round(stepVal / total, 4) * 100;
                            eChartData.X.Add(o.Item);
                            eChartData.Y.Add(o.Val);
                            eChartData.Z.Add(percent);
                            eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                            {
                                 Item=o.Item,
                                 Val=o.Val
                            });
                        }

                        break;
                    }
                case 4: //报废类别 //柏拉图
                    {
                        var itemData = datas.GroupBy(f => f.ReferType);
                        var listData = new List<ResponseWasteAnalysisEchartTable>();
                        foreach (var it in itemData)
                        {
                            var lstData = it.ToList();
                            var yVal = GetTotalPrice(lstData);
                            var item = new ResponseWasteAnalysisEchartTable();
                            item.Item = it.FirstOrDefault().ReferTypeDesc;
                            if (xType == 1) //金额
                            { 
                                item.Val = yVal;
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                item.Val = rate;
                            }
                            listData.Add(item);
                        }

                        var orderbyData = listData.OrderByDescending(o => o.Val);
                        var total = orderbyData.Sum(s => s.Val);
                        var stepVal = 0d;
                        foreach (var o in orderbyData)
                        {
                            stepVal += o.Val;
                            var percent = total == 0 ? 0 : Math.Round(stepVal / total, 4) * 100;
                            eChartData.X.Add(o.Item);
                            eChartData.Y.Add(o.Val);
                            eChartData.Z.Add(percent);
                            eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                            {
                                Item = o.Item,
                                Val = o.Val
                            });
                        }

                        break;
                    }
                case 5: //报废原因 //柏拉图
                    {
                        var itemData = datas.GroupBy(f => f.Refer);
                        var listData = new List<ResponseWasteAnalysisEchartTable>();
                        foreach (var it in itemData)
                        {
                            var lstData = it.ToList();
                            var yVal = GetTotalPrice(lstData);
                            var item = new ResponseWasteAnalysisEchartTable();
                            item.Item = it.FirstOrDefault().ReferTypeDesc;
                            if (xType == 1) //金额
                            {
                                item.Val = yVal;
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                item.Val = rate;
                            }
                            listData.Add(item);
                        }

                        var orderbyData = listData.OrderByDescending(o => o.Val);
                        var total = orderbyData.Sum(s => s.Val);
                        var stepVal = 0d;
                        foreach (var o in orderbyData)
                        {
                            stepVal += o.Val;
                            var percent = total==0?0: Math.Round(stepVal / total, 4) * 100;
                            eChartData.X.Add(o.Item);
                            eChartData.Y.Add(o.Val);
                            eChartData.Z.Add(percent);
                            eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                            {
                                 Item=o.Item,
                                 Val=o.Val
                            });
                        }
                        break;
                    }
                case 6: //年
                    {
                        var chanelData = datas.GroupBy(f => f.Year);
                        foreach (var c in chanelData)
                        {
                            var xVal = c.FirstOrDefault().Year.ToString();
                            var lstData = c.ToList();
                            var yVal = GetTotalPrice(lstData);
                            if (xType == 1) //金额
                            {
                                eChartData.Y.Add(yVal);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = yVal
                                });
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                eChartData.Y.Add(rate);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = rate
                                });
                            }
     
                            eChartData.X.Add(xVal);
                            
                        }
                        break;
                    }
                case 7: //月
                    {
                        var chanelData = datas.GroupBy(f => f.Month);
                        foreach (var c in chanelData)
                        {
                            var xVal = c.FirstOrDefault().Month.ToString();
                            var lstData = c.ToList();
                            var yVal = GetTotalPrice(lstData);
                            if (xType == 1) //金额
                            {
                                eChartData.Y.Add(yVal);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = yVal
                                });
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                eChartData.Y.Add(rate);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = rate
                                });
                            }
                           
                            eChartData.X.Add(xVal);
                           
                        }
                        break;
                    }
                case 8: //日
                    {
                        var chanelData = datas.GroupBy(f => f.Date);
                        foreach (var c in chanelData)
                        {
                            var xVal = c.First().Date;
                            var lstData = c.ToList();
                            var yVal = GetTotalPrice(lstData);
                            if (xType == 1) //金额
                            {
                                eChartData.Y.Add(yVal);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = yVal
                                });
                            }
                            else //报废率
                            {
                                var addPrice = GetAddPrice(lstData);
                                var rate = addPrice == 0 ? 0 : ((double)((int)(Math.Round(yVal / addPrice, 4) * 10000))) / 100;
                                eChartData.Y.Add(rate);
                                eChartData.tables.Add(new ResponseWasteAnalysisEchartTable
                                {
                                    Item = xVal,
                                    Val = rate
                                });
                            }
                           
                            eChartData.X.Add(xVal);
                           
                        }
                        break;
                    }
            }

            return eChartData;
        }

        /// <summary>
        /// 总金额 ：物料数量 * 物料单价
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        double GetTotalPrice(List<ResponseWasteData> data)
        {
            var value = 0d;
            foreach (var item in data)
                value += (item.Count * item.Price);
            return Math.Round(value,4);
        }

        /// <summary>
        /// 增值金额 入库数量 * 增值金额
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        double GetAddPrice(List<ResponseWasteData> data)
        {
            var value = 0d;
            var productData = data.GroupBy(g => g.Id).Select(f => f.FirstOrDefault()).ToList();
            foreach (var item in productData)
                value += (item.Warehorue * item.AddPrice);
            return Math.Round(value,4);
        }
    }
}
