using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.DashboardRepository.Entities;
using Siger.Middlelayer.DashboardRepository.Repositories.Interface;
using Siger.Middlelayer.DashboardRepository.Request;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Response;
using Siger.ApiCommon.Filters;
using Siger.Middlelayer.Utility.Helpers;
using Siger.Middlelayer.Share.Enum.ModuleEnum;
using Siger.Middlelayer.DashboardRepository.Response;
using Siger.Middlelayer.Dapper;
using System.Drawing;
using Siger.Middlelayer.Repository.Data;
using Siger.Middlelayer.QmsRepository.Repositories.Interface;
using NPOI.SS.Formula.Functions;
using Siger.Middlelayer.QmsRepository.Response;

namespace Siger.ApiDashboard.Controllers
{
    public class DashboardAndonController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly ISigerAndonInfoRepository _andonInfoRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerAndonStationConfigRepository _andonStationConfigRepository;
        private readonly IDashboardLevelRepository _dashboardLevelRepository;
        private readonly ISigerAndonExpectionTypeRepository _andonExpectionTypeRepository;
        private readonly ISigerProjectUserGroupRepository _projectUserGroupRepository;
        private readonly ISigerProjectLevelSectionRepository _levelSectionRepository;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly IDashboardFactoryChanel _dashboardFactoryChanel;
        private readonly IQmsReworkDataRepository _qmsReworkDataRepository;
        private readonly IProductRouteRepository _productRouteRepository;

        public DashboardAndonController(IUnitOfWork unitOfWork, ISigerAndonInfoRepository andonInfoRepository, ISigerProjectMachineRepository machineRepository, ISigerAndonStationConfigRepository andonStationConfigRepository
            , IDashboardLevelRepository dashboardLevelRepository, ISigerAndonExpectionTypeRepository andonExpectionTypeRepository, ISigerProjectUserGroupRepository projectUserGroupRepository
            , ISigerProjectLevelSectionRepository levelSectionRepository, ISigerProjectMachineAttributionRepository machineAttributionRepository, IDashboardFactoryChanel dashboardFactoryChanel
            , IQmsReworkDataRepository qmsReworkDataRepository, IProductRouteRepository productRouteRepository)
        {
            _unitOfWork = unitOfWork;
            _andonInfoRepository = andonInfoRepository;
            _machineRepository = machineRepository;
            _andonStationConfigRepository = andonStationConfigRepository;
            _dashboardLevelRepository = dashboardLevelRepository;
            _andonExpectionTypeRepository = andonExpectionTypeRepository;
            _projectUserGroupRepository = projectUserGroupRepository;
            _levelSectionRepository = levelSectionRepository;
            _machineAttributionRepository = machineAttributionRepository;
            _dashboardFactoryChanel = dashboardFactoryChanel;
            _qmsReworkDataRepository = qmsReworkDataRepository;
            _productRouteRepository = productRouteRepository;
        }

        #region andon others

        /// <summary>
        /// oee圆圈
        /// </summary>
        /// <param name="section"></param>
        /// <param name="date"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AndonExpectionPercentage(int section, string date, string start)
        {
            var pid = ProjectId;
            var cid = CompanyId;
            var cfg = _dashboardLevelRepository.Get(f => f.ProjectId == ProjectId && f.Section == section && f.PageType == (int)DashboardEnum.Chanel);
            if (!int.TryParse(start, out int searchTime))
                searchTime = cfg == null ? 8 : cfg.Startime;
            DateTime currDtStart = StartDate(date);

            var timerange = DateTimeHelper.GetDateTimeRange(date);

            var dtStart = section == 0 ? timerange.StarTime : currDtStart.AddHours(searchTime);
            var dtEnd = section == 0 ? timerange.EndTime : dtStart.AddHours(cfg.Schedu);
            var unixStart = UnixTimeHelper.ConvertDataTimeLong(dtStart.ToStr());
            var unixEnd = UnixTimeHelper.ConvertDataTimeLong(dtEnd.ToStr());
            var ret = new List<ResponseAndonExpectionInfo>();
            var color = new List<string>();
            double total = 0;
            //find machine
            List<int> machines = new List<int>();
            if(section != 0)
            {
                machines = _machineRepository.GetAttributionMachineIds(section, pid).ToList();
            }
            else
            {
                machines = _machineRepository.GetList(q => q.projectid == ProjectId && q.status == (int)RowState.Valid).Select(q => q.id).ToList();
            }
            
            var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machines.Contains(f.machine_id)).Select(s => s.machine_id).ToList();
            var yieldRepository = new LocationYieldRepository(cid, pid);
            var yieldData = yieldRepository.GetTopLocationYields().ToList();
            
