using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.EntityFrameworkCore;
using NPOI.SS.Formula.Functions;
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.Dapper;
using Siger.Middlelayer.Dapper.ResultData;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Data.Tpm;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.TpmRepository;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Response;
using Siger.Middlelayer.Utility.Helpers;

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

        private static ApiTpmDbContext _context;
        private static ApiConfigDbContext _cfgContext;
        public AutoAndonPushHelper()
        {
            _context = new ApiTpmDbContext();
            _cfgContext = new ApiConfigDbContext();
        }

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

        private void Process()
        {
            while (true)
            {
               

                Execute();

                Thread.Sleep(1000 * 60 * 1); // 1分钟
            }
        }

        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($"AutoAndonPush DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                        continue;
                    }
                    if(dbNameConfig.Pid==0)
                    {
                        continue;
                    }
                    //if (dbNameConfig.Pid != 999) //test
                    //{
                    //    continue;
                    //}
                    ExcuteAndontPushMessage(dbNameConfig.Pid);
                    AutoAndonTrigger(dbNameConfig.Pid, dbNameConfig.Cid);
                    AutoPlanAndon(dbNameConfig.Pid, dbNameConfig.Cid);
                    AbnormalSyn(dbNameConfig.Cid, dbNameConfig.Pid);
                }
                Dispose();
            }
        }
        /// <summary>
        /// message push
        /// </summary>
        /// <param name="projectid"></param>
        public void ExcuteAndontPushMessage(int projectid)
        {
            try
            {
                AndonPlan(projectid);
            }
            catch (Exception e)
            {
                Logger.WriteLineError("AutoAndonPush Execute AndontPush Task failed" + e);
            }
        }


        private void AndonPlan(int projectid)
        {
            var executeTime = 60;//脚本执行时间
            var nowtime = UnixTimeHelper.GetNow();
            var messages = new List<siger_app_project_message>();
            //获取推送计划
            var infoData = _context.siger_andon_info.Where(f => f.status != (int)RowState.Invalid && f.projectid == projectid && f.cruent_level<6).ToList();
            infoData = infoData.Where(f => f.status == (int)AndonState.WaitHandle
              || f.status == (int)AndonState.Handling || f.status == (int)AndonState.Complete).ToList();
           
            //获取推送人
            foreach (var item in infoData)
            {
                long time = 0;
                var type = 0;//流程
                var title = string.Empty;
                var content = string.Empty;
                switch ((AndonState)item.status)
                {
                    case AndonState.WaitHandle:
                        time = item.create_time;
                        type = 1;
                        break;
                    case AndonState.Handling:
                        time = item.handle_time;
                        type = 2;
                        break;
                    case AndonState.Complete:
                        time = item.complete_time;
                        type = 3;
                        break;
                    default:
                        return;
                }
                var andonProcess = _context.siger_andon_process.FirstOrDefault(f => f.projectid == projectid && f.status == (int)RowState.Valid && f.code.Equals(item.process_code));
                if (andonProcess == null)
                {
                    Logger.WriteLineInfo($"设备：{item.machine}安灯消息推送编号：{item.process_code}流程：{type}当前等级{item.cruent_level}未找推送流程！");
                    continue;
                }
                // Logger.WriteLineInfo($"{item.remark} Mid {item.creator }设备：{item.machine}推送编号：{item.process_code}流程：{type}当前等级{item.cruent_level}");

                title = EnumHelper.GetEnumDesc((AndonState)item.status);
                var station = _context.siger_project_machine_attribution.FirstOrDefault(f => f.projectid == projectid && f.status != 0 && f.machine == item.machine)?.station ?? 0;
                var sectionData = GetLevelParent(station, projectid).OrderBy(o => o.id).TakeLast(2).Select(s => s.title).ToList();
                content = "【安灯消息通知】 设备名称：";
                content += string.Join('-', sectionData) + "-";
                content += _context.siger_project_machine.FirstOrDefault(f => f.id == item.machine)?.title ?? "";
                content += "-安灯类型：";
                var error = _context.siger_andon_expection_type.FirstOrDefault(f => f.projectid == projectid && f.status != 0 && f.id == item.expection_type);
                if (error != null)
                {
                    if (error.level == 3)
                    {
                        content += _context.siger_andon_expection_type.FirstOrDefault(f => f.projectid == projectid && f.status != 0 && f.id == error.parent)?.name;
                    }
                    else
                    {
                        content += error.name;
                    }
                }
                content += $"-{(nowtime - time) / 60}分钟";
                content += $"{EnumHelper.GetEnumDesc((AndonState)item.status)}";
                //execute cycle check
                var cyclePushTime = (nowtime - time) % (andonProcess.repeattime * 60);
                if (cyclePushTime < executeTime)
                {
                    var uids = GetWorkingStaff(item.process_code, item.cruent_level, item.machine, projectid);
                    foreach (var uid in uids)
                    {
                        messages.Add(new siger_app_project_message
                        {
                            tomid = uid,
                            title = title,
                            content = content,
                            repairid = item.machine,
                            create_time = nowtime,
                            type = 1,
                            //(int)RepairOrPlanStatus.Andon,
                            projectid = projectid,
                        });
                    }
                }
                //goto next level
                var planData = _context.siger_project_plan_report.FirstOrDefault(f => f.type.Equals(type) && f.process_code.Equals(item.process_code)
                && f.start_level.Equals(item.cruent_level) && f.status == (int)RowState.Valid && f.mode == 0);
                if (planData != null)
                {
                    time += planData.space_time * 60;
                    //if (time + executeTime <= nowtime && time >= nowtime)
                    if (nowtime >= time)
                    {
                        var uids = GetWorkingStaff(item.process_code, item.cruent_level, item.machine, projectid);
                        foreach (var uid in uids)
                        {
                            messages.Add(new siger_app_project_message
                            {
                                tomid = uid,
                                title = title,
                                content = content,
                                repairid = item.machine,
                                create_time = nowtime,
                                type = 1,
                                //(int)RepairOrPlanStatus.Andon,
                                projectid = projectid,
                            });
                        }
                        //level+1
                        item.cruent_level += 1;
                        _context.Update(item);
                        //insert detail
                        var userModel = _context.siger_project_user.Where(f => f.projectid.Equals(projectid) && f.status == (int)RowState.Valid && uids.Contains(f.mid)).Select(s => s.name).ToArray();
                        var detailModel = new siger_andon_info_detail
                        {
                            andon_id = item.id,
                            createtime = nowtime,
                            level = item.cruent_level,
                            projectid = projectid,
                            status = (int)AndonState.MessagePush,
                            user = string.Join(',', userModel),
                        };
                        _context.Add(detailModel);
                    }
                    _context.SaveChanges();
                }
            }
            if (!messages.Any())
            {
                return;
            }
            //推送信息
            PushMidsMessage(messages, projectid);
        }
        /// <summary>
        /// 获取当班员工
        /// </summary>
        /// <param name="processCode"></param>
        /// <param name="level"></param>
        /// <param name="machine"></param>
        /// <param name="pid"></param>
        /// <returns></returns>
        private List<int> GetWorkingStaff(string processCode, int level, int machine, int pid)
        {
            var ret = new List<int>();
            //获取部门信息
            var usergroupids = _context.siger_project_plan_report_level.Where(f => f.status == (int)RowState.Valid && f.process_code.Equals(processCode)
            && f.level.Equals(level)).Select(s => s.usergroup_id).ToList();
            if (!usergroupids.Any())
            {
                return ret;
            }
            var userList = _context.siger_project_user.Where(f => usergroupids.Contains(f.usergroupid.ToInt()));
            var sectionIds= userList.Select(s => s.sectionid).ToList();
            var sectionUser = userList.Select(s => s.mid).ToList();
            var machienRelation = _context.siger_project_working_relation_machine.FirstOrDefault(f => f.machine == machine && sectionIds.Contains(f.section));
            if (machienRelation == null)
                return ret;
            //获取部门 负责该设备对应的人员
            var nowDate = UnixTimeHelper.GetUnixByDate(DateTime.Now.ToShortDateString());
            var time = UnixTimeHelper.GetNow();
            var validateUser = sectionUser.Intersect(machienRelation.employsSplit).ToList();
            var workingCalendar = _context.siger_project_working_calendar.Where(f => f.project_id==pid && f.working_group == machienRelation.workgroup_id && f.date==DateTime.Now.Date && validateUser.Contains(f.user_mid));
            foreach (var cal in workingCalendar)
            {
                var shift = _context.siger_project_shift.First(f => f.id==cal.shift_id && f.projectid== pid && f.status == (int)RowState.Valid);
                if (shift != null)
                {
                    //零点到零点的，全部都算
                    if (shift.start_time == 0 && shift.end_time == 0)
                    {
                        ret.Add(cal.user_mid);
                    }
                    //在时间范围内的
                    else if (nowDate + shift.start_time <= time && nowDate + shift.end_time >= time)
                    {
                        ret.Add(cal.user_mid);
                    }
                    //结束时间小于开始时间
                    else if (shift.end_time <= shift.start_time)
                    {
                        if (nowDate + shift.start_time <= time)
                        {
                            ret.Add(cal.user_mid);
                        }
                    }
                }
            }
            //foreach (var user in userList)
            //{
            //    var groupData = _context.siger_project_usergroup.FirstOrDefault(f => f.id.Equals(user.usergroupid.ToInt()) && f.status == (int)RowState.Valid && f.projectid.Equals(pid));
            //    if (groupData == null)
            //    {
            //        continue;
            //    }
            //    var workingGroupData = _context.siger_project_working_group.Where(f => f.status == (int)RowState.Valid && f.project_id.Equals(pid)
            //                                                                             && f.section_id.Equals(groupData.sectionid) && f.start_date <= DateTime.Now);
            //    if (!workingGroupData.Any())
            //    {
            //        Logger.WriteLineInfo($"groupid:{groupData.parentid}没有维护班组计划！");
            //        continue;
            //    }
            //    foreach (var data in workingGroupData)
            //    {
            //        //检查用户是否在当前工作组
            //        if (data.user_mids.Split(',').ToList().Contains(user.mid.ToStr()))
            //        {
            //            //检查当前用户是否分配该设备(此处不是mahcineid集合)
            //            var stationList = _context.siger_project_working_machine_set.Where(f => f.status == (int)RowState.Valid && f.user_mid.Equals(user.mid) && f.workinggroup_id.Equals(data.id)).Select(s => s.machine_id).ToList();
            //            var machineids = _context.siger_project_machine_attribution.Where(f => f.attribution == 1 && f.projectid == pid && stationList.Contains(f.station)).Select(s => s.machine).Distinct().ToList();


            //            if (machineids.Contains(machine))
            //            {
            //                //检查是否当班
            //                if (CheckIsOnShift(data))
            //                {
            //                    ret.Add(user.mid);
            //                }
            //            }
            //        }
            //    }
            //}

            //检查安灯签到信息
            var handlers = _context.siger_andon_info.Where(f => f.status == (int)AndonState.Handling && f.projectid == pid).Select(s => s.handler).ToList();
            foreach (var handler in handlers)
            {
                if (ret.Any(f => f == handler))
                {
                    ret.Remove(handler);
                }
            }
            return ret;
        }
        /// <summary>
        /// 检查是否当班（待测试）
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        private bool CheckIsOnShift(siger_project_working_group data)
        {
            var nowtime = UnixTimeHelper.GetUnixTime(DateTime.Now.ToString("HH:mm"));
            var shifts = data.shift_ids.Split(',');
            foreach (var shift in shifts)
            {
                var model = _context.siger_project_shift.First(f => f.id.Equals(shift.ToInt()));
                if (nowtime >= model.start_time && nowtime <= model.end_time)
                {
                    return true;
                }
            }
            return false;
        }

        #region 推送消息，保存消息
        /// <summary>
        /// 直接推送不判断上报层级
        /// </summary>
        private void PushMidsMessage(List<siger_app_project_message> messageList, int projectid, bool isTranslate = false)
        {
            var config = _cfgContext.siger_app_project_config.FirstOrDefault(q =>
                q.projectId == projectid && q.status == (int)RowState.Valid);
            if (config != null)
            {
                var pushmessage = new MessageJPushHelper(config.appkey, config.appsecret, config.signid, config.issendSMS);
                //new MessagePushHelper(config.appkey, config.appsecret, config.signid, config.issendSMS);
                foreach (var message in messageList)
                {
                    _cfgContext.siger_app_project_message.Add(message);
                    _cfgContext.SaveChanges();
                    var isOnline = IsOnlie(message.tomid, message.projectid, SystemConfigKey.AppUserOnlineInterval);
                    var toUserKey = GetUserAppKey(message.tomid, message.projectid);
                    var mobile = GetUserMobile(message.tomid, message.projectid);
                    var mute = _cfgContext.siger_app_mute.FirstOrDefault(t =>
                        t.projectid == projectid && t.status == 0 && t.repairid == 0 && t.mid == message.tomid);
                    if (mute == null)
                    {
                        var paras = new Dictionary<string, string>
                        {
                            { "location",  ""},
                        };
                        var msg = Mapper<siger_app_project_message, PushMessage>.Map(message);
                        var ret = pushmessage.PushMessage(msg, isOnline, toUserKey, mobile, 1, paras);
                        if (ret != PushMessageResult.SendSuccessful)
                        {
                            //Logger.WriteLineInfo($"消息：{message.content}推送失败！");
                            continue;
                        }
                        //SendWeXinMessage(message.title, message.content, message.create_time, message.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
        /// <summary>
        /// 安灯计划性触发
        /// </summary>
        /// <param name="projectid"></param>
        /// <param name="companyid"></param>
        private void AutoPlanAndon(int projectid, int companyid)
        {
            var plans = _context.siger_andon_plan.Where(f => f.projectid == projectid && f.status != 0).ToList();
            var adminuser = _context.siger_user.Where(f => f.type == (int)UserType.Admin).Select(s => s.id).ToList();
            var projectuser = _context.siger_project_user.FirstOrDefault(f => adminuser.Contains(f.mid) && f.projectid == projectid);
            var now = UnixTimeHelper.GetNow();
            var locationAlarm = new LocationAlarmRepository(companyid, projectid);
            var locationYield = new LocationYieldRepository(companyid, projectid);
            foreach (var plan in plans)
            {
                var remark = $"系统计划触发-{plan.content}";
                var starttime = UnixTimeHelper.GetTodayUnix() + plan.start;
                var endtime = UnixTimeHelper.GetTodayUnix() + plan.end;
                var info = _context.siger_andon_info.Where(f => f.projectid == projectid && f.status != 0 && f.status != (int)AndonState.CancleAndon && f.expection_type == plan.expectionid && f.machine == plan.machine).ToList();
                //未处理
                if (info.Any(f => f.status < (int)AndonState.Approve))
                {
                    continue;
                }
                //是否存在andon
                if (info.Any())
                {
                    var maxtime = info.Max(m => m.approve_time);
                    if (maxtime > starttime)
                    {
                        continue;
                    }
                }
                //时间不达标
                if (now < starttime || now > endtime)
                {
                    continue;
                }
                //expection
                var expection = _context.siger_andon_expection_type.FirstOrDefault(f => f.id == plan.expectionid);
                if (expection == null)
                {
                    continue;
                }
                //machine
                var machine = _context.siger_project_machine_attribution.FirstOrDefault(f => f.machine == plan.machine && f.status != 0);
                //status
                var status = (int)AndonState.Recovery;
                //insert info
                var andondata = new siger_andon_info
                {
                    approve_time = endtime,
                    complete_time = endtime,
                    handle_time = starttime,
                    create_time = starttime,
                    creator = projectuser.mid,
                    handler = projectuser.mid,
                    process_code = expection.process_code ?? "",
                    expection_type = expection.id,
                    machine = machine.machine,
                    station = machine.station,
                    work_order = WorkOrderGenerator(projectid),
                    remark = remark,
                    projectid = projectid,
                    status = status,
                };
                _context.siger_andon_info.Add(andondata);
                //insert detail
                _context.siger_andon_info_detail.Add(new siger_andon_info_detail
                {
                    createtime = now,
                    andon_id = andondata.id,
                    projectid = projectid,
                    remark = remark,
                    user = projectuser.name,
                    status = (int)AndonState.WaitHandle,
                });
                // alarm data
                var alarmdata = new LocationAlarm
                {
                    abnormal_time = now,
                    end_time = UnixTimeHelper.ConvertStringDateTime(endtime.ToStr()),
                    start_time = UnixTimeHelper.ConvertStringDateTime(starttime.ToStr()),
                    machine = machine.machine.ToStr(),
                    pid = projectid,
                    type = expection.id,
                    status = 0,
                    workOrderId = andondata.work_order,
                    trigger = 1,
                    sectionID = _context.siger_project_level_section.FirstOrDefault(f => f.id == machine.station)?.parentid ?? 0,
                };
                if (_context.SaveChanges() > 0)
                {
                    if (!locationAlarm.InsertLocationAlarm(alarmdata))
                    {
                        Logger.WriteLineInfo($"AutoPlanAndon-InsertLocationAlarm failed {alarmdata.workOrderId} !");
                    }
                    if (!locationYield.UpdateLocationYieldStopMachine(alarmdata.machine.ToInt(), alarmdata.type, (int)UnixTimeHelper.ConvertDataTimeLong(alarmdata.start_time), (int)UnixTimeHelper.ConvertDataTimeLong(alarmdata.end_time), alarmdata.workOrderId))
                    {
                        Logger.WriteLineInfo($"AutoPlanAndon-UpdateLocationYieldStopMachine failed {alarmdata.workOrderId} !");
                    }
                }
            }
        }
        /// <summary>
        /// andon trigger
        /// </summary>
        /// <param name="projectid"></param>
        /// <param name="companyid"></param>
        private void AutoAndonTrigger(int projectid, int companyid)
        {
            var now = UnixTimeHelper.GetNow();
            var nowtime = UnixTimeHelper.ConvertStringDateTime(now.ToStr());
            var bottonList = _context.siger_andon_station_config.Where(f => f.project_id == projectid && f.status != 0 && f.station_type == 1).ToList();
            var machines = bottonList.Select(s => s.machine_id).Distinct();
            var andonList = _context.siger_andon_info.Where(f => f.projectid == projectid && f.status == (int)AndonState.Abnormal && machines.Contains(f.machine)).ToList();
            var adminuser = _context.siger_user.Where(f => f.type == (int)UserType.Admin).Select(s => s.id).ToList();
            var projectuser = _context.siger_project_user.FirstOrDefault(f => adminuser.Contains(f.mid) && f.projectid == projectid);
            var locationAlarm = new LocationAlarmRepository(companyid, projectid);

            foreach (var andondata in andonList)
            {
                var botton = bottonList.First(f => f.machine_id == andondata.machine);
                var expection = _context.siger_andon_expection_type.FirstOrDefault(f => f.id == botton.default_error_id && f.projectid == projectid);
                var triggertime = botton.selfdeal_time * 60 + andondata.abnormal_time;
                var alarmData = locationAlarm.GetAbnormalDataByOrder(companyid, andondata.work_order).FirstOrDefault();

                //拦截安灯自动触发并关闭
                if (_context.siger_andon_info.Any(f => f.projectid == projectid && f.status > (int)AndonState.Abnormal && f.status < (int)AndonState.Complete))
                {
                    andondata.status = (int)RowState.Invalid;
                    _context.siger_andon_info.Update(andondata);
                    if (alarmData != null)
                    {
                        locationAlarm.DeleteLocationAlarm(alarmData.id);
                    }
                    continue;
                }
                if (triggertime < now && expection != null)
                {
                    andondata.expection_type = expection.id;
                    andondata.create_time = now;
                    andondata.creator = 0;
                    andondata.status = (int)AndonState.WaitHandle;
                    andondata.process_code = expection.process_code ?? "";
                    andondata.creator = projectuser.mid;
                    _context.Update(andondata);
                    _context.siger_andon_info_detail.Add(new siger_andon_info_detail
                    {
                        createtime = now,
                        andon_id = andondata.id,
                        projectid = projectid,
                        remark = "系统自动触发",
                        user = projectuser.name,
                        status = (int)AndonState.WaitHandle
                    });
                }
                #region update alarm data
                var typeid = 0;
                var expections = GetExpectionParent(andondata.expection_type, projectid);
                if (expections.Any(f => f.level == 1))
                {
                    typeid = expections.First(f => f.level == 1).id;
                }
                else
                {
                    Logger.WriteLineError($"安灯工单{alarmData.workOrderId}的异常类型{andondata.expection_type}没找到一级异常类型！");
                }
                if (alarmData != null && typeid != 0)
                {
                    alarmData.end_time = nowtime;
                    alarmData.start_time = nowtime;
                    alarmData.trigger = 1;
                    alarmData.type = typeid;
                    var flag = locationAlarm.UpdateLocationAlarmById(alarmData);
                    if (!flag)
                    {
                        Logger.WriteLineError($"安灯工单{alarmData.workOrderId}删除LocationAlarm失败");
                    }
                }
                #endregion
            }
            _context.SaveChanges();
        }
        /// <summary>
        /// abnormal syn
        /// </summary>
        private void AbnormalSyn(int cid, int pid)
        {
            var locationAlarm = new LocationAlarmRepository(cid, pid);
            var abnormalData = locationAlarm.GetAbnormalData(pid);
            foreach (var data in abnormalData)
            {
                var order = WorkOrderGenerator(pid);
                var adminuser = _context.siger_user.Where(f => f.type == (int)UserType.Admin).Select(s => s.id).ToList();
                var projectuser = _context.siger_project_user.FirstOrDefault(f => adminuser.Contains(f.mid) && f.projectid == pid);
                var station = _context.siger_project_machine_attribution.FirstOrDefault(f => f.status == (int)RowState.Valid && f.projectid.Equals(pid) & f.machine.Equals(data.machine.ToInt()));
                Logger.WriteLineInfo($"{data.machine}{UnixTimeHelper.ConvertStringDateTime(data.abnormal_time.ToStr())}{data.type}{data.parameter}");
                var model = new siger_andon_info
                {
                    abnormal_time = data.abnormal_time,
                    machine = data.machine.ToInt(),
                    station = station?.station ?? 0,
                    status = (int)AndonState.Abnormal,
                    expection_type = 0,
                    process_code = "",
                    projectid = pid,
                    remark = data.parameter,
                    work_order = order
                };
                _context.siger_andon_info.Add(model);
                if (_context.SaveChanges() > 0)
                {
                    _context.siger_andon_info_detail.Add(new siger_andon_info_detail
                    {
                        andon_id = model.id,
                        createtime = model.abnormal_time,
                        projectid = pid,
                        remark = model.remark,
                        user = projectuser.name
                    });
                    _context.SaveChanges();
                    data.workOrderId = order;
                    locationAlarm.UpdateLocationAlarmById(data);
                }
            }
        }

        private IEnumerable<siger_andon_expection_type> GetExpectionParent(int id, int projectid)
        {
            var query = from c in _context.siger_andon_expection_type
                        where c.id == id && c.status == (int)RowState.Valid
                        select c;
            return query.ToList().Concat(query.ToList().SelectMany(t => GetExpectionParent(t.parent, projectid)));
        }

        private IEnumerable<siger_project_level_section> GetLevelParent(int id, int projectid)
        {
            var query = from c in _context.siger_project_level_section
                        where c.id == id && c.status == (int)RowState.Valid
                        select c;
            return query.ToList().Concat(query.ToList().SelectMany(t => GetLevelParent(t.parentid, projectid)));
        }

        public string WorkOrderGenerator(int projectid)
        {
            var ret = string.Empty;
            var time = $"A{DateTime.Now.ToString("yyyyMMdd")}";
            var infomodel = _context.siger_andon_info.Where(f => f.projectid == projectid && f.work_order.StartsWith(time));
            var no = 1;
            if (infomodel.Any())
            {
                var maxid = infomodel.Max(m => m.id);
                var max = _context.siger_andon_info.First(f => f.id == maxid).work_order;
                var maxparams = max.Split('_');
                if (maxparams.Length == 2)
                {
                    no = maxparams[1].ToInt() + 1;
                }
            }
            ret = $"{time}_{no}";
            return ret;
        }
        public void Dispose()
        {
            _context?.Dispose();
        }
    }
}
