using PushPlatform.Common.Enumerate;
using PushPlatform.Common.Util;
using Newtonsoft.Json.Linq;
using PushInfo.Core.BLL;
using PushInfo.Core.Models.QueryResults;
using PushInfo.Core.Models.Tables;
using Quartz;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Data;
using PushInfo.Core.Common;
using PushPlatform.Common.Model;
using PushPlatform.Common.Mq;

namespace PushInfo.Core.BLL
{
    /// <summary>
    /// 处理任务业务类
    /// </summary>
    public class ProcessTaskBLL
    {
        private MapProjectPushBLL mProPushBll = new MapProjectPushBLL();
        private ProjectPushBLL pPushBll = new ProjectPushBLL();
        private PushDataBLL pDataBll = new PushDataBLL();
        private string MqName = "PushTaskQueue";
        private string MqNameTwo = "PushTaskQueueTwo";
        #region 推送执行任务
        /// <summary>
        /// 推送执行任务
        /// </summary>
        /// <param name="task">当前任务数据对象</param>
        public bool StartTask(Map_Project_Push task)
        {
            bool result = true;
            List<DataMessage> dataList = new List<DataMessage>();
            DataTable tableValue = new DataTable();
            bool execResult = false;
            try
            {
                Map_Project_Push templateTask = new Map_Project_Push();
                int? pushActionType = task.Push_ActionType;
                //如果有微信推送提取推送模板的结构
                if (task.Push_Style.IndexOf(((int)PushStyle.微信).ToString()) > -1 && !string.IsNullOrEmpty(task.Wx_MsmodelId))
                {
                    var wxTemModel = mProPushBll.Query_WxModel_By_Id(task.Wx_MsmodelId);
                    if (wxTemModel != null)
                    {
                        task.Wx_MsmTemp = wxTemModel.Content_Temp;
                    }
                }
                ObjectHelper.CopyProperties(task, templateTask);
                if (pushActionType == (int)PushActionType.Url)
                {
                    string url = task.Push_Action;
                    string data = GetFunction(url+ "?proCfgId="+task.Id);
                    var apiResult = JsonHelper.ToObject<APIResult<List<DataMessage>>>(data);
                    dataList = apiResult.Data;
                    if(dataList!=null && dataList.Count()>0)
                    {
                        foreach (var dr in dataList)
                        {
                            //if(!string.IsNullOrEmpty(dr.projectId))
                            //{
                            //    task.Project_Id = dr.projectId;
                            //}
                            task.Push_Title = PushValueHelp.TransfOfDataModel(templateTask.Push_Title, dr);
                            task.Push_Body = PushValueHelp.TransfOfDataModel(templateTask.Push_Body, dr);
                            task.Wx_MsmTemp = PushValueHelp.TransfOfDataModel(templateTask.Wx_MsmTemp, dr);
                            task.Push_IosLink = PushValueHelp.TransfOfDataModel(templateTask.Push_IosLink, dr);
                            task.Push_AndLink = PushValueHelp.TransfOfDataModel(templateTask.Push_AndLink, dr);
                            task.Push_WebLink = PushValueHelp.TransfOfDataModel(templateTask.Push_WebLink, dr);
                            task.Push_WechatLink = PushValueHelp.TransfOfDataModel(templateTask.Push_WechatLink, dr);
                            result = TaskIntoMq(task, dr,DateTime.Now);
                        }
                    }
                }
                else
                {
                    tableValue = pDataBll.GetPushDataAdo(task);
                    foreach (DataRow row in tableValue.Rows)
                    {
                        task.Push_Title = PushValueHelp.TransfOfDataRow(templateTask.Push_Title, tableValue.Columns, row);
                        task.Push_Body = PushValueHelp.TransfOfDataRow(templateTask.Push_Body, tableValue.Columns, row);
                        task.Wx_MsmTemp = PushValueHelp.TransfOfDataRow(templateTask.Wx_MsmTemp, tableValue.Columns, row);
                        task.Push_IosLink = PushValueHelp.TransfOfDataRow(templateTask.Push_IosLink, tableValue.Columns, row);
                        task.Push_AndLink = PushValueHelp.TransfOfDataRow(templateTask.Push_AndLink, tableValue.Columns, row);
                        task.Push_WebLink = PushValueHelp.TransfOfDataRow(templateTask.Push_WebLink, tableValue.Columns, row);
                        task.Push_WechatLink = PushValueHelp.TransfOfDataRow(templateTask.Push_WechatLink, tableValue.Columns, row);
                        DataMessage dataR = PushValueHelp.RowToDataMessage(tableValue, row);
                        //if (!string.IsNullOrEmpty(dataR.projectId))
                        //{
                        //    task.Project_Id = dataR.projectId;
                        //}
                        result = TaskIntoMq(task, dataR, DateTime.Now);
                    }
                }
                execResult = true;
            }
            catch (Exception ex)
            {
                Push_Message pMsave = new Push_Message();
                pMsave.Id = Guid.NewGuid().ToString();
                pMsave.Map_Id = task.Id;
                pMsave.User_Id = "exception";
                pMsave.Project_Id = task.Project_Id;
                pMsave.PushSys_ProId = task.PushSys_ProId;
                pMsave.Push_Target = task.Push_Target;
                pMsave.Push_Style = task.Push_Style;
                pMsave.Push_TagId = task.Push_TagId;
                pMsave.Push_Title = task.Push_Title;
                pMsave.Push_Body = task.Push_Body;
                pMsave.Push_IosLink = task.Push_IosLink;
                pMsave.Push_AndLink = task.Push_AndLink;
                pMsave.Push_WebLink = task.Push_WebLink;
                pMsave.Push_WechatLink = task.Push_WechatLink;
                pMsave.Have_Send = 0;
                pMsave.Is_Successed = 0;
                pMsave.Send_Time = DateTime.Now;
                pMsave.Return_Code = ex.Message;
                pMsave.HaveRead = 0;
                pMsave.Is_Deleted = 1;
                pMsave.Create_Time = DateTime.Now;
                pMsave.Create_User = "admin";
                pPushBll.AddPushMeddage(pMsave);
                LogHelper.Error(ex);
                result = false;
            }
            finally
            {
                if (task != null)
                {
                    if (task.Push_Type == (int)PushType.小时)
                    {
                        //间隔时间为小时
                        task.Exec_Time = task.Exec_Time.AddHours(task.Push_Cycle.Value);
                        task.Exec_Status = (int)ExecuteStatus.循环执行中;
                    }
                    else if (task.Push_Type == (int)PushType.天)
                    {
                        //间隔时间为天 每天的  HH:MM:SS 执行
                        task.Exec_Time = task.Exec_Time.AddDays(1 * (task.Push_Cycle ?? 1));
                        task.Exec_Status = (int)ExecuteStatus.循环执行中;
                    }
                    else if (task.Push_Type == (int)PushType.周)  //没有实现隔多少周
                    {
                        task.Exec_Status = (int)ExecuteStatus.循环执行中;
                    }
                    else if (task.Push_Type == (int)PushType.月)
                    {
                        task.Exec_Status = (int)ExecuteStatus.循环执行中;
                    }
                    else
                    {
                        //一次性执行的任务
                        task.Exec_Status = (int)ExecuteStatus.执行完毕;
                    }
                    mProPushBll.Modify_Task_Excute(task.Id, (ExecuteStatus)task.Exec_Status, task.Trigger_Key, task.Exec_Time);
                }
                //else if (task != null && !execResult)
                //{
                //    task.Exec_Status = (int)ExecuteStatus.循环执行中;
                //    if (task.Push_Type == (int)PushType.一次)
                //    {
                //        task.Exec_Status = (int)ExecuteStatus.执行完毕;
                //    }
                //    mProPushBll.Modify_Task_Excute(task.Id, (ExecuteStatus)task.Exec_Status, task.Trigger_Key, task.Exec_Time);
                //}
            }
            return result;
        }
        #endregion

