using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCNC.Result;
using Siger.ApiCommon.Filters;
using Siger.ApiCommon.Result;
using Siger.ApiCommon.Utilities;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Request;
using Siger.Middlelayer.CncRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.AppSettings;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Dapper;
using Siger.Middlelayer.Dapper.Utilities;
using Siger.Middlelayer.Dapper.Utilities.Oee;
using Siger.Middlelayer.Dapper.Utilities.Slice;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.Share.Utilities;
using Siger.Middlelayer.Utility.ExcelImport;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Utility.ImportEntities;

namespace Siger.ApiCNC.Controllers
{
    public class ProductSumController : BaseController
    {
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly IProductionBeatSetRepository _productionBeatSetRepository;
        private readonly IProductionTimeRepository _timeRepository;
        private readonly IProductionBeatSetRepository _beatSetRepository;
        private readonly IProduceEfficiencyRepository _produceEfficiencyRepository;
        private readonly IProductPlanRepository _planRepository;
        private readonly IWorkingGroupRepository _groupRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly IDashboardCombPageConditionTwoRepository _combPageConditionRepository;
        private readonly IProductionTimeAllocationRepository _timeAllocationRepository;
        private readonly ISigerProjectRestTypeRepository _restTypeRepository;
        private readonly ISigerProjectShiftRepository _sigerProjectShiftRepository;
        public ProductSumController(ISigerProjectMachineRepository machineRepository, IProductionBeatSetRepository productionBeatSetRepository,
             IProductionBeatSetRepository beatSetRepository, IProduceEfficiencyRepository produceEfficiencyRepository,
            IProductPlanRepository planRepository, IWorkingGroupRepository groupRepository, ISigerProjectLevelSectionRepository levelSectionRepository,
            IDashboardCombPageConditionTwoRepository combPageConditionRepository, IProductionTimeAllocationRepository timeAllocationRepository,
            ISigerProjectRestTypeRepository restTypeRepository, ISigerProjectShiftRepository sigerProjectShiftRepository, IProductionTimeRepository timeRepository)
        {
            _machineRepository = machineRepository;
            _productionBeatSetRepository = productionBeatSetRepository;
            _timeRepository = timeRepository;
            _beatSetRepository = beatSetRepository;
            _produceEfficiencyRepository = produceEfficiencyRepository;
            _planRepository = planRepository;
            _groupRepository = groupRepository;
            _levelSectionRepository = levelSectionRepository;
            _combPageConditionRepository = combPageConditionRepository;
            _timeAllocationRepository = timeAllocationRepository;
            _restTypeRepository = restTypeRepository;
            _sigerProjectShiftRepository = sigerProjectShiftRepository;
        }

