using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Siger.ApiTPM.Utilities;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.TpmRepository;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Response;

namespace Siger.ApiTPM.Tasks
{
    public class AutoSyncTpmHelper : IDisposable
    {
        private static AutoSyncTpmHelper _helper;
        public static AutoSyncTpmHelper Instance = _helper ?? (_helper = new AutoSyncTpmHelper());

        private static ApiTpmDbContext _context;
        public AutoSyncTpmHelper()
        {
            _context = new ApiTpmDbContext();
        }

        public void StartTask()
        {
            try
            {
                var thread = new Thread(Process)
                {
                    IsBackground = true
                };
                thread.Start();
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoSyncTpm failed, error:" + e);
            }
        }

        private void Process()
        {
            while (true)
            {
                Execute();
                Thread.Sleep(1000 * 60 * 1); // 1分钟
            }
        }

        /// <summary>
        /// TPM 应急维修 推送任务
        /// </summary>
        private void Execute()
        {
            try
            {
                if (RedisCache.Client == null)
                {
                    RedisCache.Connect();
                }
            }
            catch (Exception e)
            {
                Logger.WriteLineInfo($"Redis connect error:" + e);
            }
            var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
            if (dbConfigs.Any())
            {
                _context = new ApiTpmDbContext();
                foreach (var dbNameConfig in dbConfigs)
                {
                    if (string.IsNullOrWhiteSpace(dbNameConfig.RedisDbName))
                    {
                        Logger.WriteLineError($"AutoSyncTpm DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                        continue;
                    }
                    if (dbNameConfig.Pid ==0)
                        continue;

                    ExcuteRepairReportPushMessage(dbNameConfig.Pid);
                }
                Dispose();
            }
        }

        public void ExcuteRepairReportPushMessage(int projectId)
        {
            try
            {
                var time = UnixTimeHelper.GetNow();
                RepairReportPlan(time, projectId);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoSyncTpm Execute RepairReport Timing Task failed" + e);
            }
        }

        #region 每分钟执行一次 异常上报工单通知

        private void RepairReportPlan(int time, int _projectId)
        {
            //var configRepeatTime = GetConfigRepeatTime();
            var repairTemps = GetRepairReportPlans(time, _projectId);            
            if (repairTemps.Any())
            {
                var config = GetAppProjectConfig(_projectId);
                if (config != null)
                {
                    var levelSections = GetSonLevelSections(0, _projectId);
                    var pushmessage = new MessagePushHelper(config.appkey, config.appsecret, config.signid,
                        config.issendSMS);
                    repairTemps = repairTemps.GroupBy(t => t.repairid).Select(t => t.FirstOrDefault()).ToList();
                    var isTranslate = GetProjectLanguage(_projectId) == (int)LanguageType.EN;
                    var translateHelper = new TranslateHelper(isTranslate);
                    var pushTitle = translateHelper.GetTranslateText(TranslateEnEnum.AbnormalReport);
                    foreach (var repairTemp in repairTemps)
                    {
                        //如果90天未处理，不推送
                        if (repairTemp.difference > 60 * 24 * 30)
                            continue;

                        var repairInfo = _context.siger_project_repair.FirstOrDefault(t =>
                            t.id == repairTemp.repairid && t.status > 0 && t.status < 6 && t.projectid == _projectId);
                        if (repairInfo != null)
                        {
                            if (repairTemp.push_status == 0)
                            {
                                //记录log
                                //信息记录
                                repairInfo.report_level = repairTemp.level;
                                _context.siger_project_repair.Update(repairInfo);
                                var repairListInfo = new siger_project_repair_list
                                {
                                    repairid = repairInfo.id,
                                    status = repairInfo.status,
                                    projectid = _projectId,
                                    mid = 0,
                                    title = ((int)RepairListStatus.AbnormalReport).ToString()
                                };

                                var midList = GetReportPushAndSectionMidList(repairInfo, repairTemp.machineid, time, _projectId, repairTemp.machinelevel);
                                var reportMidList = midList[(int)AppPushType.PushAndSave].Select(s => s.mid).Distinct().ToList();

                                var sectionMidList = midList[(int) AppPushType.SaveNotPush].Select(s=>s.mid).Distinct().ToList();
                                //var groupMidList = sectionMidList.Where(t => reportMidList.Contains(t)).ToList();
                                //var grouptitle = GetUserGroupTitleByMid(groupMidList).ToList();
                                var currUser = midList[(int)AppPushType.PushAndSave].Where(f => f.level == repairInfo.report_level).Select(s => s.mid).Distinct();
                                var grouptitle = GetUserGroupTitleByMid(currUser).Distinct().ToList();
                                var paras = new Dictionary<string, string>();
                                if (grouptitle.Any())
                                {
                                    repairListInfo.content =
                                        "【" + GetPositionByMachineId(repairInfo.machineid, _projectId, levelSections) + "】 " +
                                        (repairTemp.difference) +
                                        translateHelper.GetTranslateText(TranslateEnEnum.NoResponseMinuteFeedbackUp) +
                                        string.Join(',', grouptitle) + " " +
                                        translateHelper.GetTranslateText(TranslateEnEnum.EnteredWorkOrder);
                                    paras.Add("time", repairTemp.difference + "");
                                    paras.Add("userGroupTitle", string.Join(',', grouptitle));
                                    paras.Add("enter", string.Join(',', translateHelper.GetTranslateText(TranslateEnEnum.EnteredWorkOrder)));
                                }
                                else
                                {
                                    repairListInfo.content =
                                        "【" + GetPositionByMachineId(repairInfo.machineid, _projectId, levelSections) + "】 " +
                                        (repairTemp.difference) +
                                        translateHelper.GetTranslateText(TranslateEnEnum.NoResponseMinuteFeedbackUp);
                                    paras.Add("time", repairTemp.difference + "");
                                    paras.Add("userGroupTitle", string.Join(',', grouptitle));
                                    paras.Add("enter", "");
                                }
                                repairListInfo.creattime = time;
                                _context.siger_project_repair_list.Add(repairListInfo);
                                if (_context.SaveChanges() > 0)
                                {
                                    //foreach (var mid in sectionMidList)
                                    foreach (var mid in reportMidList)
                                    {
                                        if (mid > 0)
                                        {
                                            var repairMsg = new siger_app_project_message
                                            {
                                                repairid = repairTemp.repairid,
                                                projectid = _projectId,
                                                type = (int)RepairOrPlanStatus.Repair,
                                                title = pushTitle,
                                                status = repairTemp.status,
                                                create_time = UnixTimeHelper.GetNow(),
                                                content = repairListInfo.content,
                                                tomid = mid
                                            };
                                            _context.siger_app_project_message.Add(repairMsg);
                                            _context.SaveChanges();

                                           
                                            //if (reportMidList.Contains(mid))
                                            //{
                                            var mute = _context.siger_app_mute.FirstOrDefault(t =>
                                                    t.projectid == _projectId && t.status == 0 &&
                                                    (t.repairid == repairInfo.id || t.repairid == 0) && t.mid == mid);
                                            if (mute == null)
                                            {
                                                try
                                                {
                                                    var isOnline = IsOnlie(repairMsg.tomid, repairMsg.projectid,
                                                        SystemConfigKey.AppUserOnlineInterval);
                                                    var toUserKey = GetUserAppKey(repairMsg.tomid,
                                                        repairMsg.projectid);
                                                    if (toUserKey == null)
                                                        continue;

                                                    var mobile = GetUserMobile(repairMsg.tomid,
                                                        repairMsg.projectid);
                                                    int templateId = SMSTemplateConst.RepairReportPlan;
                                                    if (isTranslate)
                                                    {
                                                        templateId = TemplateHelper.GetSmsEnTemplateId(templateId);
                                                    }
                                                    if (templateId > 0)
                                                    {
                                                        pushmessage.PushMessage(repairMsg, isOnline, toUserKey, mobile, templateId, paras);
                                                        SendWeXinMessage(repairMsg.title, repairMsg.content, time,
                                                            repairMsg.tomid, _projectId, TemplateHelper.GetWxTempleteId(isTranslate));
                                                    }
                                                }
                                                catch (Exception ex)
                                                {
                                                    Logger.WriteLineError("push message error :" + ex);
                                                }
                                            }

                                            //}
                                        }
                                    }
                                }
                            }

                            if (repairTemp.push_status == 1)
                            {
                                repairInfo.report_level = repairTemp.level;
                                _context.siger_project_repair.Update(repairInfo);
                                if (_context.SaveChanges() > 0)
                                {
                                    var message = _context.siger_app_project_message.FirstOrDefault(t =>
                                        t.projectid == _projectId && t.repairid == repairInfo.id
                                                                  && t.status == repairTemp.status &&
                                                                  t.type == (int)RepairOrPlanStatus.Repair);
                                    if (message != null)
                                    {
                                        var mute = _context.siger_app_mute.FirstOrDefault(t =>
                                            t.projectid == _projectId && t.status == 0 &&
                                            (t.repairid == repairInfo.id || t.repairid == 0) && t.mid == message.tomid);
                                        if (mute != null)
                                        {
                                            var isOnline = IsOnlie(message.tomid, message.projectid,
                                                SystemConfigKey.AppUserOnlineInterval);
                                            var toUserKey = GetUserAppKey(message.tomid, message.projectid);
                                            var mobile = GetUserMobile(message.tomid, message.projectid);
                                            int templateId = SMSTemplateConst.WaitingForOrders;
                                            if (isTranslate)
                                            {
                                                templateId = TemplateHelper.GetSmsEnTemplateId(templateId);
                                            }
                                            if (templateId > 0)
                                            {
                                                var location = GetPositionByMachineId(repairInfo.machineid, _projectId, levelSections);
                                                var fault = _context.siger_project_machine_fault.FirstOrDefault(t =>
                                                    t.id == repairInfo.faultid);
                                                var paras = new Dictionary<string, string>
                                                {
                                                    {"location", location},
                                                    {"fault", fault?.title ?? "-" + translateHelper.GetTranslateText(TranslateEnEnum.Other) + "-"}
                                                };
                                                pushmessage.PushMessage(message, isOnline, toUserKey, mobile,
                                                    templateId, paras);
                                                SendWeXinMessage(message.title, message.content, time,
                                                    message.tomid, _projectId, TemplateHelper.GetWxTempleteId(isTranslate));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private IEnumerable<string> GetUserGroupTitleByMid(IEnumerable<int> midList)
        {
            var query = from q in _context.siger_project_user
                join p in _context.siger_project_usergroup
                    on q.usergroupid.ToInt() equals p.id
                where q.status == (int) RowState.Valid && p.status == (int) RowState.Valid
                                                       && midList.Contains(q.mid)
                select p.title;
            return query;
        }

        private List<RepairTemp> GetRepairReportPlans(int time, int _projectId)
        {
            var tempList = new List<RepairTemp>();
            var repairs = GetRepairMachineList(_projectId).ToList();
            if (repairs.Any())
            {
                foreach (var repair in repairs)
                {
                    var machine = _context.siger_project_machine.FirstOrDefault(t => t.id == repair.machineid);
                    var spaceTimeArr = machine != null
                        ? GetRepairSpaceTime(_projectId, machine.machinelevel > 0 ? machine.machinelevel : 1)
                        : new List<siger_project_repair_report>();
                    if (spaceTimeArr.Any())
                    {
                        var temp = new RepairTemp
                        {
                            repairid = repair.id,
                            machineid = repair.machineid,
                            report_level = repair.report_level,
                            status = repair.status,
                            spacetime = 0,
                            machinelevel = machine.machinelevel > 0 ? machine.machinelevel : 1
                        };
                        switch (repair.status)
                        {
                            case 1:
                                var difference = time - repair.createtime;
                                temp = GetCompareRepairTempList(temp, difference, 1, spaceTimeArr);
                                if (temp.level > 0)
                                {
                                    tempList.Add(temp);
                                }
                                break;
                            case 2:
                                difference = time - repair.taketime;
                                temp = GetCompareRepairTempList(temp, difference, 2, spaceTimeArr);
                                if (temp.level > 0)
                                {
                                    tempList.Add(temp);
                                }
                                break;
                            case 3:
                                difference = time - repair.signtime;
                                temp = GetCompareRepairTempList(temp, difference, 3, spaceTimeArr);
                                if (temp.level > 0)
                                {
                                    tempList.Add(temp);
                                }
                                break;
                            case 4:
                                difference = time - repair.completetime;
                                temp = GetCompareRepairTempList(temp, difference, 4, spaceTimeArr);
                                if (temp.level > 0)
                                {
                                    tempList.Add(temp);
                                }
                                break;
                        }
                    }
                }
            }
            return tempList;
        }

        private IEnumerable<siger_project_repair> GetRepairMachineList(int projectId)
        {
            var query = from q in _context.siger_project_repair
                where q.projectid == projectId && q.status > 0 && q.status < 6 && q.work_type == 1
                select q;

            return query;
        }

        private RepairTemp GetCompareRepairTempList(RepairTemp temp, int difference, 
            int type, List<siger_project_repair_report> spaceTimeArr)
        {
            temp.type = type;
            temp.push_status = 0;
            temp.level = 0;
            var spaceTime1 = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 1);
            if (spaceTime1 != null)
            {
                var spacetime = spaceTime1.space_time * 60;
                if (difference % (spaceTime1.repeat_time * 60) < 60 && difference < spacetime && difference >= spaceTime1.repeat_time * 60)
                {
                    temp.level = 1;
                    temp.push_status = 1;//循环推送
                    temp.spacetime = spaceTime1.space_time;
                    temp.difference = difference / 60;
                }
            }
            var spaceTime2 = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 2);
            var spaceTime3 = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 3);
            if (spaceTime3 != null && spaceTime1 != null && spaceTime2 != null)
            {
                var spacetime3 = spaceTime3.space_time * 60 + spaceTime2.space_time * 60 + spaceTime1.space_time * 60;
                var spacetime2 = spaceTime2.space_time * 60 + spaceTime1.space_time * 60;
                var spacetime1 = spaceTime1.space_time * 60;
                var diff3 = difference - spacetime3;
                var diff2 = difference - spacetime2;
                var diff1 = difference - spacetime1;
                if (diff3 >= 0 && difference % spacetime3 < 60 && diff3 < 120)
                {
                    temp.level = 4;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime3.space_time;
                }
                else if (diff3 >= 0 && diff3 % (spaceTime3.repeat_time * 60) < 60 && diff3 >= spaceTime3.repeat_time * 60)
                {
                    temp.level = 4;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime3.space_time;
                }
                else if (diff2 >= 0 && diff3 < 0 && difference % spacetime2 < 60 && diff2 < 120)
                {
                    temp.level = 3;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime2.space_time;
                }
                else if (diff2 >= 0 && diff3 < 0 && diff2 % (spaceTime2.repeat_time * 60) < 60 && diff2 >= spaceTime2.repeat_time * 60)
                {
                    temp.level = 3;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime2.space_time;
                }
                else if (diff1 >= 0 && diff2 < 0 && difference % spacetime1 < 60 && diff1 < 120)
                {
                    temp.level = 2;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime1.space_time;
                }
                else if (diff1 >= 0 && diff2 < 0 && diff1 % (spaceTime1.repeat_time * 60) < 60 && diff1 >= spaceTime1.repeat_time * 60)
                {
                    temp.level = 2;
                    temp.difference = difference / 60;
                    temp.spacetime = spaceTime1.space_time;
                }
            }
            return temp;
        }

        #endregion

        #region 获取配置数据

        private siger_app_project_config GetAppProjectConfig(int projectId)
        {
            return _context.siger_app_project_config.FirstOrDefault(q =>
                q.projectId == projectId && q.status == (int) RowState.Valid);
        }

        private int GetConfigRepeatTime()
        {
            var config = _context.siger_system_config.FirstOrDefault(q =>
                q.key == SystemConfigKey.MessageRepeatTime && q.status == (int) RowState.Valid);
            return (config != null ? config.value : "15").ToInt();
        }

        private List<siger_project_repair_report> GetRepairSpaceTime(int projectId, int machinelevel)
        {
            var spaceTimesList = _context.siger_project_repair_report
                .Where(t => t.projectid == projectId && t.status == (int) RowState.Valid &&
                            t.machinelevel == machinelevel).ToList();
            return spaceTimesList;
        }

        private int GetProjectLanguage(int projectId)
        {
            var languageType = _context.siger_project.FirstOrDefault(t => t.id == projectId);
            return languageType?.language ?? 0;
        }

        #endregion

        #region 获取消息通知配置数据，发送消息

        private void SendWeXinMessage(string title, string content, int time, int tomid, int projectid, string templeteId)
        {
            if (tomid == 0)
            {
                return;
            }

            var date = UnixTimeHelper.ConvertIntDateTime(time);

            var openid = GetUserOpenId(tomid, projectid);
            if (string.IsNullOrEmpty(openid))
            {
                return;
            }

            MessageBean msgcont = new MessageBean();

            ContBean prmBean = new ContBean
            {
                value = title,
                color = "#173177"
            };

            msgcont.firstPrm = prmBean;

            List<ContBean> datas = new List<ContBean>();
            prmBean = new ContBean
            {
                value = date,
                color = "#173177"
            };
            datas.Add(prmBean);

            prmBean = new ContBean
            {
                value = content,
                color = "#173177"
            };
            datas.Add(prmBean);

            msgcont.keywordsPrm = datas;

            prmBean = new ContBean
            {
                value = "",
                color = "#173177"
            };
            msgcont.remarkPrm = prmBean;

            WeChatPushHelper.sendMsg(openid, templeteId, msgcont);
        }

        private bool IsOnlie(int mid, int projectId, string key)
        {
            var intervalMinutes = 5;
            var config =
                _context.siger_system_config.FirstOrDefault(q => q.key == key && q.status == (int) RowState.Valid);
            if (config != null)
            {
                var interval = config.value.ToInt();
                if (interval > 0)
                {
                    intervalMinutes = interval;
                }
            }

            var entity = _context.siger_app_project_user.FirstOrDefault(q =>
                q.projectId == projectId && q.mid == mid && q.status == (int) RowState.Valid);
            if (entity != null)
            {
                if (entity.refresh_time != null)
                {
                    if (DateTime.Now.Subtract(entity.refresh_time.Value).TotalMinutes <= intervalMinutes)
                    {
                        return true;
                    }
                }

                return false;
            }

            return false;
        }

        private string GetUserAppKey(int mid, int projectId)
        {
            var entity = _context.siger_app_project_user.FirstOrDefault(q =>
                q.projectId == projectId && q.mid == mid && q.status == (int) RowState.Valid);
            if (entity != null)
            {
                return entity.appkey;
            }

            return string.Empty;
        }

        private string GetUserMobile(int mid, int projectId)
        {
            var entity = _context.siger_project_user.FirstOrDefault(q =>
                q.projectid == projectId && q.mid == mid && q.status == (int) RowState.Valid);
            if (entity != null)
            {
                return entity.mobile;
            }

            return string.Empty;
        }

        private string GetUserOpenId(int mid, int projectId)
        {
            var entity = _context.siger_app_project_user.FirstOrDefault(q =>
                q.projectId == projectId && q.mid == mid && q.status == (int)RowState.Valid);
            if (entity != null)
            {
                return entity.openid;
            }

            return string.Empty;
        }

        #endregion

        #region 获取推送列表

        private Dictionary<int, List<ResponsePushLevelUser>> GetReportPushAndSectionMidList(siger_project_repair repairInfo, int machineId, int time, int _projectId, int machinelevel)
        {
            var res = new Dictionary<int, List<ResponsePushLevelUser>>();
            var reportLevelMidList =
                GetReportLevelMidList(repairInfo, time, _projectId, machinelevel)
                    .Where(t => t.mid > 0).ToList();
            var workgroupUsermidList = GetWorkgroupUsermidList(repairInfo, machineId, time, _projectId);
            res.Add((int) AppPushType.PushAndSave, reportLevelMidList);
            res.Add((int) AppPushType.SaveNotPush, workgroupUsermidList);
            return res;
        }

        private List<ResponsePushLevelUser> GetWorkgroupUsermidList(siger_project_repair repairInfo, int machineid, int time, int projectId)
        {
            var midList = new List<ResponsePushLevelUser>
            {
               new ResponsePushLevelUser{mid=  repairInfo.mid },
                new ResponsePushLevelUser{mid=  repairInfo.takemid },
                 new ResponsePushLevelUser{mid=  repairInfo.signmid },
                  new ResponsePushLevelUser{mid=  repairInfo.completemid },
                   new ResponsePushLevelUser{mid=  repairInfo.checkmid },
            };
            var repairadd = _context.siger_project_repair_add_user.Where(t => t.repairid == repairInfo.id && t.status == (int)RowState.Valid).ToList();
            if (repairadd.Any())
            {
                foreach(var add in repairadd)
                {
                    if (midList.Exists(f => f.mid == add.mid))
                        continue;

                    midList.Add(new ResponsePushLevelUser { mid = add.mid });
                }
             //   midList.AddRange(repairadd.Select(t => t.mid).ToList());
            }

            var date = DateTime.Parse(UnixTimeHelper.ConvertIntDate(time));
            //var userMids = _context.siger_project_working_machine_set.Where(q => q.machine_id == machineid && q.project_id == projectId && q.status == (int)RowState.Valid).Select(q => q.user_mid)
            //    .Distinct().ToList();
            var machineRelation = _context.siger_project_working_relation_machine.FirstOrDefault(f => f.machine == machineid && f.projectid == projectId);
            if (machineRelation == null)
                return midList;
            var userMids = machineRelation.employsSplit;
            var cals = _context.siger_project_working_calendar.Where(q => userMids.Contains(q.user_mid) && q.status == (int)RowState.Valid
                                                                                     && q.working_group == machineRelation.workgroup_id && q.date == date).ToList();
            if (cals.Any())
            {
                var shiftids = cals.Select(m => m.shift_id).Distinct().ToList();
                var shifts = _context.siger_project_shift.Where(q => shiftids.Contains(q.id) && q.status == (int)RowState.Valid);
                var nowDate = UnixTimeHelper.GetUnixByDate(date.ToShortDateString());
                foreach (var calendar in cals)
                {
                    if (midList.Exists(e => e.mid == calendar.user_mid))
                        continue;

                    var shift = shifts.FirstOrDefault(q => q.id == calendar.shift_id);
                    if (shift == null)
                    {
                        continue;
                    }

                    //零点到零点的，全部都算
                    if (shift.start_time == 0 && shift.end_time == 0)
                    {
                        midList.Add(new ResponsePushLevelUser { mid = calendar.user_mid });
                    }
                    //在时间范围内的
                    else if (nowDate + shift.start_time <= time && nowDate + shift.end_time >= time)
                    {
                        midList.Add(new ResponsePushLevelUser { mid = calendar.user_mid });
                    }
                    //结束时间小于开始时间
                    else if (shift.end_time <= shift.start_time)
                    {
                        if (nowDate + shift.start_time <= time && nowDate + 86400 + shift.end_time >= time)
                        {
                            midList.Add(new ResponsePushLevelUser { mid = calendar.user_mid });
                        }
                    }
                }
            }

            return midList;
        }

        private List<ResponsePushLevelUser> GetReportLevelMidList(siger_project_repair repairInfo, int time, int _projectId, int machinelevel)
        {
            var midList = new List<ResponsePushLevelUser>();
            if (repairInfo.report_level > 0)
            {
                midList = ListLevelUser(_projectId, repairInfo.report_level, machinelevel).ToList();
                return midList;
            }

            var spaceTimesList = _context.siger_project_repair_report
                .Where(t => t.projectid == _projectId && t.status == (int)RowState.Valid && t.machinelevel == machinelevel).ToList();
            //获取上报等级
            var templevel = GetRepairReportLevel(repairInfo, time, spaceTimesList);
            if (templevel > 0)
            {
                midList = ListLevelUser(_projectId, templevel, machinelevel).ToList();
            }
            return midList;
        }

        private IEnumerable<ResponsePushLevelUser> ListLevelUser(int projectId, int level, int machinelevel)
        {
            var query = from l in _context.siger_project_repair_report_level
                        join u in _context.siger_project_user on l.usergroup_id.ToString() equals u.usergroupid
                        where l.project_id == projectId && l.level <= level && l.status == (int)RowState.Valid
                              && l.usergroup_id > 0 && l.machinelevel == machinelevel
                        select new ResponsePushLevelUser
                        {
                            level = l.level,
                            mid = u.mid
                        };
            return query;
            //var mids = new List<int>();
            //if (query.ToList().Any())
            //{
            //    mids = query.ToList().Select(t => t.mid).ToList();
            //}
            //return mids;
        }

        #endregion

        #region 获取异常上报等级

        private int GetRepairReportLevel(siger_project_repair repair, int time, List<siger_project_repair_report> spaceTimeArr)
        {
            int templevel = 0;
            if (repair != null)
            {
                if (spaceTimeArr.Any())
                {
                    var spaceTime4 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 3);
                    var spaceTime3 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 2);
                    var spaceTime2 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 1);
                    switch (repair.status)
                    {
                        case 1:
                            var difference = time - repair.createtime;
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 2:
                            var difference1 = time - repair.createtime;
                            var difference2 = repair.taketime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 3:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            var difference3 = repair.signtime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 4:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            difference3 = repair.signtime - repair.createtime;
                            var difference4 = repair.completetime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            difference = Math.Max(difference4, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 5:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            difference3 = repair.signtime - repair.createtime;
                            difference4 = repair.completetime - repair.createtime;
                            var difference5 = repair.checktime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            difference = Math.Max(difference4, difference);
                            difference = Math.Max(difference5, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                    }
                }
            }

            return templevel;
        }

        private int GetCompareTempLevel(int difference, siger_project_repair_report spaceTime4,
            siger_project_repair_report spaceTime3, siger_project_repair_report spaceTime2)
        {
            int templevel;
            if (spaceTime4 != null && difference > spaceTime4.space_time)
            {
                templevel = 4;
            }
            else if (spaceTime3 != null && difference > spaceTime3.space_time)
            {
                templevel = 3;
            }
            else if (spaceTime2 != null && difference > spaceTime2.space_time)
            {
                templevel = 2;
            }
            else
            {
                //此时该工单未超时
                templevel = 1;
            }

            return templevel;
        }

        #endregion

        #region 产线层级

        private siger_project_machine_attribution GetLevelMachineByMachineId(int machineId)
        {
            return _context.siger_project_machine_attribution.FirstOrDefault(t => t.machine == machineId && t.attribution == 1 && t.status == (int)RowState.Valid);
        }

        private IEnumerable<siger_project_level_section> GetSonLevelSections(int parentId, int projectid)
        {
            var query = from c in _context.siger_project_level_section
                        where c.parentid == parentId && c.projectid == projectid && c.status == (int)RowState.Valid
                        select c;

            return query.ToList().Concat(query.ToList().SelectMany(t => GetSonLevelSections(t.id, projectid)));
        }

        public string GetPositionByMachineId(int machineId, int _projectId, IEnumerable<siger_project_level_section> levelSections)
        {
            var names = new List<string>();
            //工位信息
            var attibution = _context.siger_project_machine_attribution.FirstOrDefault(q => q.machine == machineId && q.projectid == _projectId &&
                                                                                            q.status == (int)RowState.Valid);
            if (attibution == null)
            {
                return string.Empty;
            }

            var level = _context.siger_project_level_section.FirstOrDefault(q => q.id == attibution.station && q.projectid == _projectId && q.status == (int)RowState.Valid);
            if (level != null)
            {
                names.Add(level.title);
                var machine = _context.siger_project_machine.FirstOrDefault(q => q.id == machineId);
                if (machine != null)
                {
                    names.Add(machine.title);
                }
            }
            return string.Join('-', names);
        }

        public IEnumerable<siger_project_level_section> GetParentLevelSections(int id, int projectid, IEnumerable<siger_project_level_section> levelSections)
        {
            var query = from c in levelSections
                        where c.id == id && c.status == (int)RowState.Valid
                select c;

            return query.ToList().Concat(query.ToList().SelectMany(t => GetParentLevelSections(t.parentid, projectid, levelSections)));
        }

        #endregion

        public void Dispose()
        {
            _context?.Dispose();
        }
    }
}