        #region 保存进推送记录表

        /// <summary>
        /// 保存进推送记录表
        /// </summary>
        /// <param name="mapProPush">存储对象</param>
        /// <param name="data">推送数据</param>
        /// <param name="pushStype">推送类型</param>
        /// <param name="result"></param>
        /// <returns></returns>
        public APIResult<string> InsertPushMessage(Map_Project_Push mapProPush, DataMessage data,string pushStype,APIResult<string> result)
        {
            try
            {
                Push_Message pMsave = new Push_Message();
                pMsave.Id = Guid.NewGuid().ToString();
                pMsave.Map_Id = mapProPush.Id;
                pMsave.User_Id = data.userId;
                pMsave.Project_Id = mapProPush.Project_Id;
                pMsave.PushSys_ProId = mapProPush.PushSys_ProId;
                pMsave.Push_Target = mapProPush.Push_Target;
                pMsave.Push_Style = mapProPush.Push_Style;
                pMsave.Push_TagId = mapProPush.Push_TagId;
                pMsave.Push_Title = mapProPush.Push_Title;
                pMsave.Push_Body = mapProPush.Push_Body;
                pMsave.Push_IosLink = mapProPush.Push_IosLink;
                pMsave.Push_AndLink = mapProPush.Push_AndLink;
                pMsave.Push_WebLink = mapProPush.Push_WebLink;
                pMsave.Push_WechatLink = mapProPush.Push_WechatLink;
                pMsave.Have_Send = 1;
                pMsave.Is_Successed = 1;
                pMsave.Send_Time = DateTime.Now;
                pMsave.Return_Code = mapProPush.Return_Code;
                pMsave.HaveRead = 0;
                pMsave.Is_Deleted = 0;
                pMsave.Create_Time = DateTime.Now;
                pMsave.Create_User = "admin";
                pMsave.Push_Style = pushStype;
                pMsave.Is_Successed = result.Result;
                if (pushStype == ((int)PushStyle.APP).ToString())
                {
                    pMsave.Send_Number = data.clientID;
                }
                if (pushStype == ((int)PushStyle.短信).ToString())
                {
                    pMsave.Send_Number = data.mobile;
                }
                if (pushStype == ((int)PushStyle.微信).ToString())
                {
                    pMsave.Send_Number = data.openId;
                }
                if(pushStype == ((int)PushStyle.站内推送).ToString())
                {
                    pMsave.Push_Style = "5";
                }
                if (pushStype == ((int)PushStyle.邮件).ToString())
                {
                    pMsave.Send_Number = data.Email;
                }
                pPushBll.AddPushMeddage(pMsave);
            }
            catch(Exception ex)
            {
                LogHelper.Error(ex);
                SmsBLL.PushErrorInfo(mapProPush.PushSys_ProId, mapProPush.Name_Des+"用户Id："+data.userId + "在保存进日志的时候发生异常，请查询原因。");
                result.Msg = "抛出异常，请查询日志！";
                result.Result = 0;
                result.code = 1;
            }
            return result;
        }
        #endregion