        //设备稼动统计
        [HttpPost]
        public async Task<IActionResult> EfficiencyAnalysisInfo([FromBody] RequestEfficiencyAnalysisInfo request)
        {
            IEnumerable<int> machinIds = null;
            if (request.sectionID != 0)
            {
                machinIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId);
            }
            var success = DateTime.TryParse(request.startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(request.endTime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var responses = new List<ResponseEfficiencyAnalysisInfo>();
            var repositoey = new SliceSateRepository(CompanyId, ProjectId);

            var sliceSates = await repositoey.GetCncSliceSatesAsync(machinIds, dtStart.ToString(ParameterConstant.DateTimeFormat),
                dtEnd.ToString(ParameterConstant.DateTimeFormat));
            if (sliceSates == null || !sliceSates.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var machineIds = sliceSates.Select(m => m.MachineID).Distinct().ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var repository = new ProductRepository(CompanyId, ProjectId);
            var sum = 0.0;
            var run = 0.0;
            foreach (var machineId in machineIds)
            {
                var machine = validMachines.FirstOrDefault(q => q.machine_id == machineId);
                var machineTitle = machine != null ? machine.lastSectionTitle : "";
                var response = new ResponseEfficiencyAnalysisInfo
                {
                    machineID = machineId,
                    title = machineTitle
                };

                double productivity = 0;
                double yield = 0;
                var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { machineId }, null, times);
                productivity = oee.OEE1;
                sum += oee.Sum;
                run += oee.Run;
                response.productivity = Math.Round(productivity, 2);

                //yield
                var query = await repository.GetYieldsAsync(request.startTime, request.endTime, new List<int> { machineId });
                var yiledSum = query.Sum(q => q.yield);
                if (yiledSum == 0)
                {
                    yield = 0;
                }
                else
                {
                    yield = oee.Run / yiledSum;
                }
                response.yield = Math.Round(yield, 2);
                responses.Add(response);
            }
            if (request.toexcel == 0)
            {
                return new ObjectResult(responses);
            }

            return ExportBarChart(responses);
        }

        //设备稼动统计
        [HttpGet]
        public async Task<IActionResult> EfficiencyAnalysisInfoTwo(string patial_code, string page_id, int projectid)
        {
            var sectionID = 0;
            var res = _combPageConditionRepository.Get(q => q.comb_page_id == page_id && q.page_patial_code == patial_code);
            sectionID = res.condition.ToInt();
            var startTime = DateTime.Now.ToString(ParameterConstant.DateFormat);
            var endTime = DateTime.Now.ToString(ParameterConstant.DateTimeFormat);
            IEnumerable<int> machinIds = null;
            if (sectionID != 0)
            {
                machinIds = _machineRepository.GetNCLevelSectionMachineIds(sectionID, projectid);
            }
            var success = DateTime.TryParse(startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(endTime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var responses = new List<ResponseEfficiencyAnalysisInfo>();
            var repositoey = new SliceSateRepository(CompanyId, projectid);

            var sliceSates = await repositoey.GetCncSliceSatesAsync(machinIds, dtStart.ToString(ParameterConstant.DateTimeFormat),
                dtEnd.ToString(ParameterConstant.DateTimeFormat));
            if (sliceSates == null || !sliceSates.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var machineIds = sliceSates.Select(m => m.MachineID).Distinct().ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(sectionID, projectid);
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, projectid);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var repository = new ProductRepository(CompanyId, projectid);
            var sum = 0.0;
            var run = 0.0;
            foreach (var machineId in machineIds)
            {
                var machine = validMachines.FirstOrDefault(q => q.machine_id == machineId);
                var machineTitle = machine != null ? machine.lastSectionTitle : "";
                var response = new ResponseEfficiencyAnalysisInfo
                {
                    machineID = machineId,
                    title = machineTitle
                };

                double productivity = 0;
                double yield = 0;
                var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { machineId }, null, times);
                productivity = oee.OEE1;
                sum += oee.Sum;
                run += oee.Run;
                response.productivity = Math.Round(productivity, 2);

                //yield
                var query = await repository.GetYieldsAsync(startTime, endTime, new List<int> { machineId });
                var yiledSum = query.Sum(q => q.yield);
                if (yiledSum == 0)
                {
                    yield = 0;
                }
                else
                {
                    yield = oee.Run / yiledSum;
                }
                response.yield = Math.Round(yield, 2);
                responses.Add(response);
            }
            foreach (var item in responses)
            {
                item.sum = Math.Round(run / sum * 100, 2);
            }
            var result1 = responses.OrderByDescending(a => a.productivity);
            return new ObjectResult(result1);
        }
        //设备稼动统计
        [HttpPost]
        public async Task<IActionResult> EfficiencyAnalysisInfoFive([FromBody] RequestEfficiencyAnalysisInfo request)
        {
            IEnumerable<int> machinIds = null;
            if (request.sectionID != 0)
            {
                machinIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId);
            }
            else
            {
                var lev = _levelSectionRepository.Get(q => q.status == (int)RowState.Valid && q.projectid == ProjectId && q.parentid == 0);
                if (lev != null)
                {
                    machinIds = _machineRepository.GetNCLevelSectionMachineIds(lev.id, ProjectId);
                }
            }
            var success = DateTime.TryParse(request.startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(request.endTime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }
            var repositoey = new SliceSateRepository(CompanyId, ProjectId);
            var sliceSates = await repositoey.GetCncSliceSatesAsync(machinIds, dtStart.ToString(ParameterConstant.DateTimeFormat),
                dtEnd.ToString(ParameterConstant.DateTimeFormat));
            if (sliceSates == null || !sliceSates.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var machineIds = sliceSates.Select(m => m.MachineID).Distinct().ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var repository = new ProductRepository(CompanyId, ProjectId);
            var sum = 0.0;
            var run = 0.0;
            foreach (var machineId in machineIds)
            {
                var machine = validMachines.FirstOrDefault(q => q.machine_id == machineId);
                var machineTitle = machine != null ? machine.lastSectionTitle : "";
                var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { machineId }, null, times);
                sum += oee.Sum;
                run += oee.Run;
            }
            var response = new ResponseEfficiencyAnalysisInfoThree
            {
                sectionid = request.sectionID,
                productivity = Math.Round(run / sum * 100, 2)
            };
            return new ObjectResult(response);
        }
        /// <summary>
        /// 设备稼动统计 长龄1.5 设备稼动率分布
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> EfficiencyAnalysisInfoThree([FromBody] RequestEfficiencyAnalysisInfo request)
        {
            var sectionList = new List<ResponseSectionList>();
            var sectionids = _levelSectionRepository.GetList(q => q.parentid == request.sectionID && q.status == (int)RowState.Valid && q.projectid == ProjectId).ToList();
            if (sectionids.Any())
            {
                foreach (var item in sectionids)
                {
                    var ids = new ResponseSectionList()
                    {
                        sectionID = item.id,
                        title = item.title
                    };
                    sectionList.Add(ids);
                }
            }
            else
            {
                var sections = _levelSectionRepository.Get(q => q.id == request.sectionID && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                var ids = new ResponseSectionList()
                {
                    sectionID = sections.id,
                    title = sections.title
                };
                sectionList.Add(ids);
            }
            var responses = new List<ResponseEfficiencyAnalysisInfoThree>();
            foreach (var item in sectionList)
            {
                var sum = 0.0;
                var run = 0.0;
                IEnumerable<int> machinIds = null;
                if (item.sectionID != 0)
                {
                    machinIds = _machineRepository.GetNCLevelSectionMachineIds(item.sectionID, ProjectId);
                }
                var success = DateTime.TryParse(request.startTime, out var dtStart);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                success = DateTime.TryParse(request.endTime, out var dtEnd);
                if (!success)
                {
                    throw new ServerException(500146);
                }
                var repositoey = new SliceSateRepository(CompanyId, ProjectId);
                var sliceSates = await repositoey.GetCncSliceSatesAsync(machinIds, dtStart.ToString(ParameterConstant.DateTimeFormat),
                    dtEnd.ToString(ParameterConstant.DateTimeFormat));
                if (sliceSates == null || !sliceSates.Any())
                {
                    var rep = new ResponseEfficiencyAnalysisInfoThree
                    {
                        sectionid = item.sectionID,
                        title = item.title,
                        productivity = 0
                    };
                    responses.Add(rep);
                    continue;
                }
                var machineIds = sliceSates.Select(m => m.MachineID).Distinct().ToList();
                var validMachines = _machineRepository.GetNCLevelSectionNames(item.sectionID, ProjectId);
                var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
                var repository = new ProductRepository(CompanyId, ProjectId);
                foreach (var machineId in machineIds)
                {
                    var machine = validMachines.FirstOrDefault(q => q.machine_id == machineId);
                    var machineTitle = machine != null ? machine.lastSectionTitle : "";
                    var oee = OeeManager.GetOeeByTime(dtStart, dtEnd, sliceSates, new List<int> { machineId }, null, times);
                    sum += oee.Sum;
                    run += oee.Run;
                }
                var response = new ResponseEfficiencyAnalysisInfoThree
                {
                    sectionid = item.sectionID,
                    title = item.title,
                    productivity = Math.Round(run / sum * 100, 2)
                };
                responses.Add(response);
            }
            return new ObjectResult(responses);
        }

        /// <summary>
        /// 设备稼动统计 长龄1.5 设备稼动率分析
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> EfficiencyAnalysisInfoFour([FromBody] RequestEfficiencyAnalysisInfoFour request)
        {
            if (request.toexcel != 0)
            {
                request.pagesize = 999999999;
            }
            IEnumerable<int> machinIds = null;
            if (request.sectionID != 0)
            {
                machinIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId);
            }
            
            var success = DateTime.TryParse(request.startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            var stateTime = request.startTime.ToDateTime().AddDays(1 - request.startTime.ToDateTime().Day).Date;
            var endTime = request.startTime.ToDateTime().AddDays(1 - request.startTime.ToDateTime().Day).Date.AddMonths(1).AddSeconds(-1);
            var res = new List<RequestEff>();
            var repositoey = new SliceSateRepository(CompanyId, ProjectId);
            var responses = new List<ResponseEfficiencyAnalysisInfoFour>();
            var sliceSates = await repositoey.GetCncSliceSatesAsync(machinIds, stateTime.ToString(ParameterConstant.DateTimeFormat),
            endTime.ToString(ParameterConstant.DateTimeFormat));
            var machineIds = sliceSates.Select(m => m.MachineID).Distinct().ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var repository = new ProductRepository(CompanyId, ProjectId);
            var state = stateTime;
            foreach (var machineId in machineIds)
            {
                var ret = new RequestEff();
                var end = state.AddDays(1).AddSeconds(-1);
               
                var sections = _machineRepository.GetSectionByMachine(machineId, ProjectId);
                var req = new List<ResponseEfficiencyAnalysisInfoFour>();
                while (end <= endTime)
                {
                    var sliceSate = _machineRepository.GetsliceSates(sliceSates, machineId, ProjectId, state.ToString(ParameterConstant.DateTimeFormat).ToDateTime(),
           end.ToString(ParameterConstant.DateTimeFormat).ToDateTime());
                    var machine = validMachines.FirstOrDefault(q => q.machine_id == machineId);
                    var machineTitle = machine != null ? machine.lastSectionTitle : "";
                    var response = new ResponseEfficiencyAnalysisInfoFour
                    {
                        machineID = machineId,
                        sectionID = sections,
                        title = machineTitle
                    };
                    ret.title = machineTitle;
                    double productivity = 0;
                    var oee = OeeManager.GetOeeByTime(state, end, sliceSate, new List<int> { machineId }, null, times);
                    productivity = oee.OEE1;
                    response.productivity = Math.Round(productivity, 2);
                    responses.Add(response);

                    state = end.AddSeconds(1);
                    end = state.AddDays(1).AddSeconds(-1);
                    req.Add(response);
                }
                state = stateTime;
                ret.eff =req;
                res.Add(ret);
            }
            var totalCount = res.Count();
            var entities = res.Skip((request.page - 1) * request.pagesize).Take(request.pagesize).ToList();
            if (request.toexcel == 0)
            {
                return new PagedObjectResult(entities, totalCount, request.page, request.pagesize);
            }
            var machines = _machineRepository.GetProjectLanguage(ProjectId);
            return ExportEfficiencyAnalysisInfoFour(entities, machines);
        }

        [HttpPost]
        public IActionResult ExportBarChart(List<ResponseEfficiencyAnalysisInfo> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"Efficiency_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<EfficiencyAnalysisList>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<EfficiencyAnalysisList>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new EfficiencyAnalysisList
                    {
                        Title = yield.title,
                        Productivity = yield.productivity
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

                helper.GenerateExcel(machineYields, fileName, false, EchartCategory.EfficiencyAnalysis);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export MachineState failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

        //产量产出统计
        [HttpPost]
        public IActionResult ListMachineYieldBySign([FromBody] RequestListMachineYieldBySign request)
        {
            var machineIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId).ToList();
            var success = DateTime.TryParse(request.startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(request.endTime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }
            var repository = new ProductRepository(CompanyId, ProjectId);
            var query = repository.GetYileds(request.startTime, request.endTime, machineIds);
            if (!query.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var yields = from m in query
                         group m by new
                         {
                             m.machineID,
                             m.programCode
                         }
                into temp
                         select new ResponseGetListMachineYieldBySign
                         {
                             machine_id = temp.Key.machineID,
                             program_code = temp.Key.programCode,
                             yield = temp.Sum(m => m.yield)
                         };

            var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC);
            var stations = _machineRepository.GetNCMachinSectionInfos(machineIds, ProjectId).ToList();
            var beats = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == ProjectId && q.status == (int)RowState.Valid
                                                        && q.start_time <= dtEnd && q.end_time >= dtEnd).ToList();

            var responses = new ListMachineYieldBySignResult();
            var list = new List<ResponseGetListMachineYieldBySign>();
            foreach (var machineYield in yields.ToList())
            {
                var beat = beats.FirstOrDefault(q => q.machineID == machineYield.machine_id && q.process_number == machineYield.program_code);
                var actYield = beat == null ? machineYield.yield : machineYield.yield * beat.yieldrate;

                var machine = machines.FirstOrDefault(q => q.id == machineYield.machine_id);
                var station = stations.FirstOrDefault(q => q.machineId == machineYield.machine_id);
                var response = new ResponseGetListMachineYieldBySign
                {
                    machine_id = machineYield.machine_id,
                    machine_name = machine != null ? machine.title : "",
                    program_code = machineYield.program_code,
                    title = station != null ? station.section_name + "-" + machine?.title : "",
                    yield = actYield
                };
                list.Add(response);
            }
            responses.data = list.OrderBy(m => m.machine_id).ToList();

            foreach (var machineId in responses.data.Select(m => m.machine_id).OrderBy(m => m).Distinct())
            {
                responses.xdata.Add(responses.data.First(m => m.machine_id == machineId).machine_name);
                responses.ydata.Add(yields.Where(m => m.machine_id == machineId).Sum(m => m.yield));
            }

            if (request.toexcel == 0)
            {
                return responses;
            }
            //导出
            return ExportYield(responses.data.ToList());
        }

        //产量产出统计
        [HttpPost]
        public async Task<IActionResult> ListMachineYieldBySignDetail([FromBody] RequestListMachineYields request)
        {
            // var machineIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId).ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            var machineIds = validMachines.Select(s => s.machine_id).ToList();
            var success = DateTime.TryParse(request.startTime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(request.endTime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var end = dtEnd > DateTime.Now ? UnixTimeHelper.GetNow() : (int)UnixTimeHelper.ConvertDataTimeLong(dtEnd);

            var repository = new ProductRepository(CompanyId, ProjectId);
            var query = repository.GetYileds(request.startTime, request.endTime, machineIds);
            if (!query.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }

            var responses = new ListMachineYieldsResult();
            var list = new List<ResponseGetListMachineYield>();
            var programNos = new List<ProgramYield>();

           // var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC).OrderBy(q => q.sorting).ToList();

            foreach (var machine in validMachines)
            {
                var machineYileds = query.Where(q => q.machineID == machine.machine_id);
                if (machineYileds.Any())
                {
                    var yields = await YieldMangaer.GetProgramNos(machineYileds, request.startTime, machine.machine_id, end);
                    programNos.AddRange(yields);
                }
            }
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var beates = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == ProjectId && q.status == (int)RowState.Valid).ToList();
            var beatInfoes = Mapper<siger_project_beat_set, BeatSetInfo>.MapList(beates);
            var routes = YieldMangaer.GetProductRoutesOEE(programNos, beatInfoes, times, CompanyId, ProjectId);
            //var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            foreach (var machineYield in routes)
            {
                var machine = validMachines.FirstOrDefault(q => q.machine_id == machineYield.machine_id);
                var route = routes.FirstOrDefault(q => q.machine_id == machineYield.machine_id && q.program_code == machineYield.program_code);
                var response = new ResponseGetListMachineYield
                {
                    machine_id = machineYield.machine_id,
                    machine_name = machine != null ? machine.machine_name : "",
                    program_code = machineYield.program_code,
                    title = machine != null ? machine.lastSecondSectionTitle + "-" + machine.lastSectionTitle : "",
                    yield = machineYield.yield,
                    product_name = route != null ? route.product_name : "",
                    route_name = route != null ? route.route_name : "",
                    efficiency = route != null ? route.efficiency : 100,
                    oee = route != null ? route.oee : 0,
                    totaltime = route.totaltime,
                    averagetime = route.averagetime
                };
                list.Add(response);
            }

            responses.data = list.ToList();

            //type 横坐标 1产线区域 2产品名称
            //typeValue
            var type = request.type.ToInt();
            if (type == 1)
            {
                var typeValue = request.typeValue.ToInt();
                if (typeValue == 0) //最后一级产线
                {
                    var levelmachine = _machineRepository.GetNCLevelSectionMachines(request.sectionID, ProjectId).FirstOrDefault();
                    if (levelmachine == null)
                    {
                        responses.xdata.Add(request.sectionID.ToStr());
                        responses.ydata.Add(0);
                    }
                    else
                    {
                        responses.xdata.Add(levelmachine.machine_name);
                        responses.ydata.Add(responses.data.Where(m => m.machine_id == levelmachine.machine_id).Sum(m => m.yield));
                    }
                }
                else
                {
                    var sections = _machineRepository.GetNCLevelSections(request.sectionID, ProjectId);
                    var levels = sections.Where(q => q.levelid == typeValue);
                    foreach (var levelSection in levels)
                    {
                        var sectionMachineIds = _machineRepository.GetNCMachinIdsBySectionId(levelSection.id, 0, ProjectId);

                        responses.xdata.Add(levelSection.title);
                        responses.ydata.Add(responses.data.Where(m => sectionMachineIds.Contains(m.machine_id)).Sum(m => m.yield));
                    }
                }
            }
            else if (type == 2)
            {
                foreach (var name in responses.data.Select(m => m.product_name).OrderBy(m => m).Distinct())
                {
                    responses.xdata.Add(responses.data.First(m => m.product_name == name).product_name);
                    responses.ydata.Add(responses.data.Where(m => m.product_name == name).Sum(m => m.yield));
                }
            }

            if (request.toexcel == 0)
            {
                return responses;
            }
            //导出
            return ExportYields(responses.data.ToList());
        }

        //综合OEE
        [HttpPost]
        public async Task<IActionResult> GetOee([FromBody] RequestGetOee request)
        {
            var machineIds = request.machineidarr;
            if (machineIds == null || !machineIds.Any())
            {
                throw new ServerException(100236); //没有获取设备
            }
            if (!DateTime.TryParse(request.starttime, out var dtStart))
            {
                dtStart = DateTime.Now.AddDays(-7);
            }

            if (!DateTime.TryParse(request.endtime, out var dtEnd))
            {
                dtEnd = DateTime.Now.AddDays(1);
            }
            dtEnd = dtEnd.AddDays(1).AddSeconds(-1);
            dtEnd = dtEnd > DateTime.Now ? DateTime.Now : dtEnd;
            if (dtStart > dtEnd)
            {
                throw new ServerException(100158);
            }

            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var result = new GetOeeResult();
            //xID - 0, 1, 2, 
            //x_type - time, machine
            //level_id 
            //OEE1 = 运行时间/24-休息时间
            //OEE2 = 总产量/理论产量  理论产量=运行时间/节拍数
            //OEE3 = 合格数/总数
            var xid = request.x_id.ToInt();
            var type = request.x_type;
            var sectionId = request.sectionID.ToInt();
            var repositoey = new SliceSateRepository(CompanyId, ProjectId);
            if (type == "time")
            {
                var interal = DateTimeHelper.GetInteral(xid);
                var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, xid);
                result.type = type;

                for (var i = 0; i < dates.Count; i++)
                {
                    DateTime start;
                    DateTime end;
                    if (xid == 0 || xid == 1)
                    {
                        start = dates[i];
                        end = dates[i].AddDays(interal).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(interal).AddSeconds(-1);
                        result.x.Add(start.ToString(ParameterConstant.DateFormat));
                    }
                    else
                    {
                        start = dates[i].AddDays(1 - dates[i].Day);
                        end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                        result.x.Add(start.ToString("yyyy-MM"));
                    }
                    var sliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, start.ToString(ParameterConstant.DateTimeFormat), end.ToString(ParameterConstant.DateTimeFormat));
                    double oeeTotal = 0;
                    var oeeEntity = new OeeDetailEntity();
                    foreach (var machineId in machineIds)
                    {
                        var machineSlice = sliceSates.Where(q => q.MachineID == machineId);
                        if (machineSlice.Any())
                        {
                            var unixStart = UnixTimeHelper.ConvertDataTimeLong(start);
                            var unixEnd = UnixTimeHelper.ConvertDataTimeLong(end);
                            var reports = _productionBeatSetRepository.GetProductReport(unixStart, unixEnd, new List<int> { machineId }, ProjectId);
                            oeeEntity = OeeManager.GetOeeByTime(start, end, machineSlice, new List<int> { machineId }, reports, times);
                            oeeTotal += oeeEntity.OEE;
                        }
                    }
                    if (machineIds.Count() == 1)
                    {
                        result.y.Add(i, new OeeDetailEntity(oeeEntity.OEE1, oeeEntity.OEE2, oeeEntity.OEE3));
                    }
                    else
                    {
                        result.y.Add(i, new OeeEntity { OEE = Math.Round(oeeTotal / machineIds.Count(), 2) });
                    }
                }
            }
            else if (type == "machine")
            {
                try
                {
                    var sections = _machineRepository.GetNCLevelSections(sectionId, ProjectId);
                    var levels = sections.Where(q => q.levelid == xid).ToList();
                    result.type = type;
                    if (levels.Any())
                    {
                        var i = 0;
                        foreach (var levelSection in levels)
                        {
                            var machines = _machineRepository.GetNCLevelSectionMachineIds(levelSection.id, ProjectId);
                            if (!machines.Any())
                            {
                                continue;
                            }
                            result.x.Add(levelSection.title);

                            var sliceSates = await repositoey.GetCncSliceSatesAsync(machines, dtStart.ToString(ParameterConstant.DateTimeFormat),
                                dtEnd.ToString(ParameterConstant.DateTimeFormat));
                            double oeeTotal = 0;
                            var oeeEntity = new OeeDetailEntity();
                            foreach (var machineId in machines)
                            {
                                var machineSlice = sliceSates.Where(q => q.MachineID == machineId);
                                if (machineSlice.Any())
                                {
                                    var unixStart = UnixTimeHelper.ConvertDataTimeLong(dtStart);
                                    var unixEnd = UnixTimeHelper.ConvertDataTimeLong(dtEnd);
                                    var reports = _productionBeatSetRepository.GetProductReport(unixStart, unixEnd, new List<int> { machineId }, ProjectId);
                                    oeeEntity = OeeManager.GetOeeByTime(dtStart, dtEnd, machineSlice, new List<int> { machineId }, reports, times);
                                    oeeTotal += oeeEntity.OEE;
                                }
                            }
                            if (machines.Count() == 1)
                            {
                                result.y.Add(i, new OeeDetailEntity(oeeEntity.OEE1, oeeEntity.OEE2, oeeEntity.OEE3));
                            }
                            else
                            {
                                result.y.Add(i, new OeeEntity { OEE = Math.Round(oeeTotal / machines.Count(), 2) });
                            }
                            i++;
                        }
                    }
                }
                catch
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
            }

            if (request.toexcel == 0)
            {
                return new ObjectResult(result);
            }

            return ExportOee(result);
        }

        /// <summary>
        /// 长江润发--按照自然周计算
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        //综合OEE
        [HttpPost]
        public async Task<IActionResult> GetOeeCJ([FromBody] RequestGetOee request)
        {
            var machineIds = request.machineidarr;
            if (machineIds == null || !machineIds.Any())
            {
                throw new ServerException(100236); //没有获取设备
            }
            if (!DateTime.TryParse(request.starttime, out var dtStart))
            {
                dtStart = DateTime.Now.AddDays(-7);
            }

            if (!DateTime.TryParse(request.endtime, out var dtEnd))
            {
                dtEnd = DateTime.Now.AddDays(1);
            }
            dtEnd = dtEnd.AddDays(1).AddSeconds(-1);
            dtEnd = dtEnd > DateTime.Now ? DateTime.Now : dtEnd;
            if (dtStart > dtEnd)
            {
                throw new ServerException(100158);
            }

            //var times = _timeRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var result = new GetOeeResult();
            //xID - 0, 1, 2, 
            //x_type - time, machine
            //level_id 
            //OEE1 = 运行时间/24-休息时间
            //OEE2 = 总产量/理论产量  理论产量=运行时间/节拍数
            //OEE3 = 合格数/总数
            var xid = request.x_id.ToInt();
            var type = request.x_type;
            var sectionId = request.sectionID.ToInt();
            var repositoey = new SliceSateRepository(CompanyId, ProjectId);
            if (type == "time")
            {
                var interal = DateTimeHelper.GetInteral(xid);
                var dates = DateTimeHelper.GetDateTimesCJ(dtStart, dtEnd, xid);
                var xData = DateTimeHelper.GetStrDateTimesCJ(dtStart, dtEnd, xid);
                result.type = type;
                if (dates.Count() > 7)
                {
                    dates.RemoveAt(0);
                    xData.RemoveAt(0);
                }

                for (var i = 0; i < dates.Count; i++)
                {
                    DateTime start;
                    DateTime end;
                    if (xid == 0)
                    {
                        start = dates[i];
                        end = dates[i].AddDays(interal).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(interal).AddSeconds(-1);
                        result.x.Add(start.ToString(ParameterConstant.DateFormat));
                    }
                    else if (xid == 1)
                    {
                        var weekStart = DateTimeHelper.GetWeekRangeStart(xData[i]);
                        var weekEnd = DateTimeHelper.GetWeekRangeEnd(xData[i]);
                        start = dtStart > weekStart ? dtStart : weekStart;
                        end = dtEnd < weekEnd ? dtEnd : weekEnd.AddDays(1).AddSeconds(-1);
                        result.x.Add(xData[i]);
                    }
                    else
                    {
                        start = dates[i].AddDays(1 - dates[i].Day);
                        end = dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1) > DateTime.Now
                            ? DateTime.Now
                            : dates[i].AddDays(1 - dates[i].Day).Date.AddMonths(1).AddSeconds(-1); //到月底
                        result.x.Add(start.ToString("yyyy-MM"));
                    }
                    var sliceSates = await repositoey.GetCncSliceSatesAsync(machineIds, start.ToString(ParameterConstant.DateTimeFormat), end.ToString(ParameterConstant.DateTimeFormat));
                    double oeeTotal = 0;
                    var oeeEntity = new OeeDetailEntity();
                    foreach (var machineId in machineIds)
                    {
                        var machineSlice = sliceSates.Where(q => q.MachineID == machineId);
                        if (machineSlice.Any())
                        {
                            var unixStart = UnixTimeHelper.ConvertDataTimeLong(start);
                            var unixEnd = UnixTimeHelper.ConvertDataTimeLong(end);
                            var reports = _productionBeatSetRepository.GetProductReport(unixStart, unixEnd, new List<int> { machineId }, ProjectId);
                            oeeEntity = OeeManager.GetOeeByTime(start, end, machineSlice, new List<int> { machineId }, reports, times);
                            oeeTotal += oeeEntity.OEE;
                        }
                    }
                    if (machineIds.Count() == 1)
                    {
                        result.y.Add(i, new OeeDetailEntity(oeeEntity.OEE1, oeeEntity.OEE2, oeeEntity.OEE3));
                    }
                    else
                    {
                        result.y.Add(i, new OeeEntity { OEE = Math.Round(oeeTotal / machineIds.Count(), 2) });
                    }
                }
            }
            else if (type == "machine")
            {
                try
                {
                    var sections = _machineRepository.GetNCLevelSections(sectionId, ProjectId);
                    var levels = sections.Where(q => q.levelid == xid).ToList();
                    result.type = type;
                    if (levels.Any())
                    {
                        var i = 0;
                        foreach (var levelSection in levels)
                        {
                            var machines = _machineRepository.GetNCLevelSectionMachineIds(levelSection.id, ProjectId);
                            if (!machines.Any())
                            {
                                continue;
                            }

                            if (xid == 699)
                            {
                                var newMachine = _levelSectionRepository.Get(q => q.id == levelSection.parentid && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                                if (newMachine != null)
                                {
                                    result.x.Add(newMachine.title + "-" + levelSection.title);
                                }
                                else
                                {
                                    result.x.Add(levelSection.title);
                                }
                            }
                            else
                            {
                                result.x.Add(levelSection.title);
                            }



                            var sliceSates = await repositoey.GetCncSliceSatesAsync(machines, dtStart.ToString(ParameterConstant.DateTimeFormat),
                                dtEnd.ToString(ParameterConstant.DateTimeFormat));
                            double oeeTotal = 0;
                            var oeeEntity = new OeeDetailEntity();
                            foreach (var machineId in machines)
                            {
                                var machineSlice = sliceSates.Where(q => q.MachineID == machineId);
                                if (machineSlice.Any())
                                {
                                    var unixStart = UnixTimeHelper.ConvertDataTimeLong(dtStart);
                                    var unixEnd = UnixTimeHelper.ConvertDataTimeLong(dtEnd);
                                    var reports = _productionBeatSetRepository.GetProductReport(unixStart, unixEnd, new List<int> { machineId }, ProjectId);
                                    oeeEntity = OeeManager.GetOeeByTime(dtStart, dtEnd, machineSlice, new List<int> { machineId }, reports, times);
                                    oeeTotal += oeeEntity.OEE;
                                }
                            }
                            if (machines.Count() == 1)
                            {
                                result.y.Add(i, new OeeDetailEntity(oeeEntity.OEE1, oeeEntity.OEE2, oeeEntity.OEE3));
                            }
                            else
                            {
                                result.y.Add(i, new OeeEntity { OEE = Math.Round(oeeTotal / machines.Count(), 2) });
                            }
                            i++;
                        }
                    }
                }
                catch
                {
                    throw new BadRequestException(CommonEnum.RecordNotFound);
                }
            }

            if (request.toexcel == 0)
            {
                return new ObjectResult(result);
            }

            return ExportOee(result);
        }

        [HttpPost]
        private IActionResult ExportOee(GetOeeResult responses)
        {
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"oee_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<OeeDetailImportEntity>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<OeeDetailImportEntity>();
                var index = 1;
                EchartCategory category = EchartCategory.None;
                foreach (var yield in responses.y)
                {
                    if (yield.Value is OeeEntity oee)
                    {
                        var machineYield = new OeeDetailImportEntity
                        {
                            No = index,
                            Abscissa = responses.x[index - 1],
                            OEE = oee.OEE
                        };
                        machineYields.Add(machineYield);
                        index++;
                        category = EchartCategory.Oee;
                    }

                    if (yield.Value is OeeDetailEntity oeeDetail)
                    {
                        var machineYield = new OeeDetailImportEntity
                        {
                            No = index,
                            Abscissa = responses.x[index - 1],
                            OEE = oeeDetail.OEE,
                            OEE1 = oeeDetail.OEE1,
                            OEE2 = oeeDetail.OEE2,
                            OEE3 = oeeDetail.OEE3,
                        };
                        machineYields.Add(machineYield);
                        index++;
                        category = EchartCategory.OeeDetail;
                    }
                }

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

        [HttpPost]
        private IActionResult ExportYield(List<ResponseGetListMachineYieldBySign> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"machineyield_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<MachineYieldImport>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<MachineYieldImport>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new MachineYieldImport
                    {
                        Section = yield.title,
                        Yield = yield.yield.ToString(),
                        //MachineName = yield.machine_name,
                        ProgramNo = yield.program_code,
                        No = index
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

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

        [HttpPost]
        private IActionResult ExportYields(List<ResponseGetListMachineYield> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"machineyields_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<MachineYields>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<MachineYields>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new MachineYields
                    {
                        Section = yield.title,
                        Yield = yield.yield.ToString(),
                        ProgramNo = yield.program_code,
                        ProductName = yield.product_name,
                        RouteName = yield.route_name,
                        //Efficiency = yield.efficiency.ToStr(),
                        //OEE = yield.oee.ToStr(),
                        No = index
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

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

        [HttpPost]
        public IActionResult GetListProductionEfficiencyAnalysis([FromBody] RequestGetProductionEfficiencyanalysis request)
        {
            var result = new ProductionEfficiencyanalysisResult();

            var machineIds = new List<int>();
            var sectionIds = string.IsNullOrWhiteSpace(request.sectionIdStr) ? new List<int>() : request.sectionIdStr.Split(',', StringSplitOptions.RemoveEmptyEntries).Select(t => t.ToInt()).ToList();
            if (!string.IsNullOrWhiteSpace(request.section_id) && string.IsNullOrWhiteSpace(request.sectionIdStr))
            {
                var sectionList = new List<siger_project_level_section>();
                var sectionlists = _levelSectionRepository.GetList(t => t.parentid == request.section_id.ToInt()).ToList();
                if (sectionlists.Count > 0)
                {
                    foreach (var item in sectionlists)
                    {
                        var IsNull = true;
                        var section = _levelSectionRepository.GetList(t => t.parentid == item.id).ToList();
                        if (section.Count > 0)
                        {
                            IsNull = false;
                            foreach (var items in section)
                            {
                                sectionIds.Add(items.id);
                            }

                        }
                        if (IsNull)
                        {
                            sectionList.Add(item);
                        }
                    }
                    foreach (var seclist in sectionList)
                    {
                        sectionIds.Add(seclist.id);
                    }
                }
                else
                {
                    sectionIds.Add(request.section_id.ToInt());
                }

            }
            machineIds = sectionIds.Any() ? _machineRepository.GetNCMachineIdsBySectionIds(sectionIds, ProjectId).ToList() : _machineRepository.GetNCLevelSectionMachineIds(request.section_id.ToInt(), ProjectId).ToList();
            var success = DateTime.TryParse(request.starttime, out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }
            success = DateTime.TryParse(request.endtime, out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var list = new List<ResponseGetListEfficiencyAnalysis>();

            var summary = new EfficiencySummary();

            if (dtEnd.Subtract(dtStart).TotalHours > 24)
            {
                throw new ServerException(500231);
            }

            if (dtStart >= DateTime.Today && dtEnd >= DateTime.Today)
            {
                var end = dtEnd > DateTime.Now ? UnixTimeHelper.GetNow() : (int)UnixTimeHelper.ConvertDataTimeLong(dtEnd);

                var repository = new ProductRepository(CompanyId, ProjectId);
                var yields = repository.GetYileds(request.starttime, UnixTimeHelper.ConvertIntDateTime(end), machineIds).ToList();

                var sliceRep = new SliceSateRepository(CompanyId, ProjectId);
                var slices = sliceRep.GetCncSliceSates(machineIds, request.starttime, UnixTimeHelper.ConvertIntDateTime(end));

                var stations = _machineRepository.GetNCLevelSectionNames(machineIds, ProjectId).ToList();
                var beats = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == ProjectId && q.status == (int)RowState.Valid
                                                            && q.start_time <= dtEnd && q.end_time >= dtEnd).ToList();
                var times = GetRestTimesBySections(machineIds);
                double totalEfficiency = 0;
                double totalDebug = 0;
                double totalFault = 0;
                double totalShutdown = 0;
                var count = 0;

                var machineProgramNos = YieldMangaer.GetMachineProgramNos(yields, request.starttime, machineIds, end);
                if (machineProgramNos.Any())
                {
                    foreach (var machineProgramNo in machineProgramNos)
                    {
                        var station = stations.FirstOrDefault(q => q.machine_id == machineProgramNo.machineId);

                        double runTimes = 0;
                        var rests = RestTimeManager.GetRunTimeByPrograms(times, machineProgramNo, dtStart, DateTime.Now, ref runTimes);

                        count++;
                        var machineYield = yields.Count(q => q.machineID == machineProgramNo.machineId && q.programCode == machineProgramNo.programNo);
                        var response = new ResponseGetListEfficiencyAnalysis
                        {
                            location = station != null ? station.lastSecondSectionTitle + "-" + station.lastSectionTitle : "",
                            actual_output = machineYield,
                            idle_loss = "0%(0.00h)",
                            debug_loss = "0%(0.00h)",
                            fault_loss = "0%(0.00h)",
                            shutdown_loss = "0%(0.00h)",
                            total_efficiency = machineYield > 0 ? "100%(0.00h)" : "0%(0.00h)",
                            program_no = machineProgramNo.programNo
                        };
                        var beat = beats.FirstOrDefault(q => q.machineID == machineProgramNo.machineId && q.process_number == machineProgramNo.programNo);
                        if (beat == null)
                        {
                            response.product_name = "NA";
                            response.route_name = "NA";
                            response.theory_yield = "NA";
                            response.total_efficiency = "NA";
                            response.idle_loss = "NA";
                        }
                        else if (runTimes != 0)
                        {
                            response.actual_output = response.actual_output * beat.yieldrate;
                            response.product_name = beat.product_name_text;
                            response.route_name = beat.route_name;

                            var machineSlice = slices.Where(q => q.MachineID == machineProgramNo.machineId);
                            //0 关机 1 运行 2 调试 3 空闲 4 故障
                            var shutdown = SliceManager.GetResetTimesBySlice(0, machineProgramNo.TimeRanges, machineSlice, rests);
                            var debug = SliceManager.GetResetTimesBySlice(2, machineProgramNo.TimeRanges, machineSlice, rests);
                            var fault = SliceManager.GetResetTimesBySlice(4, machineProgramNo.TimeRanges, machineSlice, rests);
                            var run = SliceManager.GetResetTimesBySlice(1, machineProgramNo.TimeRanges, machineSlice, null);

                            runTimes = runTimes < 0 ? run : runTimes;

                            totalDebug += debug / runTimes;
                            totalFault += fault / runTimes;
                            totalShutdown += shutdown / runTimes;

                            response.debug_loss_value = Math.Round(debug / runTimes * 100, 2);
                            response.debug_loss = response.debug_loss_value.ToStr() + "%(" + Math.Round(debug / 3600, 2) + "h)";

                            response.fault_loss_value = Math.Round(fault / runTimes * 100, 2);
                            response.fault_loss = response.fault_loss_value.ToStr() + "%(" + Math.Round(fault / 3600, 2) + "h)";

                            response.shutdown_loss_value = Math.Round(shutdown / runTimes * 100, 2);
                            response.shutdown_loss = response.shutdown_loss_value.ToStr() + "%(" + Math.Round(shutdown / 3600, 2) + "h)";

                            var beatInfo = beat.standard_besat + beat.updown_besat;
                            response.theory_yield = beatInfo <= 0 ? "0" : (Math.Round(runTimes / beatInfo, 0) * beat.yieldrate).ToStr();

                            var idle = runTimes - shutdown - debug - fault - beatInfo * machineYield;
                            var userIdle = idle < 0 ? 0 : idle;

                            response.idle_loss_value = Math.Round(userIdle / runTimes * 100, 2);
                            response.idle_loss = response.idle_loss_value.ToStr() + "%(" + Math.Round(userIdle / 3600, 2) + "h)";

                            totalEfficiency += beatInfo * machineYield / runTimes;
                            response.total_efficiency_value = Math.Round(beatInfo * machineYield / runTimes * 100, 2);
                            response.total_efficiency = response.total_efficiency_value.ToStr()
                                                        + "%(" + Math.Round(beatInfo * machineYield / 3600, 2) + "h)";
                        }
                        list.Add(response);
                    }
                    //summary
                    summary = new EfficiencySummary
                    {
                        total_eff = (totalEfficiency / count * 100).FormatDouble(),
                        debug_loss = (totalDebug / count * 100).FormatDouble(),
                        fault_loss = (totalFault / count * 100).FormatDouble(),
                        shutdown_loss = (totalShutdown / count * 100).FormatDouble(),
                    };
                    summary.idle_loss = (100 - (summary.total_eff + summary.debug_loss + summary.fault_loss + summary.shutdown_loss))
                        .FormatDouble();
                }

            }
            else
            {
                var res = _produceEfficiencyRepository.GetList(t =>
                    t.project_id == ProjectId && t.date <= dtEnd && t.date >= dtStart &&
                    t.status == (int)RowState.Valid && machineIds.Contains(t.machine_id)).ToList();
                double totalEfficiency = 0;
                double totalDebug = 0;
                double totalFault = 0;
                double totalShutdown = 0;
                var count = 0;
                foreach (var produce in res)
                {
                    produce.idle_loss = produce.idle_loss < 0 ? 0 : produce.idle_loss;
                    var model = new ResponseGetListEfficiencyAnalysis
                    {
                        location = produce.machine_location,
                        product_name = produce.product_name,
                        program_no = produce.program_no,
                        route_name = produce.route_name,
                        theory_yield = produce.theory_yield,
                        actual_output = produce.actual_yield,
                        total_efficiency_value = Math.Round(produce.total_efficiency / produce.run_times * 100, 2),
                        idle_loss_value = produce.run_times > 0 ? Math.Round(produce.idle_loss / produce.run_times * 100, 2) : 0,
                        debug_loss_value = produce.run_times > 0 ? Math.Round(produce.debug_loss / produce.run_times * 100, 2) : 0,
                        fault_loss_value = produce.run_times > 0 ? Math.Round(produce.fault_loss / produce.run_times * 100, 2) : 0,
                        shutdown_loss_value = produce.run_times > 0 ? Math.Round(produce.shutdown_loss / produce.run_times * 100, 2) : 0
                    };

                    model.total_efficiency = model.total_efficiency_value.ToStr() + "%(" + Math.Round(produce.total_efficiency / 3600, 2) + "h)";
                    model.idle_loss = model.idle_loss_value.ToStr() + "%(" + Math.Round(produce.idle_loss / 3600, 2) + "h)";
                    model.debug_loss = model.debug_loss_value.ToStr() + "%(" + Math.Round(produce.debug_loss / 3600, 2) + "h)";
                    model.fault_loss = model.fault_loss_value.ToStr() + "%(" + Math.Round(produce.fault_loss / 3600, 2) + "h)";
                    model.shutdown_loss = model.shutdown_loss_value.ToStr() + "%(" + Math.Round(produce.shutdown_loss / 3600, 2) + "h)";

                    list.Add(model);

                    totalEfficiency += produce.total_efficiency / produce.run_times;
                    totalDebug += produce.debug_loss / produce.run_times;
                    totalFault += produce.fault_loss / produce.run_times;
                    totalShutdown += produce.shutdown_loss / produce.run_times;

                    count++;
                }

                summary = new EfficiencySummary
                {
                    total_eff = count == 0 ? 0 : (totalEfficiency / count * 100).FormatDouble(),
                    debug_loss = count == 0 ? 0 : (totalDebug / count * 100).FormatDouble(),
                    fault_loss = count == 0 ? 0 : (totalFault / count * 100).FormatDouble(),
                    shutdown_loss = count == 0 ? 0 : (totalShutdown / count * 100).FormatDouble(),
                };
                summary.idle_loss = (100 - (summary.total_eff + summary.debug_loss + summary.fault_loss + summary.shutdown_loss))
                    .FormatDouble();
            }

            if (request.toexcel == 0)
            {
                //分页
                result.list = list.Skip((request.page - 1) * request.pagesize).Take(request.pagesize).ToList();
                result.summary = summary;
                result.page = request.page;
                result.pagesize = request.pagesize;
                result.total = list.Count;
                return new ObjectResult(result);
            }

            return ExportEffs(list);
        }

        private IEnumerable<MachineRestInfo> GetRestTimesBySections(IEnumerable<int> machineIds)
        {
            var result = new List<MachineRestInfo>();

            var times = _timeAllocationRepository.GetList(m => machineIds.Contains(m.machineid) && m.status == (int)RowState.Valid && m.projectid == ProjectId).ToList();
            foreach (var machineId in machineIds)
            {
                var machineTimes = times.Where(q => q.machineid == machineId);
                foreach (var time in machineTimes)
                {
                    //result.Add(new MachineRestInfo
                    //{
                    //    BingTime = time.bing_time,
                    //    EndTime = time.end_time,
                    //    MachineId = machineId,
                    //    TimeType = (TimeType)time.typeid
                    //});
                    var types = time.typeids.Split(',');
                    foreach (var item in types)
                    {
                        var rest = _restTypeRepository.Get(q => q.id == item.ToInt() && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                        result.Add(new MachineRestInfo
                        {
                            BingTime = rest.startTime,
                            EndTime = rest.endTime,
                            MachineId = machineId,
                            TimeType = (TimeType)rest.range
                        });
                    }
                }
            }

            return result;
        }

        [HttpPost]
        private IActionResult ExportEffs(IList<ResponseGetListEfficiencyAnalysis> responses)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"MachineEfficiencyAnalysis_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<MachineEfficiencyAnalysis>(_machineRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<MachineEfficiencyAnalysis>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new MachineEfficiencyAnalysis
                    {
                        Section = yield.location,
                        Yield = yield.theory_yield.ToStr(),
                        ActualYield = yield.actual_output.ToStr(),
                        ProgramNo = yield.program_no,
                        ProductName = yield.product_name,
                        RouteName = yield.route_name,
                        Efficiency = yield.total_efficiency.ToStr(),
                        IdleLoss = yield.idle_loss.ToStr(),
                        DebugLoss = yield.debug_loss.ToStr(),
                        FaultLoss = yield.fault_loss.ToStr(),
                        ShutDownLoss = yield.shutdown_loss.ToStr(),
                        No = index
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

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

        [HttpPost]
        public IActionResult ExportElectric(IList<ElectricStatistics> responses, int language)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"BarChart_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);

            var helper = new EpPlusExcelHelper<BarChart>(language);
            try
            {
                var machineYields = new List<BarChart>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new BarChart
                    {
                        No = index,
                        Abscissa = yield.title,
                        Ordinates = yield.electric.ToStr()
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

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


        //产量产出统计 数字化工厂首页
        [HttpPost]
        public async Task<IActionResult> ListMachineYieldBySignDetailTwo([FromBody] RequestListMachineYieldsTwo request)
        {
            request.type = "1";
            request.typeValue = "0";
           
            //var machineIds = _machineRepository.GetNCLevelSectionMachineIds(request.sectionID, ProjectId).ToList();
            var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            var machineIds = validMachines.Select(s => s.machine_id).ToList();

            if (!DateTime.TryParse(request.startTime, out var startTime))
            {
                throw new ServerException(500146);
            }
            if (!DateTime.TryParse(startTime.AddDays(1).AddSeconds(-1).ToString(), out var endTime))
            {
                throw new ServerException(500146);
            }
            //var startTime = DateTime.TryParse(request.startTime);
            //var endTime = UnixTimeHelper.ConvertStringDateTime(request.startTime).AddDays(1).AddSeconds(-1);
            if (request.frequency > 0)
            {
                var frequency = _sigerProjectShiftRepository.Get(q => q.id == request.frequency && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                var starts = UnixTimeHelper.GetTimeByUnix(frequency.start_time);
                var ends = UnixTimeHelper.GetTimeByUnix(frequency.end_time);
                if (frequency.start_time < frequency.end_time)
                {
                    DateTime.TryParse((startTime.ToString(ParameterConstant.DateFormat) + " " + starts), out startTime);
                    DateTime.TryParse((startTime.ToString(ParameterConstant.DateFormat) + " " + ends), out endTime);
                }
                else
                {
                    DateTime.TryParse(startTime.AddDays(1).ToString(ParameterConstant.DateFormat) + " " + ends, out endTime);
                    DateTime.TryParse(startTime.ToString(ParameterConstant.DateFormat) + " " + starts, out startTime);
                }
            }
            var repository = new ProductRepository(CompanyId, ProjectId);
            var query = repository.GetYileds(startTime.ToString(ParameterConstant.DateTimeFormat), endTime.ToString(ParameterConstant.DateTimeFormat), machineIds);
            if (!query.Any())
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            var end = (int)UnixTimeHelper.ConvertDataTimeLong(endTime);
            var responses = new ListMachineYieldsResult();
            var list = new List<ResponseGetListMachineYield>();
            var programNos = new List<ProgramYield>();

           // var machines = _machineRepository.GetList(q => machineIds.Contains(q.id) && q.projectid == ProjectId && q.status == (int)RowState.Valid && q.category == (int)MachineCategory.NC).OrderBy(q => q.sorting).ToList();

            foreach (var machine in validMachines)
            {
                var machineYileds = query.Where(q => q.machineID == machine.machine_id);
                if (machineYileds.Any())
                {
                    var yields = await YieldMangaer.GetProgramNos(machineYileds, request.startTime, machine.machine_id, end);
                    programNos.AddRange(yields);
                }
            }
            //var times = _timeRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var times = _timeAllocationRepository.GetRestTimesByMachine(machineIds, ProjectId);
            var beates = _beatSetRepository.GetList(q => machineIds.Contains(q.machineID) && q.projectID == ProjectId && q.status == (int)RowState.Valid).ToList();
            var beatInfoes = Mapper<siger_project_beat_set, BeatSetInfo>.MapList(beates);
            var routes = YieldMangaer.GetProductRoutesOEE(programNos, beatInfoes, times, CompanyId, ProjectId);
            //var validMachines = _machineRepository.GetNCLevelSectionNames(request.sectionID, ProjectId);
            foreach (var machineYield in routes)
            {
                var machine = validMachines.FirstOrDefault(q => q.machine_id == machineYield.machine_id);
                var route = routes.FirstOrDefault(q => q.machine_id == machineYield.machine_id && q.program_code == machineYield.program_code);
                var response = new ResponseGetListMachineYield
                {
                    machine_id = machineYield.machine_id,
                    machine_name = machine != null ? machine.machine_name : "",
                    program_code = machineYield.program_code,
                    title = machine != null ? machine.lastSecondSectionTitle + "-" + machine.lastSectionTitle : "",
                    yield = machineYield.yield,
                    product_name = route != null ? route.product_name : "",
                    route_name = route != null ? route.route_name : "",
                    efficiency = route != null ? route.efficiency : 100,
                    oee = route != null ? route.oee : 0,
                    totaltime = route.totaltime,
                    averagetime = route.averagetime
                };
                list.Add(response);
            }
            responses.data = list.ToList();

            //type 横坐标 1产线区域 2产品名称
            //typeValue
            var type = request.type.ToInt();
            if (type == 1)
            {
                var typeValue = request.typeValue.ToInt();
                if (typeValue == 0) //最后一级产线
                {
                    var levelmachine = _machineRepository.GetNCLevelSectionMachines(request.sectionID, ProjectId).FirstOrDefault();
                    if (levelmachine == null)
                    {
                        responses.xdata.Add(request.sectionID.ToStr());
                        responses.ydata.Add(0);
                    }
                    else
                    {
                        responses.xdata.Add(levelmachine.machine_name);
                        responses.ydata.Add(responses.data.Where(m => m.machine_id == levelmachine.machine_id).Sum(m => m.yield));
                    }
                }
                else
                {
                    var sections = _machineRepository.GetNCLevelSections(request.sectionID, ProjectId);
                    var levels = sections.Where(q => q.levelid == typeValue).ToList();
                    foreach (var levelSection in levels)
                    {
                        var sectionMachineIds = _machineRepository.GetNCMachinIdsBySectionId(levelSection.id, 0, ProjectId);

                        responses.xdata.Add(levelSection.title);
                        responses.ydata.Add(responses.data.Where(m => sectionMachineIds.Contains(m.machine_id)).Sum(m => m.yield));
                    }
                }
            }
            else if (type == 2)
            {
                foreach (var name in responses.data.Select(m => m.product_name).OrderBy(m => m).Distinct())
                {
                    responses.xdata.Add(responses.data.First(m => m.product_name == name).product_name);
                    responses.ydata.Add(responses.data.Where(m => m.product_name == name).Sum(m => m.yield));
                }
            }
            return responses;
        }
    }
}