using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Adf.Core.Db;
using Adf.Core.Entity;
using Adf.Core.Util;
using Adf.Core.WebChat.Entity;
using CYQ.Data;
using CYQ.Data.Table;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace CompanyServer
{
    static class ServerClass
    {
        private static string logpath = Application.StartupPath + "\\log\\";
        private static string CurrentTableName = "adf_wxaccesstoken";
        public static string ConnectTest(string con)
        {
            try
            {
                using (MAction action = new MAction("adf_messagecenter", con))
                {
                    action.Select(0, " 1=1 ");
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }

            return "";
        }

        public static void SendMessage(string con)
        {
            AppConfig.Cache.IsAutoCache = false; //清除CYQ的缓存
            MDataTable mDt = new MDataTable();

            try
            {
                using (MAction action = new MAction("adf_messagecenter", con))
                {
                    mDt = action.Select("issend=0  order by createdatetime desc ") ?? new MDataTable();
                    //string sWhereInfo ="issend = 0 and ((sendtype=2 and wxopenid<>'' and wxtemplatecode<>'') or (sendtype=3 and email<>'')) order by createdatetime desc";
                    //mDt = action.Select(sWhereInfo)??new MDataTable();
                }

                if (mDt.Rows.Count > 0)
                {
                    foreach (MDataRow mDr in mDt.Rows)
                    {
                        ExeMsgInfo exeMsg = new ExeMsgInfo();
                        exeMsg.RetStatus = 400;
                        //2微信发送
                        int sendtype = mDr.Get("sendtype", 0);
                        if (sendtype == 2)
                        {
                            if (string.IsNullOrWhiteSpace(mDr.Get("wxopenid", "")) || string.IsNullOrWhiteSpace(mDr.Get("wxtemplatecode", "")))
                            {
                                LogHelper.WriteLog("【" + mDr.Get("sendcode", "") + "】请填写wxopenid或者模板wxtemplatecode!\r\n" + exeMsg.RetValue, logpath);
                                continue;
                            }
                            exeMsg = SendWx(mDr, con);
                        }

                        //3邮箱推送
                        if (sendtype == 3)
                        {
                            string email = mDr.Get("email", "").Trim();
                            if (string.IsNullOrEmpty(email)) { continue; }
                            exeMsg = SendMail(mDr, con);
                            if(exeMsg.RetStatus == 400){continue;}
                        }

                        //更新发送状态
                        if (exeMsg.RetStatus == 100)
                        {
                            string sWhere = " sendcode = '" + mDr.Get("sendcode", "") + "' ";
                            using (MAction action = new MAction("adf_messagecenter", con))
                            {
                                action.Data.Set("issend", 1);
                                action.Data.Set("sendtime", DateTime.Now);
                                action.Update(sWhere, false);
                            }

                        }
                        else
                        {
                            LogHelper.WriteLog("【" + mDr.Get("sendcode", "") + "】发送失败!\r\n" + exeMsg.RetValue, logpath);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                LogHelper.WriteLog(e.Message, logpath);
                throw;
            }
        }

        #region 微信推送
        /// <summary>
        /// 微信消息推送
        /// </summary>
        /// <param name="mdr"></param>
        /// <returns></returns>
        private static ExeMsgInfo SendWx(MDataRow mdr, string con)
        {
            ExeMsgInfo exeMsg = new ExeMsgInfo();
            exeMsg.RetStatus = 100;

            string msgcontent = mdr.Get("msgcontent", "");
            string wxopenid = mdr.Get("wxopenid", "");
            string templateid = mdr.Get("wxtemplatecode", "");
            //获取微信配置
            MDataRow mDr = new MDataRow();
            using (MAction action = new MAction("adf_wxcfg", con))
            {
                MDataTable mDt = action.Select(" isenabled = 1  ") ?? new MDataTable();
                if (mDt.Rows.Count > 0)
                {
                    mDr = mDt.Rows[0];
                }
            }

            string appid = mDr.Get("appid", "");
            string appsecret = mDr.Get("appsecret", "");

            mdr.Set("wxtemplatecode", templateid);

            if (string.IsNullOrEmpty(wxopenid))
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = "openid为空，无法发送,无法发送!";
                return exeMsg;
            }


            if (string.IsNullOrEmpty(appid) || string.IsNullOrEmpty(appsecret) || string.IsNullOrEmpty(templateid))
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = "微信配置错误,无法发送!";
                return exeMsg;
            }

            string rtnData = "";
            try
            {
                AccessToken accessTokenEntity = GetAccessToken(appid, appsecret, con);
                if (accessTokenEntity == null)
                {
                    exeMsg.RetStatus = 400;
                    exeMsg.RetValue = "请配置微信";
                    return exeMsg;
                }

                string accesstoken = accessTokenEntity.access_token;
                string url = string.Format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={0}", accesstoken);

                string strPostData = "{ \"touser\":\"" + wxopenid + "\",\"template_id\":\"" + templateid + "\",\"url\":\"\"," + msgcontent + "}";

                bool isOK = true;
                int errCount = 0;//计算推送失败次数，不能超过3次
                do
                {
                    rtnData = HttpPostData(url, strPostData);
                    if (rtnData.Contains("40001"))
                    {
                        //删除token
                        using (MAction action = new MAction(CurrentTableName, con))
                        {
                            action.Delete(" 1=1 ");
                        }
                    }

                    isOK = rtnData.ToLower().Contains("\"errmsg\":\"ok\"");
                    errCount++;
                    Thread.Sleep(100);
                } while (isOK == false && errCount < 3);

                if (!isOK)
                    exeMsg.RetStatus = 400;

                exeMsg.RetValue = rtnData;
            }
            catch (Exception ex)
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = ex.ToString();
            }
            return exeMsg;
        }

        /// <summary>
        /// post提交
        /// </summary>
        /// <param name="posturl"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        private static string HttpPostData(string posturl, string postData)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            Encoding encoding = Encoding.UTF8;
            byte[] data = encoding.GetBytes(postData);
            // 准备请求...
            try
            {
                // 设置参数
                request = WebRequest.Create(posturl) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.CookieContainer = cookieContainer;
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.ContentLength = data.Length;
                outstream = request.GetRequestStream();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
                //发送请求并获取相应回应数据
                response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                instream = response.GetResponseStream();
                sr = new StreamReader(instream, encoding);
                //返回结果网页（html）代码
                string content = sr.ReadToEnd();
                return content;
            }
            catch (Exception ex)
            {
                string err = ex.Message;
                return err;
            }
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="appId"></param>
        /// <param name="appSecret"></param>
        /// <returns></returns>
        public static AccessToken GetAccessToken(string appId, string appSecret, string con)
        {
            AccessToken accessToken = null;

            try
            {
                bool flag = false;
                if (string.IsNullOrEmpty(appId))
                {
                    throw new System.Exception("AppId未配置");
                }
                if (string.IsNullOrEmpty(appSecret))
                {
                    throw new System.Exception("AppSecret未配置");
                }
                string sWhere = "tokengetdate=" + DbService.SetQuotesValue(DateTime.Now.ToString("yyyy-MM-dd"));
                MDataRow tokenDr = new MDataRow();
                MDataTable mDtToken = new MDataTable();

                try
                {
                    using (MAction action = new MAction(CurrentTableName, con))
                    {
                        mDtToken = action.Select(sWhere) ?? new MDataTable();
                        if (mDtToken.Rows.Count > 0)
                        {
                            tokenDr = mDtToken.Rows[0];
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.WriteLog(e.Message, logpath);
                    return null;
                }


                if (tokenDr != null && tokenDr.Get("tokengetdate", "") != "")
                {
                    string tokenStr = tokenDr.Get("accesstoken", "");
                    int useTime = tokenDr.Get("usetime", 0);
                    DateTime expireTime = tokenDr.Get("expiretime", DateTime.Now);
                    if (expireTime > DateTime.Now.AddMinutes(30))
                    {

                        flag = true;
                        accessToken = new AccessToken();
                        accessToken.access_token = tokenStr;
                        accessToken.expires_in = useTime;
                        accessToken.ExipreDateTime = expireTime;
                        return accessToken;
                    }
                }

                if (!flag)
                {
                    string url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appId, appSecret);
                    LogHelper.WriteLog(url, logpath);
                    //string text3 = HttpHelper.HttpGet2(url);
                    string text3 = GetJsonStr(url);
                    LogHelper.WriteLog(text3, logpath);
                    LogHelper.WriteLog("--->" + text3);

                    JObject jObject = (JObject)JsonConvert.DeserializeObject(text3);
                    if (jObject != null && jObject["access_token"] != null && jObject["expires_in"] != null)
                    {
                        LogHelper.WriteLog("---->11111", logpath);
                        accessToken = new AccessToken();
                        accessToken.access_token = jObject["access_token"].ToString();
                        accessToken.expires_in = jObject["expires_in"].ToObject<int>();
                        DateTime exipreDateTime = DateTime.Now.AddSeconds((double)accessToken.expires_in);
                        accessToken.ExipreDateTime = exipreDateTime;

                        using (MAction action = new MAction(CurrentTableName, con))
                        {
                            action.Delete(" 1=1 ");
                            action.Set("accesstoken", accessToken.access_token);
                            action.Set("usetime", accessToken.expires_in);
                            action.Set("expiretime", accessToken.ExipreDateTime);
                            action.Set("tokengetdate", DateTime.Now.ToString("yyyy-MM-dd"));
                            action.Set("gettimes", 1);
                            action.Insert(InsertOp.None);
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("source:" + ex.Source + "\r\n" + "msg:" + ex.Message, logpath);
            }
            return accessToken;
        }
        public static string GetJsonStr(string url)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "GET";
            using (WebResponse wr = req.GetResponse())
            {
                Stream s = wr.GetResponseStream();
                string StrDate = "";
                string strValue = "";
                StreamReader Reader = new StreamReader(s, Encoding.UTF8);
                while ((StrDate = Reader.ReadLine()) != null)
                {
                    strValue += StrDate + "\r\n";
                }
                return strValue;
            }
        }
        #endregion

        #region 邮件发送
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private static ExeMsgInfo SendMail(MDataRow mDr, string con)
        {
            ExeMsgInfo exeMsg = new ExeMsgInfo();
            exeMsg.RetStatus = 100;

            //获取邮件配置
            String sWhere = " isenabled = 1 ";
            MDataRow mentityEmail = new MDataRow();
            try
            {
                using (MAction action = new MAction("adf_emailcfg", con))
                {
                    MDataTable mDt = action.Select(sWhere) ?? new MDataTable();
                    if (mDt.Rows.Count > 0)
                    {
                        mentityEmail = mDt.Rows[0];
                    }
                }
            }
            catch (Exception e)
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = e.Message;
                return exeMsg;
            }


            string smtpService = mentityEmail.Get("smtpservice", "");
            string sendEmail = mentityEmail.Get("sendemail", "");
            string sendpwd = mentityEmail.Get("sendpwd", "");
            string receiveEmail = mDr.Get("email", "");
            string content = mDr.Get("msgcontent", "");
            string sendtitle = mDr.Get("sendtitle", "");

            //测试邮件发送代码（密码为授权码）
            //smtpService = "smtp.qq.com";
            //sendEmail = "aptivcs@qq.com";
            //sendpwd = "gepsekmljmkldbff";
            //receiveEmail = "15887880@qq.com";
            //content = "测试2222";
            //sendtitle = "标题1111";

            //验证邮箱格式是否正确
            Regex regexEntity = new Regex("^\\s*([A-Za-z0-9_-]+(\\.\\w+)*@(\\w+\\.)+\\w{2,5})\\s*$");
            if (!regexEntity.IsMatch(receiveEmail))
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = "发送邮箱格式错误!";
                return exeMsg;
            }

            if (string.IsNullOrEmpty(smtpService) || string.IsNullOrEmpty(sendEmail))
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = "发送邮箱格式错误!";
                return exeMsg;
            }


            //确定smtp服务器地址 实例化一个Smtp客户端
            SmtpClient smtpclient = new SmtpClient();
            smtpclient.Host = smtpService;
            smtpclient.Port = 587;//阿里云服务器必须使用此商品才能发送qq邮箱

            //确定发件地址与收件地址
            MailAddress sendAddress = new MailAddress(sendEmail);
            MailAddress receiveAddress = new MailAddress(receiveEmail);

            //构造一个Email的Message对象 内容信息
            MailMessage mailMessage = new MailMessage(sendAddress, receiveAddress);
            mailMessage.Subject = sendtitle;
            mailMessage.SubjectEncoding = System.Text.Encoding.UTF8;
            mailMessage.Body = content;
            mailMessage.BodyEncoding = System.Text.Encoding.UTF8;

            //邮件发送方式  通过网络发送到smtp服务器
            smtpclient.DeliveryMethod = SmtpDeliveryMethod.Network;

            //如果服务器支持安全连接，则将安全连接设为true
            smtpclient.EnableSsl = true;
            try
            {
                //是否使用默认凭据，若为false，则使用自定义的证书，就是下面的networkCredential实例对象
                smtpclient.UseDefaultCredentials = false;

                //指定邮箱账号和密码,需要注意的是，这个密码是你在QQ邮箱设置里开启服务的时候给你的那个授权码
                NetworkCredential networkCredential = new NetworkCredential(sendEmail, sendpwd);
                smtpclient.Credentials = networkCredential;


                LogHelper.WriteLog("---->开始发送邮件 | " + sendtitle, logpath);

                //发送邮件
                smtpclient.Send(mailMessage);
                exeMsg.RetValue = "发送邮件成功";
                
                LogHelper.WriteLog("---->邮件发送成功", logpath);
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                exeMsg.RetStatus = 400;
                exeMsg.RetValue = ex.Message;
            }
            return exeMsg;
        }

        #endregion


        public static bool WriteTxt(string sTxt)
        {
            bool retvalue = true;
            try
            {
                string filePath = Application.StartupPath + "\\data.txt";
                FileStream fs = new FileStream(filePath, FileMode.Create);
                //获得字节数组
                byte[] data = System.Text.Encoding.Default.GetBytes(sTxt);
                //开始写入
                fs.Write(data, 0, data.Length);
                //清空缓冲区、关闭流
                fs.Flush();
                fs.Close();
            }
            catch (Exception e)
            {
                retvalue = false;
            }

            return retvalue;
        }
        
        public static bool WriteTxtFull(string sTxt)
        {
            bool retvalue = true;
            try
            {
                string filePath = Application.StartupPath + "\\data.txt";
                FileStream fs = new FileStream(filePath, FileMode.Append);
                //获得字节数组
                byte[] data = System.Text.Encoding.Default.GetBytes(sTxt);
                //开始写入
                fs.Write(data, 0, data.Length);
                //清空缓冲区、关闭流
                fs.Flush();
                fs.Close();
            }
            catch (Exception e)
            {
                retvalue = false;
            }

            return retvalue;
        }

        /// <summary>
        /// 读取txt文件
        /// </summary>
        /// <returns></returns>
        public static string Read()
        {
            try
            {
                string filePath = Application.StartupPath + "\\data.txt";
                FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                StreamReader sr = new StreamReader(fs, Encoding.Default);
                sr.BaseStream.Seek(0, SeekOrigin.Begin);
                string str = sr.ReadToEnd();
                sr.Close();
                fs.Close();
                return str;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "友情提醒", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                return "";
            }
        }

        /// <summary>
        /// 读取配置信息
        /// </summary>
        /// <param name="companytype">类型</param>
        /// <returns></returns>
        public static DataRow ReadDataTable(string companytype)
        {

            DataTable dt = new DataTable();
            dt.Columns.Add("companytype", typeof(string));
            dt.Columns.Add("connectstring", typeof(string));

            string allData = Read();
            if (!string.IsNullOrEmpty(allData))
            {
                string[] arrayData = allData.Split(new string[] { "%%" }, StringSplitOptions.RemoveEmptyEntries);
                if (arrayData.Length > 0)
                {
                    foreach (string sArray in arrayData)
                    {
                        string[] array = sArray.Split(new string[] { "##" }, StringSplitOptions.RemoveEmptyEntries);
                        if (array.Length > 1)
                        {
                            DataRow dr = dt.Rows.Add();
                            dr["companytype"] = array[0];
                            dr["connectstring"] = array[1];
                        }
                    }
                }
            }

            DataRow[] arrayDataRows = dt.Select(" companytype = '" + companytype + "'");

            if (arrayDataRows.Length > 0)
            {
                return arrayDataRows[0];
            }
            else
            {
                return null;
            }

        }

        //private void 开机启动_Click(object sender, EventArgs e)
        //{
        //    MessageBox.Show("设置开机自启动，需要修改注册表", "提示");
        //    string path = Application.ExecutablePath;
        //    RegistryKey rk = Registry.LocalMachine;
        //    RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
        //    rk2.SetValue("JcShutdown", path);
        //    rk2.Close();
        //    rk.Close();

        //}

        //private void 取消启动_Click(object sender, EventArgs e)
        //{
        //    MessageBox.Show("取消开机自启动，需要修改注册表", "提示");
        //    string path = Application.ExecutablePath;
        //    RegistryKey rk = Registry.LocalMachine;
        //    RegistryKey rk2 = rk.CreateSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run");
        //    rk2.DeleteValue("JcShutdown", false);
        //    rk2.Close();
        //    rk.Close();
        //}
        public static string HttpPostByFile(string url, string filepath, string contentM)
        {
            byte[] fileContentByte = new byte[1024]; // 文件内容二进制
            #region 将文件转成二进制

            if (!String.IsNullOrEmpty(filepath))
            {
                FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read);
                fileContentByte = new byte[fs.Length]; // 二进制文件
                fs.Read(fileContentByte, 0, Convert.ToInt32(fs.Length));
                fs.Close();
            }


            #endregion

            var encryptStrByte = Encoding.UTF8.GetBytes(contentM);//encrypt所有字符串二进制
            string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
            Stream myRequestStream = request.GetRequestStream();//定义请求流
            #region 将各个二进制 安顺序写入请求流
            if (!String.IsNullOrEmpty(filepath))
            {
                myRequestStream.Write(fileContentByte, 0, fileContentByte.Length);
            }

            if (!String.IsNullOrEmpty(contentM))
            {
                myRequestStream.Write(encryptStrByte, 0, encryptStrByte.Length);
            }


            #endregion

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();//发送

            Stream myResponseStream = response.GetResponseStream();//获取返回值
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));

            string retString = myStreamReader.ReadToEnd();

            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }
    }
}