        #region 调用接口，获得推送的数据
        /// <summary>
        /// 调用接口，获得推送的数据
        /// </summary>
        /// <param name="url">接口地址</param>
        /// <returns></returns>
        public string GetFunction(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new Exception("请求地址为空");
            }
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }
        #endregion

        #region 确认发送推送
        /// <summary>
        /// 确认发送推送
        /// </summary>
        /// <param name="mapProPush"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public bool ConfirmSend(Map_Project_Push mapProPush, DataMessage Data)
        {
            APIResult<string> result = ConfirmSendTask(mapProPush, Data);
            if (result.Result == 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 确认发送推送
        /// </summary>
        /// <param name="mapProPush">发送配置信息</param>
        /// <param name="Data">发送对象数据</param>
        public APIResult<string> ConfirmSendTask(Map_Project_Push mapProPush, DataMessage Data)
        {
            APIResult<string> result = new APIResult<string>();
            result.Result = 1;
            string pushStype = string.Empty;
            try
            {
                if (string.IsNullOrEmpty(mapProPush.Push_Style))
                {
                    LogHelper.Info("projectId：" + mapProPush.Project_Id + Data.realName + "-" + Data.loginName + "推送方式为空");
                    result.Result = 0;
                    return result;
                }
                int num = 0;
                var sendCfgList = mProPushBll.GetSendCfgByProId(mapProPush.PushSys_ProId);
                if (mapProPush.Push_Style.IndexOf(((int)PushStyle.APP).ToString()) > -1)  //有App推送
                {
                    pushStype = ((int)PushStyle.APP).ToString();
                    var appCfg = sendCfgList.Where(x => x.Type == (int)SendCfgType.APP).FirstOrDefault();
                    if (appCfg != null)
                    {
                        AppPushConfig appCfgModel = JsonUtil.ConvertToObject<AppPushConfig>(appCfg.Config_Info);
                        if (!string.IsNullOrEmpty(Data.clientID) && !string.IsNullOrEmpty(Data.clientType))
                        {
                            var taskResult = Task.Run(() =>
                            {
                                return Send_Push(appCfgModel, Data.clientID, Data.clientType, mapProPush.Push_Title, mapProPush.Push_Body, mapProPush.Push_AndLink, mapProPush.Push_IosLink);
                            });
                            result = taskResult.Result;
                        } 
                        else
                        {
                            result.Result = 0;
                            result.Msg = "用户的推送设备号信息不全：clientID：" + Data.clientID + "；clientType：" + Data.clientType;
                        }
                        mapProPush.Return_Code = result.Msg;
                        result = InsertPushMessage(mapProPush, Data, pushStype, result);
                        if (result.Result == 0)
                        { LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "手机推送记录失败"); result.Result = 0; };
                    }
                    else
                    {
                        LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "手机推送记录失败原因：未查询到配置");
                        result.Result = 0;
                    }
                }
                if (mapProPush.Push_Style.IndexOf(((int)PushStyle.短信).ToString()) > -1) //有短信推送
                {
                    result.Msg = "";
                    pushStype = ((int)PushStyle.短信).ToString();
                    var smsCfg = sendCfgList.Where(x => x.Type == (int)SendCfgType.短信).FirstOrDefault();
                    if (smsCfg != null)
                    {
                        SmsConfig smsCfgModel = JsonUtil.ConvertToObject<SmsConfig>(smsCfg.Config_Info);
                        if (!string.IsNullOrEmpty(Data.mobile))
                            result = Send_Message(smsCfgModel.InfoPformProId, Data.mobile, mapProPush.Push_Body, smsCfgModel.SmsSign, smsCfgModel.SmsType);
                        else
                        {
                            result.Result = 0;
                            result.Msg = "推送短信的手机为空！";
                        }
                        mapProPush.Return_Code = result.Msg;
                        result = InsertPushMessage(mapProPush, Data, pushStype, result);
                        if (result.Result == 0) { LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "短信推送记录失败"); result.Result = 0; }
                    }
                    else
                    {
                        LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "短信推送记录失败原因：未查询到配置");
                        result.Result = 0;
                    }

                }
                if (mapProPush.Push_Style.IndexOf(((int)PushStyle.微信).ToString()) > -1) //有微信推送
                {
                    pushStype = ((int)PushStyle.微信).ToString();
                    WechatMsgModel msgModel = new WechatMsgModel();
                    Wechat_Msgmodel sysWxModel = mProPushBll.Query_WxModel_By_Id(mapProPush.Wx_MsmodelId);
                    if (sysWxModel != null)
                    {
                        msgModel.touser = Data.openId;
                        msgModel.template_id_short = "1";
                        msgModel.templeteid = sysWxModel.Templete_Id;
                        msgModel.originalid = sysWxModel.OriginalId;
                        msgModel.data = mapProPush.Wx_MsmTemp;
                        msgModel.url = mapProPush.Push_WechatLink;
                        WeChatHelper.OriginalId = sysWxModel.OriginalId;
                        result = WeChatHelper.SendTempletMessge(msgModel);
                        mapProPush.Return_Code = result.Msg;
                        result = InsertPushMessage(mapProPush, Data, pushStype, result);
                        if (result.Result == 0) { LogHelper.Info(Data.realName + "-" + Data.loginName + "微信推送记录失败"); result.Result = 0; }
                    }
                    else
                    {
                        LogHelper.Info(Data.realName + "-" + Data.loginName + "历史记录失败,微信模板查询失败！");
                        result.Result = 0;
                    }
                }

