using Siger.DataSchedule.Infrastructure.Extend;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.QmsRepository;
using Siger.Middlelayer.QmsRepository.Request;
using Siger.Middlelayer.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Siger.Schedule.QmsModule
{
    public class QmsSensorJobSchedule : IScheduleJob
    {
        QmsSensorJob sensorJob;
        public void PreInit(ScheduleContext context)
        {
            Logger.RegisterLogEngine(Module.Qms);
            sensorJob = new QmsSensorJob();
        }

        public void Execute(ScheduleContext context)
        {
            sensorJob.Execute();
        }

        public void AfterExecute(ScheduleContext context)
        {
            
        }

        public void Undo()
        {

        }
    }

    public class QmsSensorJob
    {
        private static readonly ApiQmsDbContext _context;

        static QmsSensorJob()
        {
            _context = new ApiQmsDbContext();
        }

        public void Execute()
        {
            try
            {
                var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
                foreach (var item in dbConfigs)
                {
                    //update time and state
                    var paramModel = _context.siger_qms_sensor_parameter.Where(f => f.projectid.Equals(item.Pid)
                    && f.status != (int)RowState.Invalid
                    && f.status != (int)SensorStatus.Marking
                    //&& f.status != (int)SensorStatus.NoSet//去除未设置状态排除
                    ).ToList();
                    foreach (var param in paramModel)
                    {
                        var restTime = param.nexttime - UnixTimeHelper.GetNow();
                        var cycle = CalTimeStamp((CycleUnit)param.cycle_unit, param.cycle);
                        if (restTime <= 30 * 24 * 3600 && restTime > 0)
                        {
                            param.status = (int)SensorStatus.WaitMark;
                        }
                        else if (restTime <= 0)
                        {
                            param.status = (int)SensorStatus.OverDue;
                        }
                        else
                        {
                            param.status = (int)SensorStatus.Normal;
                        }
                        if (param.verification == 1 && param.nextmark_type == 1 && param.status != (int)SensorStatus.WaitMark && param.status != (int)SensorStatus.OverDue)//存在中期检查的正常传感器
                        {
                            if (restTime >= cycle / 2)
                            {
                                param.status = (int)SensorStatus.Verification;
                            }
                        }
                    }
                    if (paramModel.Any())
                    {
                        _context.siger_qms_sensor_parameter.UpdateRange(paramModel);
                        _context.SaveChanges();
                    }
                    var sensormodel = _context.siger_qms_sensor_detail.Where(f => f.projectid.Equals(item.Pid) && f.status != (int)RowState.Invalid
                    );
                    //审核
                    var waitAudit = sensormodel.Where(f => f.status == (int)SensorResult.WaitAudit).Select(s => s.checkuser).Distinct().ToList();
                    if (waitAudit.Any())
                    {
                        waitAudit.ForEach(f =>
                        {
                            SendEmail(f, item.Pid, SensorResult.WaitAudit, item.ServerIP);
                        });
                    }
                    //second审核
                    var secondWaitAudit = sensormodel.Where(f => f.status == (int)SensorResult.SecondWaitAudit).Select(s => s.checkuser2).Distinct().ToList();
                    if (secondWaitAudit.Any())
                    {
                        secondWaitAudit.ForEach(f =>
                        {
                            SendEmail(f, item.Pid, SensorResult.SecondWaitAudit, item.ServerIP);
                        });
                    }
                    //批准
                    var audit = sensormodel.Where(f => f.status == (int)SensorResult.Audit).Select(s => s.approvaluser).Distinct().ToList();
                    if (audit.Any())
                    {
                        audit.ForEach(f =>
                        {
                            SendEmail(f, item.Pid, SensorResult.Audit, item.ServerIP);
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLineError(ex.Message);
            }

        }
        private void SendEmail(int mid, int pid, SensorResult result, string server)
        {
            RequestSensorToken tokenModel = new RequestSensorToken();
            tokenModel.uid = mid;
            var html = string.Empty;
            switch (result)
            {
                case SensorResult.WaitAudit:
                    tokenModel.type = (int)SensorResult.WaitAudit;
                    html = "QMS.PiZ_details.html";
                    break;
                case SensorResult.SecondWaitAudit:
                    tokenModel.type = (int)SensorResult.SecondWaitAudit;
                    html = "QMS.PiZ_details.html";
                    break;
                case SensorResult.Audit:
                    tokenModel.type = (int)SensorResult.Audit;
                    html = "QMS.Audit_details.html";
                    break;
                default:
                    Logger.WriteLineInfo("result错误 邮件发送失败！");
                    return;
            }
            var token = MakeToken(tokenModel);
            if (string.IsNullOrEmpty(token))
            {
                Logger.WriteLineInfo("token生成失败！");
                return;
            }
            var Cfg = _context.siger_project_email_config.FirstOrDefault(f => f.project == pid && f.status == (int)RowState.Valid);
            if (Cfg == null)
            {
                Logger.WriteLineInfo("你没有维护邮箱！");
                return;
            }
            var user = _context.siger_project_user.FirstOrDefault(f => f.mid.Equals(mid) && f.status == (int)RowState.Valid);
            if (user == null || string.IsNullOrEmpty(user.work_email))
            {
                Logger.WriteLineInfo($"{mid}该用户没有邮箱！");
                return;
            }
            StringBuilder sbuilder = new StringBuilder();
            sbuilder.Append($"{user.name}\r\n");
            sbuilder.Append($"您好，传感器标定结果需要您处理，请点击以下网址进行审核。\r\n");
            sbuilder.Append($"http://{server}/{html}");//网址拼接
            sbuilder.Append($"?token={token}&page=1&pagesize=10 \r\n");//参数赋值
            sbuilder.Append($"\r\n  该链接将在24小时后失效 系统自动邮件，请勿回复");
            MailHelper.SendMail(Cfg.server, true, Cfg.send, Cfg.code, "Smart Test Lab",
                   Cfg.send, user.work_email, "传感器标定结果您处理", sbuilder.ToString(), new List<string>());
        }
        private string MakeToken(RequestSensorToken data)
        {
            try
            {
                data.expirationtime = UnixTimeHelper.GetNow() + 24 * 3600;
                var model = JsonHelper.SerializerToJsonString(data);
                return CryptoJSHelper.Encrypt(model);
            }
            catch (Exception ex)
            {
                Logger.WriteLineInfo(ex.Message);
                return "";
            }
        }
        /// <summary>
        /// 计算周期时间
        /// </summary>
        /// <param name="unit"></param>
        /// <param name="cycle"></param>
        /// <returns></returns>
        public int CalTimeStamp(CycleUnit unit, double cycle)
        {
            switch (unit)
            {
                case CycleUnit.Hour:
                    return (int)(3600 * cycle);
                case CycleUnit.Day:
                    return (int)(24 * 3600 * cycle);
                case CycleUnit.Mounth:
                    return (int)(30 * 24 * 3600 * cycle);
                default:
                    return 0;
            }
        }
    }
}
