using Siger.DataSchedule.Infrastructure.Extend;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Repository.Data.Tpm;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.TpmRepository;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Response;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Siger.Schedule.TpmModule
{
    public class AutoSyncTpmPlan : IScheduleJob
    {
        AutoSyncTpmPlanHelper planHelper;
        public void PreInit(ScheduleContext context)
        {
            Logger.RegisterLogEngine(Module.Tpm);
            planHelper = new AutoSyncTpmPlanHelper();
        }

        public void Execute(ScheduleContext context)
        {
            planHelper.StartTask();
        }

       
        public void AfterExecute(ScheduleContext context)
        {
            
        }

       

        public void Undo()
        {
            
        }
    }

    public class AutoSyncTpmPlanHelper : IDisposable
    {
        private static AutoSyncTpmPlanHelper _helper;
        public static AutoSyncTpmPlanHelper Instance = _helper ?? (_helper = new AutoSyncTpmPlanHelper());

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

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

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

                var now = DateTime.Now;
                //每天的8:00执行
                if (now.Hour == 8 && now.Minute == 0)
                {
                    Execute();
                }
            }
        }

        private void Execute()
        {
            //try
            //{
            //    if (RedisCache.Client == null)
            //    {
            //        RedisCache.Instance.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($"AutoSyncTpmPlan DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                        continue;
                    }
                    ExcutePlanReportPushMessage(dbNameConfig.Pid);
                    ExcutePlanTaskPlan(dbNameConfig.Pid);
                    //ExcuteCheckTaskPlan(dbNameConfig.Pid);//每天早上八点推送微信端 有盘点任务需要执行
                }
                Dispose();
            }
        }

        public void ExcutePlanReportPushMessage(int projectId)
        {
            try
            {
                var time = UnixTimeHelper.GetTodayUnix();
                var configTime = GetConfigRepeatTime();
                PlanReportPlan(configTime, time, projectId);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoSyncTpmPlan Execute PlanRepair Timing Task failed" + e);
            }
        }

        public void ExcutePlanTaskPlan(int projectId)
        {
            try
            {
                var time = UnixTimeHelper.GetTodayUnix();
                PlanTaskPlan(time, projectId);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoSyncTpmPlan Execute PlanTaskPlan Timing Task failed" + e);
            }
        }

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

        #region 今天之前的未执行的计划 每天早上八点

        private void PlanReportPlan(int configRepeatTime, int todayTime, int _projectId)
        {
            var planTimes = GetTimeOutPlanList((int)PlanStatus.Normal, todayTime, _projectId);
            var tempList = new List<PlanTemp>();
            foreach (var planTime in planTimes)
            {
                var tempArr = new PlanTemp
                {
                    planid = planTime.planid,
                    plantimeid = planTime.timeid,
                    machineid = planTime.machineid,
                    instruction_mid = planTime.instruction_mid,
                    instruction_time = planTime.instruction_time,
                    mode = planTime.mode,
                    type = ConvertTypeByInstructionCycle(planTime.instruction_cycle),
                    information = planTime.information,
                };
                bool updateSuccess = false;
                var plantime = _context.siger_project_plan_time.FirstOrDefault(t => t.id == planTime.timeid);
                if (plantime != null)
                {
                    if (plantime.information == (int)PlanStatus.Overdue)
                    {
                        updateSuccess = true;
                    }
                    else
                    {
                        plantime.information = (int)PlanStatus.Overdue;
                        _context.siger_project_plan_time.Update(plantime);
                        if (_context.SaveChanges() > 0)
                        {
                            updateSuccess = true;
                        }
                    }
                }
                var level = GetPlanReportTimeOut(planTime.mode, todayTime, planTime.instruction_time,
                    planTime.instruction_cycle, configRepeatTime, _projectId);
                if (level > 0 && updateSuccess)
                {
                    tempArr.level = level;
                    tempList.Add(tempArr);
                }
            }
            var time = UnixTimeHelper.GetNow();
            var isTranslate = GetProjectLanguage(_projectId) == (int)LanguageType.EN;
            var translateHelper = new TranslateHelper(isTranslate);
            tempList = tempList.GroupBy(t => t.machineid).Select(t => t.FirstOrDefault()).ToList();
            var levelSections = GetSonLevelSections(0, _projectId);
            foreach (var plan in tempList)
            {
                var title = translateHelper.GetTranslateText(TranslateEnEnum.AbnormalReport);
                var location = string.Join("-", GetPositionByMachineId(plan.machineid, _projectId, levelSections));
                var content = "【" + location + "】 " +
                              translateHelper.GetTranslateText(TranslateEnEnum
                                  .NoteSomeMaintenanceProjectsNotImplementedScheduled);
                var paras = new Dictionary<string, string>
                {
                    { "location", location }
                };
                var planMsg = new siger_app_project_message
                {
                    repairid = plan.machineid,
                    projectid = _projectId,
                    type = (int)RepairOrPlanStatus.Plan,
                    title = title,
                    status = plan.information,
                    content = content
                };
                var midList = GetMidList(plan.machineid, time, plan.level, plan.mode, _projectId);
                PushPlanMessage(planMsg, midList, _projectId, isTranslate, paras);
            }
        }

        private IEnumerable<PlanAppItemList> GetTimeOutPlanList(int information, int todayTime, int projectId)
        {
            var queryList = (from t in _context.siger_project_plan
                             join pitem in _context.siger_project_plan_item on t.itemid equals pitem.id
                             join ptime in _context.siger_project_plan_time on t.id equals ptime.planid
                             join machine in _context.siger_project_machine on t.machineid equals machine.id
                             where t.projectid == projectId && t.status == (int)RowState.Valid && pitem.projectid == projectId &&
                                   pitem.status == (int)RowState.Valid
                                   && ptime.status == (int)RowState.Valid && ptime.information > information
                                   && ptime.instruction_time < todayTime
                             select new PlanAppItemList
                             {
                                 id = t.id,
                                 type = pitem.type,
                                 typeid = pitem.typeid,
                                 machineid = pitem.machineid,
                                 content = pitem.content,
                                 value_type = pitem.value_type,
                                 mode = pitem.mode,
                                 unit = pitem.unit,
                                 up_limit = pitem.up_limit,
                                 lower_limit = pitem.lower_limit,
                                 severity_level = pitem.severity_level,
                                 failure_mode = pitem.failure_mode,
                                 work_instruction_url = pitem.work_instruction_url,
                                 result_demo_url = pitem.result_demo_url,
                                 standard_time = pitem.standard_time,
                                 instruction_cycle = t.instruction_cycle,
                                 create_mid = pitem.create_mid,
                                 create_time = pitem.create_time,
                                 work_instruction_name = pitem.work_instruction_name,
                                 planid = t.id,
                                 machinetitle = machine.title,
                                 first_instruction_time = UnixTimeHelper.ConvertStringDateTime(t.first_instruction_time)
                                     .ToString(ParameterConstant.DateFormat),
                                 instruction_mid = ptime.instruction_mid.ToStr(),
                                 remark = pitem.remark,
                                 date_rang = t.date_rang,
                                 starttime = t.starttime,
                                 endtime = t.endtime,
                                 instruction_mid_str = t.instruction_mid,
                                 instruction_time = ptime.instruction_time,
                                 information = ptime.information,
                                 timeid = ptime.id
                             }).GroupBy(t => t.timeid).Select(t => t.FirstOrDefault()).ToList();

            return queryList;
        }

        private int ConvertTypeByInstructionCycle(int instructionCycle)
        {
            int type;
            switch (instructionCycle)
            {
                case 1:
                    type = 1;
                    break;
                case 7:
                    type = 2;
                    break;
                case 15:
                    type = 3;
                    break;
                case 30:
                    type = 4;
                    break;
                case 60:
                    type = 5;
                    break;
                case 120:
                    type = 6;
                    break;
                case 180:
                    type = 7;
                    break;
                case 360:
                    type = 8;
                    break;
                default:
                    type = 0;
                    break;
            }

            return type;
        }

        #endregion

        #region 今日需要维护的设备数量 每天早上八点

        private void PlanTaskPlan(int todayTime, int _projectId)
        {
            var isTranslate = GetProjectLanguage(_projectId) == (int)LanguageType.EN;
            var translateHelper = new TranslateHelper(isTranslate);
            var plantasks = ListPlanTodayTask(todayTime, _projectId);
            plantasks = plantasks.Where(t => t.instruction_mid > 0).ToList();
            foreach (var task in plantasks)
            {
                var title = translateHelper.GetTranslateText(TranslateEnEnum.PlannedMaintenance);
                var content = translateHelper.GetTranslateText(TranslateEnEnum.Today) + task.count +
                              translateHelper.GetTranslateText(TranslateEnEnum.EquipmentPlannedMaintenanceTask);
                var paras = new Dictionary<string, string>
                {
                    {"count", task.count.ToString()}
                };
                PushMidsMessage(new List<int> { task.instruction_mid }, 0, 0, title, content, _projectId, isTranslate, paras);
            }
        }

        private List<GetListPlanTodayTask> ListPlanTodayTask(int todayTime, int _projectId)
        {
            var planTimes = _context.siger_project_plan_time.Where(t =>
                t.projectid == _projectId && t.status == (int)RowState.Valid
                                          && t.instruction_time >= todayTime && t.instruction_time < todayTime + 86400 && t.information != (int)PlanStatus.Normal).ToList();
            var groupbymid = planTimes.GroupBy(t => t.instruction_mid).ToList();
            var res = new List<GetListPlanTodayTask>();
            foreach (var mid in groupbymid)
            {
                if (mid.Any())
                {
                    var machines = new List<PlanTodayTask>();
                    foreach (var plantime in mid)
                    {
                        var plan = _context.siger_project_plan.FirstOrDefault(t => t.id == plantime.planid);
                        if (plan != null)
                        {
                            machines.Add(new PlanTodayTask
                            {
                                machineid = plan.machineid,
                            });
                        }
                    }
                    machines = machines.GroupBy(t => t.machineid).Select(t => t.FirstOrDefault()).ToList();
                    res.Add(new GetListPlanTodayTask
                    {
                        instruction_mid = mid.First().instruction_mid,
                        count = machines.Count,
                        planTodayTasks = machines
                    });
                }
            }
            return res;
        }

        #endregion

        #region 有盘点任务需要执行 每天早上八点 微信推送

        public void CheckTaskPlan(int time, int _projectId)
        {
            var checkTodayTask = ListCheckTodayTask(time, _projectId);
            foreach (var task in checkTodayTask)
            {
                var sectionStationStr = GetLevelSectionBySectionId(task.sectionid, _projectId);
                var checktask = new CheckTaskMessage
                {
                    title = sectionStationStr,
                    mid = task.mid,
                    date = UnixTimeHelper.ConvertIntDate(task.end_time)
                };
                SendPlanTaskPlan(checktask, _projectId);
            }
        }

        private void SendPlanTaskPlan(CheckTaskMessage checktask, int projectid)
        {
            var content = checktask.title ?? "";
            var date = checktask.date ?? "";
            if (checktask.mid == 0)
            {
                return;
            }

            var username = "";
            var user = GetUserInfo(checktask.mid);
            if (user != null)
            {
                username = user.name;
            }

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

            var title = username + ",有盘点任务需要你完成!";
            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, WeChatPushHelper.temleteIdMdp, msgcont);
        }

        private List<GetListCheckTodayTask> ListCheckTodayTask(int time, int _projectId)
        {
            var list = GetProjectChecksByTime(time, _projectId);
            var res = new List<GetListCheckTodayTask>();
            foreach (var checkmode in list)
            {
                var task = new GetListCheckTodayTask();
                res.Add(new GetListCheckTodayTask
                {
                    check_code = checkmode.check_code,
                    mid = checkmode.duty_mid,
                    end_time = checkmode.end_time,
                    sectionid = checkmode.sectionid
                });
                res.Add(task);
            }
            return res;
        }

        public IEnumerable<siger_project_check> GetProjectChecksByTime(int time, int projectId)
        {
            var query = _context.siger_project_check.Where(t => t.create_time < time && t.end_time < time
                                                                                     && t.status ==
                                                                                     (int)RowState.Valid &&
                                                                                     t.projectid == projectId);
            return query;
        }

        #endregion

        #region 推送消息，保存消息

        /// <summary>
        /// 判断异常上报用户,然后推送
        /// </summary>
        private void PushPlanMessage(siger_app_project_message planMsg, Dictionary<int, List<int>> midList,
            int _projectId, bool isTranslate, Dictionary<string, string> paras)
        {
            var config = GetAppProjectConfig(_projectId);
            if (config != null)
            {
                var pushmessage =
                    new MessagePushHelper(config.appkey, config.appsecret, config.signid, config.issendSMS);
                var sectionMidList = midList[(int)AppPushType.SaveNotPush];
                var pushMidList = midList[(int)AppPushType.PushAndSave];
                foreach (var mid in sectionMidList)
                {
                    var time = UnixTimeHelper.GetNow();
                    var model = new siger_app_project_message
                    {
                        repairid = planMsg.repairid,
                        projectid = _projectId,
                        type = planMsg.type,
                        title = planMsg.title,
                        status = planMsg.status,
                        content = planMsg.content,
                        tomid = mid,
                        create_time = time
                    };
                    _context.siger_app_project_message.Add(model);
                    _context.SaveChanges();
                    var mute = _context.siger_app_mute.FirstOrDefault(t =>
                        t.projectid == _projectId && t.status == 0 && t.repairid == 0 && t.mid == mid);
                    if (pushMidList.Contains(mid) && mute == null)
                    {
                        var isOnline = IsOnlie(mid, _projectId, SystemConfigKey.AppUserOnlineInterval);
                        var toUserKey = GetUserAppKey(mid, _projectId);
                        var mobile = GetUserMobile(mid, _projectId);
                        var templateId = SMSTemplateConst.PlanReportPlan;
                        if (isTranslate)
                        {
                            templateId = TemplateHelper.GetSmsEnTemplateId(SMSTemplateConst.PlanReportPlan);
                        }
                        if (templateId > 0)
                        {
                            pushmessage.PushMessage(model, isOnline, toUserKey, mobile, templateId, paras);
                            SendWeXinMessage(model.title, model.content, time, mid, _projectId, TemplateHelper.GetWxTempleteId(isTranslate));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 直接推送不判断上报层级
        /// </summary>
        private void PushMidsMessage(List<int> midList, int repairId, int planStatus, string title, string content,
            int _projectId, bool isTranslate, Dictionary<string, string> paras)
        {
            var config = GetAppProjectConfig(_projectId);
            if (config != null)
            {
                var pushmessage =
                    new MessagePushHelper(config.appkey, config.appsecret, config.signid, config.issendSMS);
                foreach (var mid in midList)
                {
                    var time = UnixTimeHelper.GetNow();
                    var planMsg = new siger_app_project_message
                    {
                        repairid = repairId,
                        projectid = _projectId,
                        type = (int)RepairOrPlanStatus.Plan,
                        title = title,
                        status = planStatus,
                        content = content,
                        tomid = mid,
                        create_time = time
                    };
                    _context.siger_app_project_message.Add(planMsg);
                    _context.SaveChanges();
                    var isOnline = IsOnlie(planMsg.tomid, planMsg.projectid, SystemConfigKey.AppUserOnlineInterval);
                    var toUserKey = GetUserAppKey(planMsg.tomid, planMsg.projectid);
                    var mobile = GetUserMobile(planMsg.tomid, planMsg.projectid);
                    var mute = _context.siger_app_mute.FirstOrDefault(t =>
                        t.projectid == _projectId && t.status == 0 && t.repairid == 0 && t.mid == mid);
                    if (mute == null)
                    {
                        var templateId = SMSTemplateConst.PlanTaskPlan;
                        if (isTranslate)
                        {
                            templateId = TemplateHelper.GetSmsEnTemplateId(SMSTemplateConst.PlanTaskPlan);
                        }
                        if (templateId > 0)
                        {
                            pushmessage.PushMessage(planMsg, isOnline, toUserKey, mobile, templateId, paras);
                            SendWeXinMessage(title, content, time, planMsg.tomid, _projectId, TemplateHelper.GetWxTempleteId(isTranslate));
                        }
                    }
                }
            }
        }

        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<int>> GetMidList(int machineid, int time, int level, int mode, int _projectId)
        {
            var res = new Dictionary<int, List<int>>
            {
                {
                    (int) AppPushType.PushAndSave,
                    GetReportMidList(level, mode, _projectId).Where(t => t > 0).Distinct().ToList()
                },
                {
                    (int) AppPushType.SaveNotPush,
                    GetSectionMidList(machineid, time, _projectId).Where(t => t > 0).Distinct().ToList()
                }
            };
            return res;
        }

        private List<int> GetSectionMidList(int machineid, int time, int _projectId)
        {
            //根据设备id获取所有与之相关的人的mid数组                        
            var sectionIdArr = new List<int>();
            var section = GetLevelMachineByMachineId(machineid);
            if (section != null)
            {
                sectionIdArr.Add(section.station);
            }
            var sectionMidArr = new List<int>();
            if (sectionIdArr.Any())
            {
                sectionMidArr = ListAllMidArrBySectionIDArr(sectionIdArr, time).ToList();
            }

            return sectionMidArr;
        }

        private List<int> GetReportMidList(int level, int mode, int _projectId)
        {
            var reportMidArr = ListLevelUser(_projectId, level, mode).ToList();
            return reportMidArr;
        }

        private IEnumerable<int> ListLevelUser(int projectId, int level, int mode)
        {
            var query = from l in _context.siger_project_plan_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.mode == mode
                        select u;
            var mids = new List<int>();
            if (query.ToList().Any())
            {
                mids = query.ToList().Select(t => t.mid).ToList();
            }
            return mids;
        }

        private IEnumerable<int> ListAllMidArrBySectionIDArr(IEnumerable<int> sectionIds, int time)
        {
            var date = UnixTimeHelper.ConvertIntDateTime(time).ToDateTime();
            int this_time = date.Hour * 3600 + date.Minute * 60 + date.Millisecond;
            var rowstate = (int)RowState.Valid;
            var query = from sta in _context.siger_project_station
                        join pug in _context.siger_project_user_group on sta.groupid equals pug.groupid
                        join sh in _context.siger_project_shift on sta.shiftid equals sh.id
                        where sh.status == rowstate && sectionIds.Contains(sta.sectionid) && pug.mid > 0 && sta.status == rowstate
                              && (sh.start_time < sh.end_time
                                  ? (sh.start_time <= this_time && this_time <= sh.end_time)
                                  : (sh.start_time <= this_time || this_time <= sh.end_time))
                              && time >= sta.starttime && time <= sta.endtime
                        select pug;
            var mids = new List<int>();
            if (query.ToList().Any())
            {
                mids = query.ToList().Select(t => t.mid).ToList();
            }
            return mids;
        }

        #endregion

        #region 获取超时异常的计划维护

        private int GetPlanReportTimeOut(int itemMode, int time, int instructionTime, int instructionCycle,
            int configRepeatTime, int _projectId)
        {
            var level = 0;
            var spaceTimeArr = _context.siger_project_plan_report.Where(t =>
                    t.projectid == _projectId && t.status == (int)RowState.Valid && t.mode == itemMode)
                .ToList();
            var days = (float)(time - instructionTime) / 86400;
            if (spaceTimeArr.Any())
            {
                switch (instructionCycle)
                {
                    case 1:
                        level = GetReportLevel(spaceTimeArr, 1, days, configRepeatTime);
                        break;
                    case 7:
                        level = GetReportLevel(spaceTimeArr, 2, days, configRepeatTime);
                        break;
                    case 14:
                        level = GetReportLevel(spaceTimeArr, 3, days, configRepeatTime);
                        break;
                    case 30:
                        level = GetReportLevel(spaceTimeArr, 4, days, configRepeatTime);
                        break;
                    case 60:
                        level = GetReportLevel(spaceTimeArr, 5, days, configRepeatTime);
                        break;
                    case 90:
                        level = GetReportLevel(spaceTimeArr, 6, days, configRepeatTime);
                        break;
                    case 180:
                        level = GetReportLevel(spaceTimeArr, 7, days, configRepeatTime);
                        break;
                    case 360:
                        level = GetReportLevel(spaceTimeArr, 8, days, configRepeatTime);
                        break;
                }
            }

            return level;
        }

        private int GetReportLevel(List<siger_project_plan_report> spaceTimeArr, int type, float difference, int configRepeatTime)
        {
            var spaceTime1 = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 1);
            if (spaceTime1 != null)
            {
                var spacetime = spaceTime1.space_time;
                if (difference % configRepeatTime < 1 && difference < spacetime && difference >= configRepeatTime)
                {
                    return 1;
                }
            }
            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 + spaceTime2.space_time + spaceTime1.space_time;
                var spacetime2 = spaceTime2.space_time + spaceTime1.space_time;
                var spacetime1 = spaceTime1.space_time;
                var diff3 = difference - spacetime3;
                var diff2 = difference - spacetime2;
                var diff1 = difference - spacetime1;
                if (diff3 >= 0 && difference % spacetime3 < 1 && diff3 < 1)
                {
                    return 4;
                }
                else if (diff3 >= 0 && diff3 % configRepeatTime < 1 && diff3 >= configRepeatTime)
                {
                    return 4;
                }
                else if (diff2 >= 0 && diff3 < 0 && difference % spacetime2 < 1 && diff2 < 1)
                {
                    return 3;
                }
                else if (diff2 >= 0 && diff3 < 0 && diff2 % configRepeatTime < 1 && diff2 >= configRepeatTime)
                {
                    return 3;
                }
                else if (diff1 >= 0 && diff2 < 0 && difference % spacetime1 < 1 && diff1 < 1)
                {
                    return 2;
                }
                else if (diff1 >= 0 && diff2 < 0 && diff1 % configRepeatTime < 1 && diff1 >= configRepeatTime)
                {
                    return 2;
                }
            }
            return 0;
        }

        private int GetPlanReportTimeOutByType(List<siger_project_plan_report> spaceTimeArr, int type, float days,
            int repeatTime)
        {
            int level = 0;
            var spaceTime = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 3);
            if (spaceTime != null && days > spaceTime.space_time)
            {
                if (CompareTwo(days, spaceTime.space_time, repeatTime))
                {
                    level = 4;
                }
            }
            else
            {
                spaceTime = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 2);
                if (spaceTime != null && days > spaceTime.space_time)
                {
                    if (CompareTwo(days, spaceTime.space_time, repeatTime))
                    {
                        level = 3;
                    }
                }
                else
                {
                    spaceTime = spaceTimeArr.FirstOrDefault(t => t.type == type && t.start_level == 1);
                    if (spaceTime != null && days > spaceTime.space_time)
                    {
                        if (CompareTwo(days, spaceTime.space_time, repeatTime))
                        {
                            level = 2;
                        }
                    }
                }
            }

            return level;
        }

        private bool CompareTwo(float difference, int spaceTime, int repeatTime)
        {
            var diff = (difference - spaceTime) % repeatTime;
            return diff < 1;
        }

        #endregion

        #region 获取配置数据

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

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

        public siger_project_user GetUserInfo(int mid)
        {
            return _context.siger_project_user.FirstOrDefault(t => t.mid == mid);
        }

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

        #endregion

        #region 产线结构

        private List<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 names;
            }

            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 names;
        }

        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 GetLevelSectionBySectionId(int sectionId, int projectId)
        {
            var section = _context.siger_project_level_section.FirstOrDefault(t => t.id == sectionId && t.status == (int)RowState.Valid && t.projectid == projectId);
            return section != null ? section.title : "";
        }

        #endregion

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