                if (mapProPush.Push_Style.IndexOf(((int) PushStyle.站内推送).ToString()) > -1) //有站内推送
                {
                    pushStype = ((int) PushStyle.站内推送).ToString();
                    result = InsertPushMessage(mapProPush, Data, pushStype, result);
                    if (result.Result==0)
                    {
                        LogHelper.Info(Data.realName + "-" + Data.loginName + "站内推送记录失败");
                    }
                }

                if (mapProPush.Push_Style.IndexOf(((int) PushStyle.socket).ToString()) > -1)
                {
                    if (mapProPush.Push_Style.IndexOf(((int) PushStyle.站内推送).ToString()) < 0)
                    {
                        pushStype = ((int) PushStyle.站内推送).ToString();
                        result = InsertPushMessage(mapProPush, Data, pushStype, result);
                        if (result.Result==0)
                        {
                            LogHelper.Info(Data.realName + "-" + Data.loginName + "socket站内推送记录失败");
                            result.Result = 0;
                        }
                    }
                }

                if(mapProPush.Push_Style.IndexOf(((int)PushStyle.邮件).ToString()) > -1)
                {
                    pushStype = ((int)PushStyle.邮件).ToString();
                    var emailCfg = sendCfgList.Where(x => x.Type == (int)SendCfgType.APP).FirstOrDefault();
                    if (emailCfg != null)
                    {
                        MailConfig emailCfgModel = JsonUtil.ConvertToObject<MailConfig>(emailCfg.Config_Info);
                        SmsBLL smsBll = new SmsBLL();
                        result = smsBll.SendEmail(Data.Email, mapProPush.Push_Title, mapProPush.Push_Body, emailCfgModel);
                        mapProPush.Return_Code = result.Msg;
                        result = InsertPushMessage(mapProPush, Data, pushStype, result);
                        if (result.Result == 0) { LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "邮件推送记录失败"); result.Result = 0; }
                    }
                    else
                    {
                        LogHelper.Info(mapProPush.Name_Des + Data.realName + "-" + Data.loginName + "邮件推送记录失败原因：未查询到配置");
                        result.Result = 0;
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                SmsBLL.PushErrorInfo(mapProPush.PushSys_ProId, mapProPush.Name_Des + "推送任务发生异常，请查询原因。");
                result.code = 1;
                result.Result = 0;
            }
            return result;
        }
        #endregion

        #region 推送手机通知
        /// <summary>
        /// 推送手机通知
        /// </summary>
        /// <param name="clientId">设备序列号</param>
        /// <param name="clientType">设备类型</param>
        /// <param name="pushTitle">同送title</param>
        /// <param name="pushBody">消息体</param>
        /// <param name="andActionLink">and推送跳转</param>
        /// <param name="iosActionLink">ios推送跳转</param>
        /// <returns></returns>
        public APIResult<string> Send_Push(AppPushConfig appCfgModel,string clientId, string clientType, string pushTitle, string pushBody, string andActionLink, string iosActionLink)
        {
            SmsBLL bllSms = new SmsBLL();
            if (clientType == "ios")
            {
                if(!string.IsNullOrEmpty(iosActionLink))
                {
                    iosActionLink = iosActionLink.Replace("[titleInfo]", pushTitle);
                    iosActionLink = iosActionLink.Replace("[bodyInfo]", pushBody);
                }
                return bllSms.PushSingle(appCfgModel, clientId, 1, pushTitle, pushBody, iosActionLink);
            }
            else
                return bllSms.PushSingle(appCfgModel, clientId, 0, pushTitle, pushBody, andActionLink);
        }
        #endregion

        #region 发送短信通知
        /// <summary>
        /// 发送短信通知
        /// </summary>
        /// <param name="mobile">手机号</param>
        /// <param name="pushBody">短信内容</param>
        /// <returns></returns>
        public APIResult<string> Send_Message(string projectId, string mobile, string pushBody, string smsMessageSigna, int smsType)
        {
            SmsBLL bllSms = new SmsBLL();
            return bllSms.PushMessage(projectId, mobile, pushBody, smsMessageSigna, smsType);
        }
        #endregion

        /// <summary>
        /// 推送任务塞入消息队列
        /// </summary>
        /// <param name="mapProPush"></param>
        /// <param name="data"></param>
        /// <param name="sendDate">发送时间</param>
        /// <returns></returns>
        public bool TaskIntoMq(Map_Project_Push mapProPush, DataMessage data,DateTime sendDate)
        {
            try
            {
                //ConfirmSendTask(mapProPush, data);
                if (mapProPush.Push_Style.IndexOf(((int)PushStyle.APP).ToString()) > -1)
                    MqNameTwo = MqName;
                ActiveMQHelper.CreateMQProducer(MqNameTwo, MQMode.Queue, new DataCenterMessage { ObjectID = "", MsgData = mapProPush.ToJson(), MsgSecondData = data.ToJson()}, sendDate);
            }
            catch (Exception e)
            {
               LogHelper.Error(e);
            }
            return true;
        }

        /// <summary>
        /// 推送任务消费消息队列
        /// </summary>
        /// <param name="mapProPush"></param>
        /// <param name="Data"></param>
        /// <returns></returns>
        public void ReleaseTaskMq()
        {
            ActiveMQHelper.CreateMQConsumer(MqName, MQMode.Queue, msg =>
            {
                try
                {
                    if (!string.IsNullOrEmpty(msg.MsgData) && !string.IsNullOrEmpty(msg.MsgSecondData))
                    {
                        Map_Project_Push mapProPush = JsonHelper.ToObject<Map_Project_Push>(msg.MsgData);
                        DataMessage data = JsonHelper.ToObject<DataMessage>(msg.MsgSecondData);
                        APIResult<string> result = new APIResult<string>();
                        try
                        {
                            result = ConfirmSendTask(mapProPush, data);
                        }
                        catch (Exception ex)
                        {
                            LogHelper.Debug(ex.Message);
                        }
                        if (result.Result != 1 && result.code == 1)
                            TaskIntoMq(mapProPush, data, DateTime.Now.AddSeconds(10));
                        Console.WriteLine(mapProPush.Push_Title + "：" + DateTime.Now.ToString("yyyy-MM-dd HHss"));
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Debug(ex.Message);
                    TaskIntoMq(JsonHelper.ToObject<Map_Project_Push>(msg.MsgData), JsonHelper.ToObject<DataMessage>(msg.MsgSecondData), DateTime.Now.AddSeconds(10));
                }
            });
        }
    }
}
