using System;
using System.Collections.Generic;
using System.Linq;
using FluentScheduler;
using Siger.Middlelayer.KpiRespository;
using Siger.Middlelayer.KpiRespository.Respose;
using Siger.Middlelayer.Repository.Entities;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Redis;
using Siger.Middlelayer.Share.ModuleEnum;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Share.Models;
using Siger.Middlelayer.KpiRespository.Entities;
using NPOI.SS.Formula.Functions;

namespace Siger.ApiKPI.Tasks
{
    /// <summary>
    /// 
    /// </summary>
    public class KpiPushJob : IJob
    {
        private ApiKpiDbContext _context;

        /// <summary>
        /// 
        /// </summary>
        public KpiPushJob()
        {
            _context = new ApiKpiDbContext();
        }
 
        /// <summary>
        /// 
        /// </summary>
        public void Execute()
        {
            //休息日 不推送
            //if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
            //    return;

            var dbConfigs = RedisCache.Instance.GetDbNameConfigs();
            foreach (var dbNameConfig in dbConfigs)
            {
                if (string.IsNullOrWhiteSpace(dbNameConfig.RedisDbName))
                {
                    Logger.WriteLineError($"KpiTasksJob DbNameConfig setting error, can not find redisdbname by cid:{dbNameConfig.Cid}, pid:{dbNameConfig.Pid}.");
                    continue;
                }
                var config = _context.siger_app_project_config.FirstOrDefault(f => f.projectId == dbNameConfig.Pid);
                if (config == null)
                    continue;
                TaskPushing(dbNameConfig.Pid, config);
            }
        }

        /// <summary>
        ///  推送任务
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="config"></param>
        public void TaskPushing(int projectId, siger_app_project_config config)
        {
            try
            {
                var msgData = _context.siger_project_kpi_push_msg.Where(f => f.ProjectId == projectId && f.Mode == Module.Kpi && f.status == (int)RowState.Valid && f.Push<4).ToList();
                if (!msgData.Any())
                    return;
                var pushhelper = new MessageJPushHelper(config.appkey, config.appsecret, config.signid, config.issendSMS);
                foreach (var msg in msgData)
                {
                    var pushSetting = _context.siger_project_kpi_push_setting.FirstOrDefault(f => f.projectId == projectId && f.section_id == msg.SectionId && f.kpi_item == msg.ItemId);
                    if (pushSetting == null)
                        continue;
                    //已计划，检查计划日期前一天开始提醒
                    if (msg.LevelType == KpiPushSettingType.Processing)
                    {
                        var actionData = _context.siger_project_kpi_action.FirstOrDefault(f => f.projectId == projectId && f.TaskId == msg.TaskId);
                        if (actionData == null)
                            continue;
                        if (DateTime.Now < actionData.Plantime.AddDays(-1))
                            continue;
                    }
                    //是否到达该推送时间
                    var level = GetCurrentLevel(projectId, pushSetting.process_code, msg);
                    if (level == 0)
                        continue;
                    var puthTitle = $"{EnumHelper.GetEnumDesc(msg.LevelType)}-{level}级推送";
                    var appMsg = _context.siger_app_project_message.FirstOrDefault(f => f.projectid == projectId && f.repairid == msg.TaskId && f.title == puthTitle);
                    if (appMsg != null)
                    {
                        //频率内是否已经推送
                        var cycleHour = pushSetting.repeattime;
                        var appMsgPushTime = UnixTimeHelper.ConvertIntDateTime(appMsg.create_time);
                        DateTime.TryParse(appMsgPushTime, out DateTime pushTime);
                        if (pushTime.AddDays(cycleHour) > DateTime.Now)
                            continue;
                    }
                    var users = GetUsers(projectId, level, pushSetting.process_code);
                    if(!users.Any())
                    {
                        Logger.WriteLineInfo($"Level{level} Users Not Config");
                        continue;
                    }
                    foreach (var user in users)
                    {
                        var isOnline = IsOnlie(user.Mid, projectId, SystemConfigKey.AppUserOnlineInterval);
                        var appUser = _context.siger_app_project_user.FirstOrDefault(f => f.mid == user.Mid && f.projectId == projectId);
                        if (appUser == null)
                        {
                            Logger.WriteLineInfo($"Level{level} app_project_user Mobile: {user.Mobile} Not found");
                            continue;
                        }
                        var templateId = 166005;
                        var paras = new Dictionary<string, string>{
                            { "location",  ""} };

                        var taskData = _context.siger_project_kpi_tasklist.FirstOrDefault(f => f.id == msg.TaskId);
                        if (taskData == null)
                            continue;
                        var itemData = _context.siger_project_kpi_item.FirstOrDefault(f => f.id == taskData.ItemId);
                        if (itemData == null)
                            continue;
                        var section = _context.siger_project_section.FirstOrDefault(f => f.id == itemData.Section)?.title ?? "";
                        var content = $"部门{section}，KPI指标{itemData.Item}，指标周期{taskData.cycle}，目标值{itemData.TargetVal}，实际值{taskData.ActVal}，日期{taskData.Busidate.ToString(ParameterConstant.DateFormat)}";
                        _context.siger_app_project_message.Add(new siger_app_project_message
                        {
                            tomid = user.Mid,
                            projectid = projectId,
                            repairid = msg.TaskId,
                            create_time = UnixTimeHelper.GetNow(),
                            type = 1,
                            title = puthTitle,
                            content = content,
                            read_sign = 0,
                            status = (int)RowState.Valid,
                        });
                        var messageInfo = new PushMessage
                        {
                            tomid = user.Mid,
                            projectid = projectId,
                            repairid = msg.ItemId,
                            create_time = UnixTimeHelper.GetNow(),
                            type = 1,
                            title = puthTitle,
                            content = content,
                            read_sign = 0,
                            status = (int)RowState.Valid,
                        };
                        var result = pushhelper.PushMessage(messageInfo, isOnline, appUser.appkey, user.Mobile, templateId, paras);
                        msg.Push = level;
                        msg.LastUpdate = DateTime.Now;
                        _context.siger_project_kpi_push_msg.Update(msg);
                        //if (msg.LevelType == KpiPushSettingType.Done)
                        //    _context.siger_project_kpi_push_msg.Remove(msg);
                        //_context.SaveChanges();
                    }
                    if (msg.LevelType == KpiPushSettingType.Done)
                        _context.siger_project_kpi_push_msg.Remove(msg);
                    _context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLineError(ex.ToString());
            }
        }
       
        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;
        }