            var expections = _andonExpectionTypeRepository.GetList(f => f.projectid == pid && f.status != 0);
            var typeids = yieldData.Select(s => s.type).Distinct();
            foreach (var typeid in typeids)
            {
                double time = 0;
                var expection = expections.FirstOrDefault(f => f.id == typeid);
                if (expection != null && expection.is_caloee == 0)
                {
                    continue;
                }
                var yield = yieldData.Where(f => f.type == typeid).ToList();
                if (yield.Any())
                {
                    time = yield.Sum(s => s.subtraction);
                }
                var data = new ResponseAndonExpectionInfo
                {
                    expection_id = typeid,
                    expection_name = expection?.name ?? "    ",
                    color = expection?.color ?? "#01B1FF",
                    time = time,
                    start = unixStart,
                    end = unixEnd,
                };
                ret.Add(data);
            }
            //oee 返工报废
            var sections = _levelSectionRepository.GetLevelSectionIds(section, pid);
            var error = _qmsReworkDataRepository.GetReworkData(sections.ToList(), ProjectId, dtStart, dtEnd);
            if (error.Any())
            {
                var errorTotal = 0d;
                var errorExpection = _andonExpectionTypeRepository.Get(f => f.level == 1 && f.status != 0 && f.type == 2);
                errorTotal = error.Sum(s => s.Loss);
                if (errorExpection != null && ret.Any(f => f.expection_id == errorExpection.id))
                {
                    var temp = ret.First(f => f.expection_id == errorExpection.id);
                    temp.time += errorTotal;
                }
                else
                {
                    ret.Add(new ResponseAndonExpectionInfo
                    {
                        color = errorExpection?.color ?? "#19FFFF",
                        expection_name = errorExpection?.name ?? "报废件&返工件损失Scrap & Rework",
                        expection_id = errorExpection?.id ?? 0,
                        time = errorTotal,
                        start = unixStart,
                        end = unixEnd,
                    });
                }
            }
            if (ret.Any())
            {
                total = ret.Sum(s => s.time);
                color = ret.Select(s => s.color).ToList();
            }
            return new ObjectResult(new { arr = ret.Where(f => f.time > 0), total, color });
        }

        [HttpGet]
        public IActionResult AndonSlice(int section, string date, string start)
        {
            var nowtime = DateTime.Now;
            var now = UnixTimeHelper.GetNow();
            var ret = new List<ResponseAndonSlice>();
            var pid = ProjectId;
            var cid = CompanyId;
            //_dashboardLevelRepository.GetTimeRange(date, pid, out var dtStart, out var dtEnd, section, DashboardEnum.Chanel);
            var cfg = _dashboardLevelRepository.Get(f => f.ProjectId == ProjectId && f.Section == section && f.PageType == (int)DashboardEnum.Chanel);
            if (!int.TryParse(start, out int searchTime))
                searchTime = cfg == null ? 8 : cfg.Startime;
            DateTime currDtStart = StartDate(date);
            var dtStart = currDtStart.AddHours(searchTime);
            var dtEnd = dtStart.AddHours(cfg.Schedu);
            var interval = UnixTimeHelper.ConvertDataTimeLong(dtEnd) - UnixTimeHelper.ConvertDataTimeLong(dtStart);

            //find machine
            var machines = _machineRepository.GetAttributionMachineIds(section, pid);
            var botton_machines = _andonStationConfigRepository.GetList(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machines.Contains(f.machine_id)).Select(s => s.machine_id);
            var yieldRepository = new LocationYieldRepository(cid, pid);
            var machineid = 0;
            if (botton_machines.Any())
            {
                machineid = botton_machines.OrderBy(f => f).First();
            }
            var yieldData = yieldRepository.GetLocationYields(new List<int> { machineid }, dtStart, dtEnd).OrderBy(f => f.startTime).ToList();
            var temp_type = 0;
            var expections = _andonExpectionTypeRepository.GetList(f => f.projectid == pid && f.status != 0 && f.level == 1).ToList();
            //构造数据
            foreach (var item in yieldData)
            {
                if (item.type == 0)
                {
                    continue;
                }
                if (temp_type == item.type)
                {
                    ret.Last().cycletime += item.cycletime;
                    ret.Last().endtime = item.endTime;
                }
                else
                {
                    ret.Add(new ResponseAndonSlice
                    {
                        cycletime = item.cycletime,
                        starttime = item.startTime,
                        endtime = item.endTime,
                        status = item.type
                    });
                }
                temp_type = item.type;
            }
            //1.0
            //if (!ret.Any())
            //{
            //    ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = dtEnd, percentage = 1, color = "#808080", cycletime = interval, status = 0 });
            //    return new ObjectResult(ret);
            //}
            //2.0
            if (!ret.Any())
            {
                var lastdata = yieldRepository.GetLastLocationYieldsData(new List<int> { machineid }, dtEnd).FirstOrDefault();
                if (lastdata == null)
                {
                    ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = dtEnd, percentage = 1, color = "#808080", cycletime = interval, status = 0 });
                    return new ObjectResult(ret);
                }
                if (lastdata.startTime < dtStart && lastdata.endTime > dtEnd)
                {
                    var color = _andonExpectionTypeRepository.Get(f => f.level == 1 && f.status != (int)RowState.Invalid && f.id == lastdata.type)?.color ?? "#808080";
                    ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = dtEnd, percentage = 1, color = color, cycletime = interval, status = 0 });
                    return new ObjectResult(ret);
                }
                else if (lastdata.endTime < dtStart)
                {
                    ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = dtEnd, percentage = 1, color = "#808080", cycletime = interval, status = 0 });
                    return new ObjectResult(ret);
                }
                else
                {
                    var cycletime = lastdata.endTime.Subtract(dtStart).TotalSeconds;
                    var color = _andonExpectionTypeRepository.Get(f => f.level == 1 && f.status != (int)RowState.Invalid && f.id == lastdata.type)?.color ?? "#808080";
                    ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = lastdata.endTime, percentage = cycletime / interval, color = color, cycletime = cycletime, status = lastdata.type });
                    cycletime = dtEnd.Subtract(lastdata.endTime).TotalSeconds;
                    ret.Add(new ResponseAndonSlice { starttime = lastdata.endTime, endtime = dtEnd, percentage = cycletime / interval, color = "#808080", cycletime = cycletime, status = 0 });
                    return new ObjectResult(ret);
                }
            }
            var last = ret.OrderBy(o => o.starttime).Last();
            var lastendtime = last.endtime;
            //end
            if (last.cycletime == 0)
            {
                last.endtime = nowtime;
                last.status = 0;
                last.color = "#5AF158";
                last.cycletime = now - UnixTimeHelper.ConvertDataTimeLong(last.starttime);
            }
            lastendtime = last.endtime;
            var lastinterval = UnixTimeHelper.ConvertDataTimeLong(dtEnd) - UnixTimeHelper.ConvertDataTimeLong(lastendtime);
            if (lastendtime < dtEnd && last.cycletime != 0)
            {
                ret.Add(new ResponseAndonSlice { starttime = lastendtime, endtime = dtEnd, cycletime = lastinterval, status = 0, color = "#808080" });
            }
            else
            {
                last.endtime = dtEnd;
                var lastdata = last;
                var cycletime = UnixTimeHelper.ConvertDataTimeLong(lastdata.endtime) - UnixTimeHelper.ConvertDataTimeLong(lastdata.starttime);
                last.cycletime = cycletime;
            }

            //start
            var firststarttime = ret.OrderBy(o => o.starttime).First().starttime;
            var firstinterval = UnixTimeHelper.ConvertDataTimeLong(firststarttime) - UnixTimeHelper.ConvertDataTimeLong(dtStart);
            var lastyielddata = yieldRepository.GetLastLocationYieldsData(new List<int> { machineid }, firststarttime).FirstOrDefault();
            if (lastyielddata != null)
            {
                ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = firststarttime, cycletime = firstinterval, status = lastyielddata.type, color = "#5AF158" });
            }
            else
            {
                ret.Add(new ResponseAndonSlice { starttime = dtStart, endtime = firststarttime, cycletime = firstinterval, status = 0, color = "#5AF158" });
            }
            //处理数据
            var total = ret.Select(s => s.cycletime).Sum();
            foreach (var item in ret)
            {
                item.percentage = (double)(item.cycletime) / total;
                if (item.status != 0)
                {
                    item.color = expections.FirstOrDefault(f => f.id == item.status)?.color ?? "#5AF158";
                }
            }
            return new ObjectResult(ret.OrderBy(o => o.starttime));
        }

        /// <summary>
        /// top10 andon order(care)
        /// </summary>
        /// <param name="section"></param>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Top10Andon(int section, string date)
        {
            var pid = ProjectId;
            var now = UnixTimeHelper.GetNow();
            _dashboardLevelRepository.GetTimeRange(date, pid, out var dtStart, out var dtEnd, section, DashboardEnum.Chanel);
            var starttime = UnixTimeHelper.ConvertDataTimeLong(dtStart);
            var endtime = UnixTimeHelper.ConvertDataTimeLong(dtEnd);
            //find machine
            var machines = _machineRepository.GetAttributionMachineIds(section, pid);
            var andoninfos = _andonInfoRepository.GetList(f => f.create_time <= endtime && f.create_time >= starttime && f.projectid == pid
            && machines.Contains(f.machine) && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal)
            //坑
            //.Select(s => new ResponseTop10Andon { start = s.create_time, end = s.complete_time == 0 ? now : s.complete_time, work_order = s.work_order, expection_type = s.expection_type }).ToList();
            .Select(s => new ResponseTop10Andon { start = s.create_time, end = s.approve_time == 0 ? now : s.approve_time, work_order = s.work_order, expection_type = s.expection_type, section = s.station }).ToList();
            //坑 谜之操作
            var temp = andoninfos.ToList();
            foreach (var item in temp)
            {
                var expections = _andonExpectionTypeRepository.GetExpectionParent(item.expection_type, pid);
                if (expections.Any(f => f.level == 2))
                {
                    item.work_order = expections.First(f => f.level == 2).name;
                    item.work_order += "-" + _levelSectionRepository.Get(f => f.id == item.section)?.title ?? "";
                }
                else
                {
                    andoninfos.Remove(item);
                }
            }
            var topdata = andoninfos.Where(f => f.end >= starttime).Select(s => new { cost = s.end - s.start, s.work_order }).OrderByDescending(o => o.cost).ToList();
            if (andoninfos.Count > 10)
            {
                topdata = topdata.Take(10).ToList();
            }
            return new ObjectResult(topdata);
        }
        /// <summary>
        /// 查询时间
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        DateTime StartDate(string date)
        {
            if (string.IsNullOrEmpty(date))
            {
                return DateTimeHelper.GetTodayStartTime();
            }

            if (!DateTime.TryParse(date, out DateTime dt))
                return DateTimeHelper.GetTodayStartTime();
            return DateTimeHelper.GetTodayStartTime(dt);

        }
        /// <summary>
        /// andon info data channel
        /// </summary>
        /// <param name="section"></param>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AndonInfo(int section, string date)
        {
            var pid = ProjectId;
            var now = UnixTimeHelper.GetNow();
            var ret = new List<ResponseAndonInfo>();
            //var timerange = DateTimeHelper.GetDateTimeRange(date);
            //var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            //var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var machineids = _machineRepository.GetAttributionMachineIds(section, pid);
            var andondatas = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.Approve && machineids.Contains(f.machine)).OrderByDescending(o => o.create_time).ToList();
            foreach (var andondata in andondatas)
            {
                if (ret.Any(f => f.machine_id == andondata.machine))
                {
                    var data = ret.First(f => f.machine_id == andondata.machine);
                    data.count += 1;
                    //data.cost += (andondata.complete_time == 0 ? now : andondata.complete_time) - andondata.create_time;
                    continue;
                }
                var status = 0;
                //status = andondatas.Where(f => f.status <= (int)AndonState.Approve && f.machine == andondata.machine).OrderBy(o => o.status).FirstOrDefault()?.status ?? 0;
                var machine = _machineRepository.GetList(f => f.id == andondata.machine && f.projectid == pid && f.status != 0).FirstOrDefault();
                //hehe
                var expections = _andonExpectionTypeRepository.GetExpectionParent(andondata.expection_type, ProjectId);
                if (!expections.Any(f => f.level == 2))
                {
                    continue;
                }
                ret.Add(new ResponseAndonInfo
                {
                    count = 1,
                    status = EnumHelper.GetEnumDesc((AndonState)status),
                    status_value = andondata.status,
                    machine = machine?.title ?? "    ",//unknow machine
                    machine_id = machine?.id ?? 0,
                    expection = expections.First(f => f.level == 2).name,
                    //坑
                    //cost = (andondata.complete_time == 0 ? now : andondata.complete_time) - andondata.create_time
                    cost = (andondata.approve_time == 0 ? now : andondata.approve_time) - andondata.create_time
                });
            }
            return new ObjectResult(ret);
        }

        /// <summary>
        /// andon info data channel for mobile
        /// </summary>
        /// <param name="section"></param>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AndonInfoForMobile(int section, string date)
        {
            var pid = ProjectId;
            var now = UnixTimeHelper.GetNow();
            var ret = new List<ResponseAndonInfo>();
            var timerange = DateTimeHelper.GetDateTimeRange(date);
            var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var machineids = _machineRepository.GetAttributionMachineIds(section, pid);

            var andondatas = _andonInfoRepository.GetList(f => f.projectid == pid && f.status != 0 && machineids.Contains(f.machine) && f.status < (int)AndonState.Approve).ToList();
            foreach (var andondata in andondatas)
            {
                var expection = string.Empty;
                var expectiondata = _andonExpectionTypeRepository.Get(f => f.projectid == pid && f.status != 0 && f.id == andondata.expection_type);
                switch (expectiondata.level)
                {
                    case 1:
                        expection = expectiondata?.name ?? "";
                        break;
                    case 2:
                        if (expectiondata != null)
                        {
                            expectiondata = _andonExpectionTypeRepository.Get(f => f.projectid == pid && f.status != 0 && f.id == expectiondata.parent);
                            expection = expectiondata?.name ?? "";
                        }
                        break;
                    case 3:
                        if (expectiondata != null)
                        {
                            expectiondata = _andonExpectionTypeRepository.Get(f => f.projectid == pid && f.status != 0 && f.id == expectiondata.parent);
                            if (expectiondata != null)
                            {
                                expectiondata = _andonExpectionTypeRepository.Get(f => f.projectid == pid && f.status != 0 && f.id == expectiondata.parent);
                                expection = expectiondata?.name ?? "";
                            }
                        }
                        break;
                    default:
                        break;
                }
                var machine = _machineAttributionRepository.Get(f => f.machine == andondata.machine).name;
                var sectiondata = _levelSectionRepository.Get(f => f.id == section)?.title ?? "";
                ret.Add(new ResponseAndonInfo
                {
                    //坑
                    //cost = (andondata.complete_time == 0 ? now : andondata.complete_time) - andondata.create_time,
                    cost = (andondata.approve_time == 0 ? now : andondata.approve_time) - andondata.create_time,
                    status = EnumHelper.GetEnumDesc((AndonState)andondata.status),
                    status_value = andondata.status,
                    expection = expection,
                    machine = $"{sectiondata}-{machine}"
                });
            }
            return new ObjectResult(ret);
        }

        /// <summary>
        /// andon info data factory
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AndonInfoForFactory(string date)
        {
            var pid = ProjectId;
            var ret = new List<ResponseAndonInfoForFactory>();
            var now = UnixTimeHelper.GetNow();
            var timerange = DateTimeHelper.GetDateTimeRange(date);
            var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var second_expections = _andonExpectionTypeRepository.GetList(f => f.projectid == pid && f.status != 0 && f.level == 2).ToList();
            foreach (var second_data in second_expections)
            {
                var sons = _andonExpectionTypeRepository.GetExpectionSonLevel(second_data.id, pid).Select(s => s.id).ToList();
                sons.Add(second_data.id);
                var andoninfo = _andonInfoRepository.GetList(f => f.create_time >= start && f.create_time <= end && f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).ToList();
                long cost = 0;
                var count = 0;
                if (andoninfo.Any())
                {
                    cost = andoninfo.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - s.create_time }).Sum(s => s.cost);
                    count = andoninfo.Count();
                }
                else
                {
                    andoninfo = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).Take(5).ToList();
                    if (andoninfo.Any())
                    {
                        var first = andoninfo.Max(q => q.create_time);
                        cost = andoninfo.Select(s => new { cost = (s.approve_time == 0 ? first : s.approve_time) - s.create_time }).Sum(s => s.cost);
                        count = andoninfo.Count();
                    }
                }
                if(cost > 0)
                {
                    ret.Add(new ResponseAndonInfoForFactory
                    {
                        cost = cost,
                        count = count,
                        expection = second_data.name
                    });
                }
            }
            ret = ret.Where(f => f.count > 0).ToList();
            ret = ret.OrderByDescending(o => o.cost).ToList();
            return new ObjectResult(ret);
        }
        [HttpGet]
        public IActionResult AndonMachinForChannel(int section, string date)
        {
            var pid = ProjectId;
            var now = UnixTimeHelper.GetNow();
            var ret = new List<ResponseAndonMachinForChannel>();
            //var timerange = DateTimeHelper.GetDateTimeRange(date);
            //var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            //var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var machineids = _machineRepository.GetAttributionMachineIds(section, pid).ToList();
            var machines = _machineRepository.GetMachineLocationForDashboard(machineids, pid);
            var andondatas = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && machineids.Contains(f.machine) && f.status < (int)AndonState.Approve).OrderByDescending(o => o.create_time).ToList();
            foreach (var item in andondatas)
            {
                var machine = machines.FirstOrDefault(f => f.machineId == item.machine);
                if (machine != null)
                {
                    if (!ret.Any(f => f.title.Equals(machine.machine_name)))
                    {
                        ret.Add(new ResponseAndonMachinForChannel
                        {
                            left = machine.x,
                            top = machine.y,
                            status = item.status,
                            type = _andonExpectionTypeRepository.Get(f => f.id == item.expection_type)?.name ?? "",
                            title = machine.machine_name,
                            //坑
                            //timeRang = (item.complete_time == 0 ? now : item.complete_time) - item.create_time
                            timeRang = (item.approve_time == 0 ? now : item.approve_time) - item.create_time
                        });
                    }
                }
            }
            return new ObjectResult(ret);
        }

        #endregion

        #region andon dashboard
        /// <summary>
        /// andon top5 expection
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult SecondExpcectionTop5(string date)
        {
            var pid = ProjectId;
            var ret = new List<ResponseAndonInfoForFactory>();
            var now = UnixTimeHelper.GetNow();
            var timerange = DateTimeHelper.GetDateTimeRange(date);
            var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var second_expections = _andonExpectionTypeRepository.GetList(f => f.projectid == pid && f.status != 0 && f.level == 2).ToList();
            foreach (var second_data in second_expections)
            {
                var sons = _andonExpectionTypeRepository.GetExpectionSonLevel(second_data.id, pid).Select(s => s.id).ToList();
                sons.Add(second_data.id);
                var andoninfo = _andonInfoRepository.GetList(f => f.create_time >= start && f.create_time <= end && f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).ToList();
                long cost = 0;
                var count = 0;
                if (andoninfo.Any())
                {
                    cost = andoninfo.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - s.create_time }).Sum(s => s.cost);
                    count = andoninfo.Count();
                }
                else
                {
                    andoninfo = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).Take(5).ToList();
                    if (andoninfo.Any())
                    {
                        var first = andoninfo.Max(q => q.approve_time);
                        cost = andoninfo.Select(s => new { cost = (s.approve_time == 0 ? first : s.approve_time) - s.create_time }).Sum(s => s.cost);
                        count = andoninfo.Count();
                    }
                }
                ret.Add(new ResponseAndonInfoForFactory
                {
                    cost = cost,
                    count = count,
                    expection = second_data.name
                });
            }
            ret = ret.Where(f => f.cost != 0).OrderByDescending(o => o.cost).Take(5).ToList();
            return new ObjectResult(ret);
        }

        /// <summary>
        /// andon handle cost
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]

        public IActionResult AndonHandleCost(string date)
        {
            var pid = ProjectId;
            var now = UnixTimeHelper.GetNow();
            var ret = new List<ResponseAndonHandleCost>();
            var timerange = DateTimeHelper.GetDateTimeRange(date);
            var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var second_expections = _andonExpectionTypeRepository.GetList(f => f.projectid == pid && f.status != 0 && f.level == 2).ToList();
            foreach (var second_data in second_expections)
            {
                var sons = _andonExpectionTypeRepository.GetExpectionSonLevel(second_data.id, pid).Select(s => s.id).ToList();
                sons.Add(second_data.id);
                var andoninfo = _andonInfoRepository.GetList(f => f.create_time >= start && f.create_time <= end && f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).ToList();
                long cost = 0;
                var count = 0;
                long handle = 0;
                if (!andoninfo.Any())
                {
                    andoninfo = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && sons.Contains(f.expection_type)).Take(10).ToList();
                    if (andoninfo.Any())
                    {
                        now = andoninfo.Max(q => q.approve_time).ToStr().ToInt();
                    }
                }
               
                cost = andoninfo.Select(s => new { cost = (s.approve_time == 0 ? now : s.approve_time) - (s.handle_time == 0 ? now : s.handle_time) }).Sum(s => s.cost);
                handle = andoninfo.Select(s => new { handle = (s.handle_time == 0 ? now : s.handle_time) - s.create_time }).Sum(s => s.handle);
                count = andoninfo.Count();

                ret.Add(new ResponseAndonHandleCost
                {
                    cost = cost,
                    count = count,
                    expection = second_data.name,
                    handle = handle,
                    group = _projectUserGroupRepository.GetList(f => f.projectid == pid && f.status != 0 && f.id == second_data.usergroup).FirstOrDefault()?.title ?? "N/A"
                });
            }
            ret = ret.Where(f => f.count > 0).OrderByDescending(o => o.cost).ToList();
            return new ObjectResult(ret);
        }

        /// <summary>
        /// andon count
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]

        public IActionResult AndonCount(string date)
        {
            var pid = ProjectId;
            var ret = new ResponseAndonCount();
            var timerange = DateTimeHelper.GetDateTimeRange(date);
            var todaystart = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            var todayend = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var start = 0;
            var end = UnixTimeHelper.GetNow();
            var andoninfo = _andonInfoRepository.GetList(f => f.create_time >= start && f.create_time <= end && f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal).ToList();
            ret.today_count = _andonInfoRepository.GetList(f => f.create_time >= todaystart && f.create_time <= todayend && f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal).ToList().Count();
            ret.unhandle_count = andoninfo.Count(f => f.status == (int)AndonState.WaitHandle);
            ret.handling_count = andoninfo.Count(f => f.status == (int)AndonState.Handling);
            ret.handle_count = andoninfo.Count(f => f.status == (int)AndonState.Complete);
            return new ObjectResult(ret);
        }

        /// <summary>
        /// andon group count
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult AndonGroupCount(string date)
        {
            var pid = ProjectId;
            var ret = new { x = new List<string>(), y1 = new List<int>(), y2 = new List<int>(), y3 = new List<int>() };
            //var timerange = DateTimeHelper.GetDateTimeRange(date);
            //var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            //var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var start = 0;
            var end = UnixTimeHelper.GetNow();
            var andoninfo = _andonInfoRepository.GetAndonGroupCount(pid, start, end).ToList();
            foreach (var item in andoninfo)
            {
                ret.x.Add(item.group_name);
                ret.y1.Add(item.unhandle_count);
                ret.y2.Add(item.handling_count);
                ret.y3.Add(item.wait_count);
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// andon detail data
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAndonDetail(string date)
        {
            var pid = ProjectId;
            //var timerange = DateTimeHelper.GetDateTimeRange(date);
            //var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            //var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var start = 0;
            var end = UnixTimeHelper.GetNow();
            var ret = _andonInfoRepository.GetAndonDashboradDetail(pid, start, end);
            return new ObjectResult(ret);
        }
        /// <summary>
        /// channel trigger
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAndonChannelData(string date)
        {
            var pid = ProjectId;
            //var timerange = DateTimeHelper.GetDateTimeRange(date);
            //var start = UnixTimeHelper.ConvertDataTimeLong(timerange.StarTime);
            //var end = UnixTimeHelper.ConvertDataTimeLong(timerange.EndTime);
            var start = 0;
            var end = UnixTimeHelper.GetNow();
            var ret = new List<ResponseChannelData>();
            var sections = _dashboardFactoryChanel.GetDashboardChanel(pid);
            foreach (var section in sections)
            {
                var machines = _machineRepository.GetAttributionMachineIds(section.id, pid);
                var andon = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && machines.Contains(f.machine) && f.create_time >= start && f.create_time <= end).ToList();
                ret.Add(new ResponseChannelData
                {
                    name = section.title,
                    accept = andon.Count(f => f.status == (int)AndonState.WaitHandle),
                    handle = andon.Count(f => f.status == (int)AndonState.Handling),
                    wait = andon.Count(f => f.status == (int)AndonState.Complete),
                    current = andon.Count(f => f.status < (int)AndonState.Approve && f.status != (int)AndonState.Abnormal),
                });
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// channel trigger for mobile
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAndonChannelDataForMobile(string date)
        {
            var now = UnixTimeHelper.GetNow();
            var pid = ProjectId;
            var cid = CompanyId;
            var start = 0;
            var end = UnixTimeHelper.GetNow();
            var ret = new List<ResponseChannelDataForMobile>();
            var sections = _dashboardFactoryChanel.GetDashboardChanel(pid);
            var yieldRepository = new LocationYieldRepository(cid, pid);
            foreach (var section in sections)
            {
                var expection = string.Empty;
                var ishutdown = 0;
                var handling = 0;
                var unhandle = 0;
                var wait = 0;
                var machines = _machineRepository.GetAttributionMachineIds(section.id, pid);

                var allandon = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal
                     && machines.Contains(f.machine) && f.create_time >= start && f.create_time <= end).OrderByDescending(o => o.create_time).ToList();
                if (allandon.Any())
                {
                    unhandle = allandon.Count(f => f.status == (int)AndonState.WaitHandle);
                    wait = allandon.Count(f => f.status == (int)AndonState.Complete);
                    handling = allandon.Count(f => f.status == (int)AndonState.Handling);
                }
                var botton = _andonStationConfigRepository.Get(f => f.project_id == pid && f.status != 0 && f.station_type == 1 && machines.Contains(f.machine_id));
                if (botton != null)
                {
                    var lastdata = yieldRepository.GetLastLocationYieldsData(new List<int> { botton.machine_id }, DateTime.Now).FirstOrDefault();
                    expection = _andonExpectionTypeRepository.Get(f => f.id == lastdata.type && f.id != 14)?.name ?? "";//排除速度与损失
                }
                ret.Add(new ResponseChannelDataForMobile
                {
                    title = section.title,
                    id = section.id,
                    expection = expection,
                    handling = handling,
                    unhandle = unhandle,
                    wait = wait,
                    isShutDown = ishutdown
                });
            }
            return new ObjectResult(ret);
        }
        /// <summary>
        /// 工单通道分布
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAndonMobile(string date)
        {
            var pid = ProjectId;
            var ret = new { x = new List<string>(), y1 = new List<int>(), y2 = new List<int>(), y3 = new List<int>() };
            var sections = _dashboardFactoryChanel.GetDashboardChanel(ProjectId);
            //  var sections = _levelSectionRepository.GetAccLines(pid);
            foreach (var section in sections)
            {
                var machines = _machineRepository.GetAttributionMachineIds(section.id, pid);
                var andon = _andonInfoRepository.GetList(f => f.projectid == pid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.CancleAbnormal && machines.Contains(f.machine)).ToList();
                ret.x.Add(section.title);
                ret.y1.Add(andon.Count(f => f.status == (int)AndonState.WaitHandle));
                ret.y2.Add(andon.Count(f => f.status == (int)AndonState.Handling));
                ret.y3.Add(andon.Count(f => f.status == (int)AndonState.Complete));
            }
            return new ObjectResult(ret);
        }
        #endregion

        /// <summary>
        /// slice detail
        /// </summary>
        /// <param name="section"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <param name="expectiontype"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAdnonSliceDetail(int section, int starttime, int endtime, int expectiontype)
        {
            var ret = new ResponseAdnonSliceDetail();
            var start = UnixTimeHelper.ConvertStringDateTime(starttime.ToStr());
            var end = UnixTimeHelper.ConvertStringDateTime(endtime.ToStr());
            var retAndon = new List<ResponseAndonDetail>();
            //var machines = _machineRepository.GetAttributionMachineIds(section, ProjectId);
            List<int> machines;
            if (section != 0)
            {
                var machineData = _machineRepository.GetAttributionMachineIds(section, ProjectId);
                machines = _andonStationConfigRepository.GetList(f => f.project_id == ProjectId && f.status != 0 && f.station_type == 1 && machineData.Contains(f.machine_id)).Select(s => s.machine_id).ToList();
            }
            else
            {
                machines = _andonStationConfigRepository.GetList(f => f.project_id == ProjectId && f.status != 0 && f.station_type == 1).Select(s => s.machine_id).ToList();
            }

            var yieldHelper = new LocationYieldRepository(CompanyId, ProjectId);
            var yieldData = yieldHelper.GetLocationYields(machines, start, end);
            if (expectiontype != 0)
            {
                yieldData = yieldData.Where(f => f.type == expectiontype).ToList();
            }
            foreach (var item in yieldData)
            {
                var st = UnixTimeHelper.ConvertDataTimeLong(item.startTime);
                var check = retAndon.LastOrDefault(f => f.expection_id == item.type && f.end == st);
                if (check != null)
                {
                    check.cost_time += item.subtraction;
                    continue;
                }
                var expectionName = _andonExpectionTypeRepository.Get(f => f.id == item.type)?.name ?? "";
                var expectionId = item.type;
                var responsibility = string.Empty;
                if (!string.IsNullOrEmpty(item.workOrderId))
                {
                    var andoninfo = _andonInfoRepository.Get(f => f.status != 0 && f.work_order == item.workOrderId);
                    if (andoninfo != null)
                    {
                        expectionId = andoninfo.expection_type;
                        var lastExpection = _andonExpectionTypeRepository.Get(f => f.id == andoninfo.expection_type)?.usergroup ?? 0;
                        var expection = _andonExpectionTypeRepository.GetExpectionParent(andoninfo.expection_type, ProjectId).OrderBy(o => o.level);
                        if (expection.Any())
                        {
                            expectionName = string.Join('-', expection.Select(s => s.name));
                        }
                        responsibility = _projectUserGroupRepository.Get(f => f.id == lastExpection)?.title ?? "";
                    }
                }
                var model = new ResponseAndonDetail
                {
                    cost_time = item.subtraction,
                    end = UnixTimeHelper.ConvertDataTimeLong(item.endTime.ToStr()),
                    start = UnixTimeHelper.ConvertDataTimeLong(item.startTime.ToStr()),
                    work_order = item.workOrderId,
                    expection = expectionName,
                    expection_id = expectionId,
                    responsibility = responsibility,
                };
                retAndon.Add(model);
            }
            ret.AndonDetail = retAndon;
            var expectionCheck = _andonExpectionTypeRepository.Get(f => f.projectid == ProjectId && f.status != 0 && f.id == expectiontype);
            if (expectionCheck != null && expectionCheck.type == 2)
            {
                var sections = _levelSectionRepository.GetLevelSectionIds(section, ProjectId);
                ret.AndonDetailEx = _qmsReworkDataRepository.GetReworkData(sections.ToList(), ProjectId, start, end);
            }
            else
            {
                ret.AndonDetailEx = new List<ResponseReworkData>();
            }
            return new ObjectResult(ret);
        }

        /// <summary>
        /// slice detail
        /// </summary>
        /// <param name="section"></param>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetAdnonSliceSum(int section, int starttime, int endtime)
        {
            var start = UnixTimeHelper.ConvertStringDateTime(starttime.ToStr());
            var end = UnixTimeHelper.ConvertStringDateTime(endtime.ToStr());
            var ret = new List<ResponseAndonDetail>();
            var machines = _machineRepository.GetAttributionMachineIds(section, ProjectId);
            var yieldHelper = new LocationYieldRepository(CompanyId, ProjectId);
            var yieldData = yieldHelper.GetLocationYields(machines, start, end);
            var types = yieldData.Select(s => s.type).Distinct().ToList();

            foreach (var item in types)
            {
                var expection = _andonExpectionTypeRepository.Get(f => f.id == item);
                if (expection == null)
                {
                    continue;
                }
                if (expection.is_caloee == 0 && expection.is_passprocess == 1)
                {
                    continue;
                }
                var model = new ResponseAndonDetail
                {
                    expection_id = expection.id,
                    expection = expection.name,
                    cost_time = yieldData.Where(f => f.type == item).Select(s => s.subtraction).Sum()
                };
                ret.Add(model);
            }
            return new ObjectResult(ret);
        }
    }
}