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

namespace Siger.ApiTPM.Controllers
{
    /// <summary>
    /// 安灯基础设置
    /// </summary>
    public class AndonSummaryController : BaseController
    {
        private readonly ISigerAndonExpectionTypeRepository _andonExpectionType;
        private readonly ISigerAndonInfoRepository _andonInfoRepository;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerAndonStationConfigRepository _andonStationConfigRepository;
        private readonly ISigerProjectUserGroupRepository _projectUserGroupRepository;
        private readonly ISigerProjectUserRepository _projectUserRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;

        public AndonSummaryController(
              ISigerAndonExpectionTypeRepository andonExpectionType, ISigerAndonInfoRepository andonInfoRepository, ISigerProjectLevelSectionRepository levelSectionRepository
            , ISigerProjectMachineAttributionRepository machineAttributionRepository, ISigerProjectMachineRepository machineRepository
            , ISigerAndonStationConfigRepository andonStationConfigRepository, ISigerProjectUserGroupRepository projectUserGroupRepository
            , ISigerProjectUserRepository projectUserRepository)
        {
            _andonExpectionType = andonExpectionType;
            _andonInfoRepository = andonInfoRepository;
            _levelSectionRepository = levelSectionRepository;
            _machineAttributionRepository = machineAttributionRepository;
            _machineRepository = machineRepository;
            _andonStationConfigRepository = andonStationConfigRepository;
            _projectUserGroupRepository = projectUserGroupRepository;
            _projectUserRepository = projectUserRepository;
        }