        /// <summary>
        /// 获取等级 间隔时间
        /// </summary>
        /// <param name="code"></param>
        /// <param name="projectId"></param>
        /// <param name="itemId"></param>
        /// <param name="type">类型（异常未处理，指定计划时间，处理结果）</param>
        /// <returns></returns>
        IEnumerable<ResponsePlanLevel> GetLeveTime(string code, int projectId, int itemId, int type)
        {
            var query = from s in _context.siger_project_kpi_push_setting
                        join r in _context.siger_project_plan_report on s.process_code equals r.process_code
                        where s.projectId == projectId && s.process_code == code && s.kpi_item == itemId && r.type == type
                        select new ResponsePlanLevel
                        {
                            StartLevel = r.start_level,
                            EndLevel = r.end_level,
                            SpaceTime = r.space_time,
                            Type = r.type
                        };
            return query;
        }


        int GetCurrentLevel(int projectId, string processCode, SigerProjectKpiTaskMessage msg)
        {
            var levelSetting = GetLeveTime(processCode, projectId, msg.ItemId, (int)msg.LevelType).OrderBy(s => s.StartLevel).ToList();

            //未到推送时间
            var level = 1;
            foreach (var l in levelSetting)
            {
                if (msg.Push +1 != l.StartLevel)
                    continue;
                if (DateTime.Now <= msg.LastUpdate.AddMinutes(l.SpaceTime))
                    level = l.StartLevel;
       
            }
           
            return level;
        }
        List<ResponsePlanLevelUser> GetUsers(int projectId, int level, string processCode)
        {
            // 如果level=2，发送1,2 层级User,以此类推
            List<int> levels = new List<int>();
            for (var i = 0; i < level; i++)
            {
                levels.Add(i + 1);
            }
            var query = from l in _context.siger_project_plan_report_level
                        join g in _context.siger_project_usergroup on l.usergroup_id equals g.id
                        join u in _context.siger_project_user on l.usergroup_id.ToString() equals u.usergroupid
                        where l.project_id == projectId && l.process_code == processCode && levels.Contains(l.level) &&
                        l.status == (int)RowState.Valid && g.status == (int)RowState.Valid && u.status == (int)RowState.Valid
                        select new ResponsePlanLevelUser
                        {
                            Mid = u.mid,
                            Mobile = u.mobile,
                            Email = u.work_email,
                            Name = u.name
                        };
            return query.GroupBy(g=>g.Mid).Select(f=>f.FirstOrDefault()).ToList();
        }

    }
}