        [HttpPost]
        public IActionResult GetErrorSummary([FromBody] RequestGetErrorSummary request)
        {
            var now = UnixTimeHelper.GetNow();
            var pid = ProjectId;
            var requestdates = request.dateTime.Split(" - ");
            var success = DateTime.TryParse(requestdates[0], out var dtStart);
            if (!success)
            {
                throw new ServerException(500146);
            }

            success = DateTime.TryParse(requestdates[1], out var dtEnd);
            if (!success)
            {
                throw new ServerException(500146);
            }

            var endDate = dtEnd > DateTime.Now ? DateTime.Now : dtEnd.AddDays(1).AddSeconds(-1);
            dtEnd = dtEnd.AddDays(1).AddSeconds(-1);
            //xID - 0, 1, 2, 
            //x_type - 1 时间 2产线 3异常类型4 部门
            var unixStart = UnixTimeHelper.ConvertDataTimeLong(dtStart);
            var unixEnd = UnixTimeHelper.ConvertDataTimeLong(dtEnd);
            Expression<Func<siger_andon_info, bool>> funCommon = f => f.projectid == pid && f.status != (int)RowState.Invalid && f.create_time >= unixStart && f.create_time <= unixEnd;
            Expression<Func<siger_andon_info, bool>> funExpection = f => true;
            if (request.expection != 0)
            {
                var expections = _andonExpectionType.GetAllExpectionlevel(request.expection, pid);
                funExpection = f => expections.Contains(f.expection_type);
            }
            Expression<Func<siger_andon_info, bool>> funMachine = f => true;
            if (request.sectionId != 0)
            {
                var mids = _machineRepository.GetAttributionMachineIds(request.sectionId, ProjectId);
                if (request.isbottle == 1)
                {
                    mids = _andonStationConfigRepository.GetBottleMachines(ProjectId, new List<int> { request.sectionId }).Select(s => s.machine).ToList();
                }
                funMachine = f => mids.Contains(f.machine);
            }
            var predicates = funCommon.And(funExpection).And(funMachine);
            var andonData = _andonInfoRepository.GetList(predicates).Where(f => f.status == (int)AndonState.Recovery || f.status == (int)AndonState.Com_Approve);

            var xid = request.typeValue.ToInt();
            var type = request.type;
            var sectionId = request.sectionId;
            var result = new List<ResponseGetErrorSummary>();
            if (type == 1)
            {
                var interal = DateTimeHelper.GetInteral(xid);
                var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, xid);
                for (var i = 0; i < dates.Count; i++)
                {
                    long start;
                    long end;
                    var date = string.Empty;
                    if (xid == 0 || xid == 1)
                    {
                        date = dates[i].ToString(ParameterConstant.DateFormat);
                    }
                    else
                    {
                        date = dates[i].ToString(ParameterConstant.YearMonthFormat);
                    }
                    start = UnixTimeHelper.ConvertDataTimeLong(dates[i]);
                    end = UnixTimeHelper.ConvertDataTimeLong(dates[i].AddDays(interal).AddSeconds(-1));
                    var andon = andonData.Where(f => f.create_time >= start && f.create_time <= end);
                    var count = andon.Count();
                    var totalError = andon.Select(s => new { errtime = s.approve_time - s.create_time });
                    double avgResponse = 0;
                    double avgHandle = 0;
                    if (count != 0)
                    {
                        avgHandle = andon.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - (s.handle_time == 0 ? now : s.handle_time) }).Sum(s => s.cost) / count;
                        avgResponse = andon.Select(s => new { handle = (s.handle_time == 0 ? now : s.handle_time) - s.create_time }).Sum(s => s.handle) / count;
                    }
                    result.Add(new ResponseGetErrorSummary
                    {
                        title = date,
                        error_hours = totalError.Sum(s => s.errtime),
                        error_count = count,
                        average_handle_hours = Math.Round(avgHandle, 0),
                        average_response_hours = Math.Round(avgResponse, 0),
                        average_total = Math.Round(avgHandle, 0) + Math.Round(avgResponse, 0)
                    });
                }
            }
            else if (type == 2)
            {
                //var sections = _levelSectionRepository.GetList(f => f.projectid == pid && f.status == (int)RowState.Valid && f.levelid == request.typeValue.ToInt()).ToList();
                var sectiondata = _levelSectionRepository.Get(f => f.id == request.sectionId);
                var sections = _levelSectionRepository.GetSectionFamilyList(request.sectionId, ProjectId);
                sections.Add(sectiondata);
                sections = sections.Where(f => f.levelid == request.typeValue.ToInt()).ToList();
                foreach (var section in sections)
                {
                    var machines = _machineRepository.GetAttributionMachineList(section.id, pid, new List<int> { 1 }).Select(s => s.id).Distinct().ToList();
                    var andon = andonData.Where(f => machines.Contains(f.machine));
                    var count = andon.Count();
                    var totalError = andon.Select(s => new { errtime = s.approve_time - s.create_time }).Sum(s => s.errtime);
                    double avgResponse = 0;
                    double avgHandle = 0;
                    if (count != 0)
                    {
                        avgHandle = andon.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - (s.handle_time == 0 ? now : s.handle_time) }).Sum(s => s.cost) / count;
                        avgResponse = andon.Select(s => new { handle = (s.handle_time == 0 ? now : s.handle_time) - s.create_time }).Sum(s => s.handle) / count;
                    }
                    result.Add(new ResponseGetErrorSummary
                    {
                        title = section.title,
                        error_hours = totalError,
                        error_count = count,
                        average_handle_hours = Math.Round(avgHandle, 0),
                        average_response_hours = Math.Round(avgResponse, 0),
                        average_total = Math.Round(avgHandle, 0) + Math.Round(avgResponse, 0)
                    });
                }
            }
            else if (type == 3)
            {
                var secondlevel = _andonExpectionType.GetList(f => f.projectid == pid && f.status != 0 && f.level == 2).ToList();
                foreach (var item in secondlevel)
                {
                    var expections = _andonExpectionType.GetAllExpectionlevel(item.id, pid);
                    var andon = andonData.Where(f => expections.Contains(f.expection_type));
                    var count = andon.Count();
                    var totalError = andon.Select(s => new { errtime = s.approve_time - s.create_time }).Sum(s => s.errtime);
                    double avgResponse = 0;
                    double avgHandle = 0;
                    if (count != 0)
                    {
                        avgHandle = andon.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - (s.handle_time == 0 ? now : s.handle_time) }).Sum(s => s.cost) / count;
                        avgResponse = andon.Select(s => new { handle = (s.handle_time == 0 ? now : s.handle_time) - s.create_time }).Sum(s => s.handle) / count;
                        result.Add(new ResponseGetErrorSummary
                        {
                            title = item.name,
                            error_hours = totalError,
                            error_count = count,
                            average_handle_hours = Math.Round(avgHandle, 0),
                            average_response_hours = Math.Round(avgResponse, 0),
                            average_total = Math.Round(avgHandle, 0) + Math.Round(avgResponse, 0)
                        });
                    }
                }
            }
            else if (type == 4)
            {
                var groups = _andonExpectionType.GetList(f => f.projectid == pid && f.status != 0).Select(s => s.usergroup).Distinct().ToList();
                foreach (var item in groups)
                {
                    var expections = _andonExpectionType.GetList(f => f.usergroup == item && f.projectid == pid).Select(s => s.id);
                    var andon = andonData.Where(f => expections.Contains(f.expection_type));
                    var count = andon.Count();
                    var totalError = andon.Select(s => new { errtime = s.approve_time - s.create_time }).Sum(s => s.errtime);
                    double avgResponse = 0;
                    double avgHandle = 0;
                    if (count != 0)
                    {
                        avgHandle = andon.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - (s.handle_time == 0 ? now : s.handle_time) }).Sum(s => s.cost) / count;
                        avgResponse = andon.Select(s => new { handle = (s.handle_time == 0 ? now : s.handle_time) - s.create_time }).Sum(s => s.handle) / count;
                        var groupdata = _projectUserGroupRepository.Get(f => f.projectid == pid && f.id == item && f.status != 0);
                        if (groupdata != null)
                        {
                            result.Add(new ResponseGetErrorSummary
                            {
                                title = groupdata.title,
                                error_hours = totalError,
                                error_count = count,
                                average_handle_hours = Math.Round(avgHandle, 0),
                                average_response_hours = Math.Round(avgResponse, 0),
                                average_total = Math.Round(avgHandle, 0) + Math.Round(avgResponse, 0)
                            });
                        }
                    }
                }
            }
            //init ret data
            var sumcount = result.Sum(s => s.average_total);
            double num = 0;
            foreach (var item in result)
            {
                num += item.average_total;
                if (sumcount != 0)
                {
                    item.error_percent = Math.Round(num / sumcount * 100, 0);
                }
            }
            var sumError = result.Sum(s => s.error_hours);
            if (request.toexcel == 0)
            {
                var ret = new ResponseErrorSummary();
                ret.dataX.AddRange(result.Select(s => s.title).ToList());
                ret.dataY2.AddRange(result.Select(s => s.error_percent).ToList());
                ret.dataYList.Add(result.Select(s => Math.Floor(s.average_handle_hours / 60)).ToList());
                ret.dataYList.Add(result.Select(s => Math.Floor(s.average_response_hours / 60)).ToList());
                ret.max = 1;
                if (result.Any())
                {
                    ret.max = result.Select(s => new { max = s.average_handle_hours + s.average_response_hours }).Max(m => m.max);
                }
                foreach (var item in result)
                {
                    if (sumError != 0)
                    {
                        item.error_percent = Math.Round(item.error_hours / sumError * 100, 0);
                    }
                    else
                    {
                        item.error_percent = 0;
                    }
                }
                ret.table.AddRange(result.ToList());
                ret.max = Math.Round(ret.max / 60);
                return new ObjectResult(ret);
            }
            foreach (var item in result)
            {
                if (sumError != 0)
                {
                    item.error_percent = Math.Round(item.error_hours / sumError * 100, 0);
                }
                else
                {
                    item.error_percent = 0;
                }
            }
            return ExportErrorSummary(result);
        }

        private IActionResult ExportErrorSummary(List<ResponseGetErrorSummary> 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<AndonErrorSummary>(_machineAttributionRepository.GetProjectLanguage(ProjectId));
            try
            {
                var machineYields = new List<AndonErrorSummary>();
                var index = 1;
                foreach (var yield in responses)
                {
                    var machineYield = new AndonErrorSummary
                    {
                        No = index,
                        Abscissa = yield.title,
                        ErrorCount = yield.error_count,
                        ErrorHour = Math.Round(yield.error_hours / 60, 0),
                        AverageHandleHours = Math.Round(yield.average_handle_hours / 60, 0),
                        AverageResponseHours = Math.Round(yield.average_response_hours / 60, 0),
                        ErrorPercent = yield.error_percent
                    };
                    machineYields.Add(machineYield);
                    index++;
                }

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

        [HttpGet]
        public IActionResult OeeLossAnalysis(int sectionId, string dateTime)
        {
            return new ObjectResult(CommonEnum.Succefull);
        }
        /// <summary>
        /// 获取大数据oee信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(List<ResponseAndonOee>), 200)]
        public async Task<IActionResult> GetOeeData([FromBody] RequestAndonOee request)
        {
            var ret = new List<ResponseAndonOee>();
            var pid = ProjectId;
            var cid = CompanyId;
            var yieldRepository = new LocationYieldRepository(cid, pid);
            var mids = _andonStationConfigRepository.GetBottleMachines(pid, new List<int> { request.section }).Select(s => s.machine).ToList();
            if (request.toexcel > 0)
            {
                request.page = 1;
                request.pagesize = 999999;
            }
            var datas = await yieldRepository.GetLocationYieldDataAsync(mids, request.type, request.start, request.end, request.page, request.pagesize);
            var levelDatas = _levelSectionRepository.GetList(f => f.projectid == pid && f.status != 0);
            var userDatas = _projectUserRepository.GetList(f => f.projectid == pid && f.status != 0);
            var typeDatas = _andonExpectionType.GetList(f => f.projectid == pid && f.status != 0);
            foreach (var item in datas.Data)
            {
                var model = Mapper<LocationYield, ResponseAndonOee>.Map(item);
                model.sectionName = levelDatas.FirstOrDefault(f => f.id == item.sectionID)?.title ?? "";
                model.editor_name = userDatas.FirstOrDefault(f => f.projectid == pid && f.status != 0 && f.mid == model.editor)?.name ?? "";
                model.type_name = typeDatas.FirstOrDefault(f => f.projectid == pid && f.status != 0 && f.id == model.type)?.name ?? "";
                model.subtraction = model.subtraction;
                model.rel_edit_time = model.edit_time == 0 ? "" : UnixTimeHelper.ConvertStringDateTime(model.edit_time.ToStr()).ToStr();
                model.str_endTime = model.endTime.ToString(ParameterConstant.DateTimeFormat);
                model.str_startTime = model.startTime.ToString(ParameterConstant.DateTimeFormat);
                if (!string.IsNullOrEmpty(model.workOrderId))
                {
                    var andonInfo = _andonInfoRepository.GetData(new RequestAndon { work_order = model.workOrderId }, pid);
                    if (andonInfo.Total > 0)
                    {
                        var temp = andonInfo.Data.First();
                        model.expection2 = temp.expection2;
                        model.expection3 = temp.expection3;
                        model.usergroup_name = temp.usergroup_name;
                    }
                }
                ret.Add(model);
            }
            //ret = ret.Where(f => f.subtraction > 0).ToList();
            if (request.toexcel > 0)
            {
                return ExportOeeData(ret, pid);
            }
            return new PagedObjectResult(ret, datas.Total, request.page, request.pagesize);
        }

        private IActionResult ExportOeeData(List<ResponseAndonOee> responses, int pid)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }


            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"OeeData_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            var helper = new EpPlusExcelHelper<AndonOee>(_machineAttributionRepository.GetProjectLanguage(pid));
            try
            {
                var data = Mapper<ResponseAndonOee, AndonOee>.MapList(responses);
                helper.GenerateExcel(data, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export ErrorSummary failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }
        /// <summary>
        /// 获取一级异常
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetFirstLevelExpection()
        {
            var data = _andonExpectionType.GetList(f => f.projectid == ProjectId && f.status != 0 && f.level == 1);
            return new ObjectResult(data);
        }
        /// <summary>
        /// 修改oee异常类型
        /// </summary>
        /// <param name="id">以“,”隔开的id</param>
        /// <param name="type">一级异常id</param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult SetOeeData(string id, int type)
        {
            var strids = id.Split(',').ToList();
            if (!strids.Any() || type == 0)
            {
                throw new BadRequestException(CommonEnum.Fail);
            }
            var ids = new List<int>();
            foreach (var strid in strids)
            {
                var num = strid.ToInt();
                if (num != 0)
                {
                    ids.Add(num);
                }
            }
            var pid = ProjectId;
            var cid = CompanyId;
            var yieldRepository = new LocationYieldRepository(cid, pid);
            if (yieldRepository.UpdateYieldDataType(ids, type, UserId, UnixTimeHelper.GetNow()))
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }



        /// <summary>
        /// Oee统计图表
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(ResponseOeeStatistical), 200)]
        public IActionResult GetOeeStatistical([FromBody] RequestOeeStatistical request)
        {
            var pid = ProjectId;
            var unixStart = request.start;
            var unixEnd = request.end;
            var dtStart = UnixTimeHelper.ConvertStringDateTime(unixStart.ToStr());
            var dtEnd = UnixTimeHelper.ConvertStringDateTime(unixEnd.ToStr());
            var xtype = request.xtype;
            var type = request.type;
            var data = new List<ResponseOeeStatisticalTable>();
            if (request.toexcel > 0)
            {
                request.page = 1;
                request.pagesize = 999999;
            }
            if (type == 1)//时间
            {
                var sections = _levelSectionRepository.GetLevelSectionIds(request.section, ProjectId).ToList();
                var oeeInfo = _andonInfoRepository.GetOee(dtStart, dtEnd, sections);
                var interal = DateTimeHelper.GetInteral(xtype);
                var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, xtype);
                for (var i = 0; i < dates.Count; i++)
                {
                    DateTime start;
                    DateTime end;
                    var date = string.Empty;
                    var rate = 0d;
                    if (xtype == 0 || xtype == 1)
                    {
                        date = dates[i].ToString(ParameterConstant.DateFormat);
                    }
                    else if (xtype == 999)
                    {
                        date = dates[i].ToString(ParameterConstant.YearMonthDayHourMinute);
                    }
                    else
                    {
                        date = dates[i].ToString(ParameterConstant.YearMonthFormat);
                    }
                    start = dates[i];
                    //end = xtype == 999 ? dates[i].AddHours(1).AddSeconds(-1) : dates[i].AddDays(interal).AddSeconds(-1);
                    end = xtype == 999 ? dates[i].AddHours(1) : dates[i].AddDays(interal);
                    var oeeInterval = oeeInfo.Where(f => f.starttime >= start && f.endtime <= end);
                    var numerator = oeeInterval.Sum(s => s.numerator);
                    var denominator = oeeInterval.Sum(s => s.denominator);
                    if (denominator != 0)
                    {
                        rate = Math.Round((numerator / denominator) * 100, 2);
                    }
                    data.Add(new ResponseOeeStatisticalTable
                    {
                        name = date,
                        rate = rate
                    });
                }
            }
            else if (type == 2)//产线
            {
                var sectiondata = _levelSectionRepository.GetList(f => f.levelid == request.xtype).ToList();
                //var sections = _levelSectionRepository.GetSectionFamilyList(request.section, ProjectId);
                //sections.Add(sectiondata);
                //sections = sections.Where(f => f != null && f.levelid == xtype).ToList();

                foreach (var section in sectiondata)
                {
                    var sections = _levelSectionRepository.GetLevelSectionIds(section.id, ProjectId).ToList();
                    var rate = 0d;
                    var oeeInterval = _andonInfoRepository.GetOee(dtStart, dtEnd, sections);
                    var numerator = oeeInterval.Sum(s => s.numerator);
                    var denominator = oeeInterval.Sum(s => s.denominator);
                    if (denominator != 0)
                    {
                        rate = Math.Round((numerator / denominator) * 100, 2);
                    }
                    data.Add(new ResponseOeeStatisticalTable { rate = rate, name = section.title });
                }
            }
            var ret = new ResponseOeeStatistical
            {
                data = data,
                x = data.Select(s => s.name).ToList(),
                y = data.Select(s => s.rate).ToList()
            };
            if (request.toexcel > 0)
            {
                return ExportOeeStatistical(ret.data, pid);
            }
            return new ObjectResult(ret);
        }

        private IActionResult ExportOeeStatistical(List<ResponseOeeStatisticalTable> responses, int pid)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }


            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"OeeStatistical_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            var helper = new EpPlusExcelHelper<OeeStatisticalTable>(_machineAttributionRepository.GetProjectLanguage(pid));
            try
            {
                var data = Mapper<ResponseOeeStatisticalTable, OeeStatisticalTable>.MapList(responses);
                helper.GenerateExcel(data, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export ExportOeeStatistical failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }



        /// <summary>
        /// 整体OEE损失分布
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        [ProducesResponseType(typeof(ResponseOeeLoss), 200)]
        public async Task<IActionResult> GetOeeLoss([FromBody] RequestOeeLoss request)
        {
            var cid = CompanyId;
            var pid = ProjectId;
            var unixStart = request.start;
            var unixEnd = request.end;
            var dtStart = UnixTimeHelper.ConvertStringDateTime(unixStart.ToStr());
            var dtEnd = UnixTimeHelper.ConvertStringDateTime(unixEnd.ToStr());
            var xtype = request.xtype;
            var type = request.type;
            var data = new List<ResponseOeeLossTable>();
            var yieldRepository = new LocationYieldRepository(cid, pid);
            //init types
            var strtypes = request.expections.Split(',').ToList();
            var types = new List<int>();
            foreach (var strtype in strtypes)
            {
                if (strtype.ToInt() != 0)
                {
                    types.Add(strtype.ToInt());
                }
            }
            types = types.Where(f => f != 0).Distinct().ToList();
            if (!types.Any())//如果没有查询条件 初始化所有异常类型
            {
                types = _andonExpectionType.GetList(f => f.projectid == pid && f.status != 0 && f.level == 1).Select(s => s.id).ToList();
            }
            //去除计划停机
            var stopExpection = _andonExpectionType.Get(f => f.projectid == pid && f.status != 0 && f.is_caloee == 0 && f.is_passprocess == 1)?.id ?? 0;
            if (stopExpection != 0)
            {
                types = types.Where(f => f != stopExpection).ToList();
            }
            if (request.toexcel > 0)
            {
                request.page = 1;
                request.pagesize = 999999;
            }
            if (type == 1)//时间
            {
                var machineids = _machineRepository.GetAttributionMachineList(request.section, ProjectId, new List<int> { 1 }).Select(s => s.id);
                var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machineids.Contains(f.machine_id)).Select(s => s.machine_id);
                var interal = DateTimeHelper.GetInteral(xtype);
                var dates = DateTimeHelper.GetDateTimes(dtStart, dtEnd, xtype);
                for (var i = 0; i < dates.Count; i++)
                {
                    DateTime start;
                    DateTime end;
                    var date = string.Empty;
                    if (xtype == 0 || xtype == 1)
                    {
                        date = dates[i].ToString(ParameterConstant.DateFormat);
                    }
                    else if (xtype == 999)
                    {
                        date = dates[i].ToString(ParameterConstant.DateTimeFormat);
                    }
                    else
                    {
                        date = dates[i].ToString(ParameterConstant.YearMonthFormat);
                    }
                    start = dates[i];
                    end = xtype == 999 ? dates[i].AddHours(1).AddSeconds(-1) : dates[i].AddDays(interal).AddSeconds(-1);
                    var loss = await yieldRepository.GetOeeLoss(start, end, botton_machines, types);

                    data.Add(new ResponseOeeLossTable
                    {
                        name = date,
                        loss = Math.Round(loss / 60, 2),
                        start = start,
                        end = end
                    });
                }
            }
            else if (type == 2)//产线
            {
                var start = UnixTimeHelper.ConvertStringDateTime(request.start.ToStr());
                var end = UnixTimeHelper.ConvertStringDateTime(request.end.ToStr());
                var sectiondata = _levelSectionRepository.Get(f => f.id == request.section);
                var sections = _levelSectionRepository.GetSectionFamilyList(request.section, ProjectId);
                sections.Add(sectiondata);
                sections = sections.Where(f => f != null && f.levelid == xtype).ToList();
                foreach (var section in sections)
                {
                    var machineids = _machineRepository.GetAttributionMachineList(section.id, ProjectId, new List<int> { 1 }).Select(s => s.id);
                    var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machineids.Contains(f.machine_id)).Select(s => s.machine_id);
                    var loss = await yieldRepository.GetOeeLoss(start, end, botton_machines, types);
                    data.Add(new ResponseOeeLossTable
                    {
                        name = section.title,
                        loss = Math.Round(loss / 60, 2),
                        start = start,
                        end = end
                    });
                }
            }
            else if (type == 3)//损失类型
            {
                var start = UnixTimeHelper.ConvertStringDateTime(request.start.ToStr());
                var end = UnixTimeHelper.ConvertStringDateTime(request.end.ToStr());
                var machineids = _machineRepository.GetAttributionMachineList(request.section, ProjectId, new List<int> { 1 }).Select(s => s.id);
                var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machineids.Contains(f.machine_id)).Select(s => s.machine_id);
                //去除计划停机
                var expectionids = _andonExpectionType.GetList(f => f.status != 0 && f.projectid == pid && f.level == 1
                && f.is_caloee != 0).Select(s => s.id);
                if (types.Any())
                {
                    expectionids = expectionids.Where(f => types.Contains(f));
                }
                foreach (var id in expectionids)
                {
                    var loss = await yieldRepository.GetOeeLoss(start, end, botton_machines, new List<int> { id });
                    var expection = _andonExpectionType.Get(f => f.id == id);
                    if (expection != null)
                    {
                        data.Add(new ResponseOeeLossTable
                        {
                            name = expection.name,
                            loss = Math.Round(loss / 60, 2),
                            start = start,
                            end = end
                        });
                    }
                }
            }
            else if (type == 4)//异常类型级别
            {
                //只支持一个一级异常查询
                if (!types.Any())
                {
                    throw new BadRequestException(CommonEnum.NoData);
                }
                var expections = _andonExpectionType.GetExpectionSonSelfLevel(types.First(), pid).Where(f => f.level == xtype);
                var machineids = _machineRepository.GetAttributionMachineList(request.section, ProjectId, new List<int> { 1 }).Select(s => s.id);
                var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machineids.Contains(f.machine_id)).Select(s => s.machine_id);

                foreach (var expection in expections)
                {
                    //init workorders
                    var tempExpections = _andonExpectionType.GetExpectionSonSelfLevel(expection.id, pid).Select(s => s.id).Distinct();
                    var workorders = _andonInfoRepository.GetList(f => f.status != 0 && f.projectid == pid && tempExpections.Contains(f.expection_type)).Select(s => $"'{s.work_order}'").Where(f => !string.IsNullOrEmpty(f) && f != "''").Distinct().ToList();
                    var loss = 0d;
                    if (workorders.Any())
                    {
                        loss = await yieldRepository.GetOeeLoss(dtStart, dtEnd, botton_machines, null, workorders);
                    }
                    data.Add(new ResponseOeeLossTable
                    {
                        name = expection.name,
                        loss = Math.Round(loss / 60, 2),
                        start = dtStart,
                        end = dtEnd
                    });
                }
            }
            data = data.Where(f => f.loss > 0).OrderByDescending(o => o.loss).ToList();
            var y2 = new List<double>();
            var total = data.Sum(s => s.loss);
            var nowLoss = 0d;
            foreach (var item in data)
            {
                nowLoss += item.loss;
                var temp = nowLoss / total;
                y2.Add(Math.Round(temp * 100));
            }
            var ret = new ResponseOeeLoss
            {
                data = data,
                x = data.Select(s => s.name).ToList(),
                y1 = data.Select(s => s.loss).ToList(),
                y2 = y2
            };
            if (request.toexcel > 0)
            {
                return ExportOeeLoss(ret.data, pid);
            }
            return new ObjectResult(ret);
        }

        private IActionResult ExportOeeLoss(List<ResponseOeeLossTable> responses, int pid)
        {
            if (!responses.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }

            var rootDir = FileSystemHelper.GetPhysicalFolders(FileSystemHelper.CommonFileSetting.PhysicalFolder, FileSystemHelper.ExportFileName);
            var temporaryFileName = $"OeeLoss_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
            var fileName = Path.Combine(rootDir, temporaryFileName);
            var helper = new EpPlusExcelHelper<OeeLossTable>(_machineAttributionRepository.GetProjectLanguage(pid));
            try
            {
                var data = Mapper<ResponseOeeLossTable, OeeLossTable>.MapList(responses);
                helper.GenerateExcel(data, fileName);
                return new ObjectResult($"{FileSystemHelper.CommonFileSetting.RequestPath}/{FileSystemHelper.ExportFileName}/{temporaryFileName}");
            }
            catch (Exception e)
            {
                Logger.WriteLineError("Export ExportOeeLoss failed, error: " + e.Message);
                throw new BadRequestException(RequestEnum.ExportFailed);
            }
            finally
            {
                helper.Dispose();
            }
        }

    }
}