<?php
require_once(APPPATH."libraries/PHPMailer/class.phpmailer.php");
require_once(APPPATH."libraries/PHPMailer/class.smtp.php");
require_once(APPPATH."libraries/PHPMailer/class.email.php");
class EmailModel extends CI_Model
{
    public $recallTime;
    public $emailContent;
    public $emailTitle;
    public $_langList;
//    protected $_langList = [
//        'en'=>'英文',
//        'zh'=>'中文',
//        'tw'=>'中文（台湾）',
//        'fr'=>'法语',
//        'de'=>'德语',
//        'es'=>'西班牙',
//        'pt'=>'葡萄牙',
//        'th'=>'泰语',
//        'vi'=>'越南',
//        'no'=>'挪威',
//        'id'=>'印尼',
//        'ro'=>'罗马尼亚',
//        'my'=>'马来西亚'
//    ];
    public function __construct(){
        parent::__construct();
        $this->load->model('oo');
        $this->recallTime = time() - 15*24*60*60;
        $this->_langList = oo::cfg('lang')['en_zh'];
        self::setEmailContent();
    }

    public function setEmailContent($cid=1){
        $tb = otable::EmailConfig();
        $ret= oo::commonOprDb('slavedb')->getAll("SELECT * FROM {$tb} WHERE class={$cid}",MYSQLI_ASSOC);
        foreach ($ret as $row){
            $this->emailContent[strtolower($row['lang'])] = $row['content'];
            $this->emailTitle[strtolower($row['lang'])] = $row['title'];
        }
    }

    public function getUserLang($uid){
        $table = otable::xg_push();
        $sql = " SELECT * FROM {$table} WHERE uid={$uid}";
        $ret = oo::commonOprDb('slavedb')->getOne($sql,MYSQLI_ASSOC);
        if(empty($ret)){
            return false;
        }
        return $ret['lang'];
    }


    public function getUserEmailInfoNew($uid,$db=false){
        $key = okeys::userEmailInfo($uid);
        $info = oo::commonOprRedis('games')->hGetAll($key);
        if(empty($info)||$db){
            $tb = otable::userEmailNew($uid);
            $sql= "SELECT * FROM {$tb} where uid={$uid}";
            $info = oo::commonOprDb('slavedb')->getOne($sql,1);
            oo::commonOprRedis('games')->hMset($key,$info);
        }
        return $info;
    }

    //常规邮件
    public function commonEmail($tid){
        $logTb = otable::EmailSendLog();
        $w = "id={$tid}";
        $sql = "Select * from {$logTb} where {$w}";
        $taskInfo = oo::commonOprDb('games')->getOne($sql,1);


//        $tb = otable::userinfo();
//        if($taskInfo['ext']){
//            $uidList = $taskInfo['ext'];
//            $sql = "SELECT uid,nick,email FROM {$tb} WHERE email!=2 and email!='' and uid in({$uidList})";
//            $list1 = oo::commonOprDb('slavedb')->getAll($sql,1);
//        }
        $ext = json_decode($taskInfo['ext'],true);
        if($ext&&is_array($ext)){
            if($ext['person']){
                $uidList = explode(',',$ext['person']);
                foreach ($uidList as $uid){
                    $info = $this->getUserEmailInfoNew($uid);
                    if($info){
                        $res =$this->sendToUidList($taskInfo,[$info]);
                        oo::logs()->commlog(["mtype"=>1,"uid"=>$uid,"res"=>$res],"sendEmail");
                    }
                }
                $update['status']=2;
                $sql = funs::db_updateSQL($logTb,$update,$w);
                $res2 = oo::commonOprDb('games')->query($sql);
            }
        }
          return ;
    }

    //召回邮件
    public function callBackEmail(){
        $stime =oo::getMsectime();
        $tb = otable::EmailSendLog();
        $sql = "SELECT * FROM {$tb} where mtype=2 and status=1";
        $taskInfo = oo::commonOprDb('slavedb')->getOne($sql,1);
        $actionTime = explode(',',json_decode($taskInfo['ext'],1)['callDay']);
        if(!is_array($actionTime)){
            //TODO 异常处理
            return ;
        }
//        echo "<pre>";
//        print_r($taskInfo);
        $tsA = strtotime(date("Y-m-d",time()));
        foreach ($actionTime as $day){
            $moArr =[];
            $starTime = $tsA- $day*24*60*60;
            $endTime  = $tsA - ($day-1)*24*60*60;
            //到期用户
            $tb = otable::userinfo();
            $sql = "Select uid,email,nick from {$tb} where lasttime BETWEEN {$starTime} and {$endTime}";
            $list = oo::commonOprDb('slavedb')->getAll($sql,1);
//            print_r($list);
//            exit;

            $uList = array_column($list,'uid');
//            $uList2 = array_column($list,null,"uid");
            $uListStr =implode(',',$uList);
            //取模分类
            foreach ($uList as $uid){
                $mo =  $uid%100;
                $moArr[$mo][] =$uid;
            }

            //获取可发送的列表
            $sendList = $sendUidList = [];
            $w = "where 1=1 ";
            switch ($taskInfo['utype']){
                case 2:
                    $w .= " and status=0";
                    break;
                case 3:
                    $w .= " and status=1";
                    break;
            }
            foreach ($moArr as $mo=>$row ){
                $moUids = implode(',',$moArr[$mo]);
                $w2 = "and uid in ({$moUids})";
                $w3 = $w.$w2;
                $tb = otable::userEmailNew($mo);
                $sql2 = "Select uid,email,nick from {$tb} {$w3}";
                $one =oo::commonOprDb('slavedb')->getAll($sql2,1);
                $sendList = array_merge($sendList,$one);
                $sendUidList = array_merge($sendUidList,array_column($one,"uid"));
            }
            //所有邮箱用户时,取用户表有邮箱,但验证表没有邮箱的,加入发送列表
            if($taskInfo['utype']==5){
                foreach ($list as $item){
                    if(filter_var($item['email'], FILTER_VALIDATE_EMAIL)&&!in_array($item['uid'],$sendUidList)){
                        $sendList[] = $item;
                    }
                }
            }
//            var_dump($day);
//            print_r($sendList);
//            exit;
            $res =$this->sendToUidList($taskInfo,$sendList);
            $etime =oo::getMsectime();
            oo::logs()->commlog(["type"=>"callBackEmail","mtype"=>3,"ts"=>($etime-$stime),"sendRes"=>$res,"sendList"=>$sendList],"sendCallBackEmail");
        }
        return true;
    }
    public function actionRecall_Old(){
        $tb = otable::EmailSendLog();
        $sql = "SELECT * FROM {$tb} where mtype=2 and status=1";
        $haveData = oo::commonOprDb('games')->getOne($sql,1);
        $actionTime = explode(',',json_decode($haveData['ext'],1)['callDay']);
        foreach ($actionTime as $day=>$next){
            $recallTime = time() - $day*24*60*60;
            $cacheKey = okeys::EmailRecall($day);
            $ret  = oo::commonOprRedis('games')->zRangeByScore($cacheKey,0,$recallTime,['withscores'=>true]);
            $userArr = [];
            foreach ($ret as $uid=>$time){
                $userInfo = oo::commonOprModel('member')->getUserInfo($uid);
                if(!empty($userInfo['email']) && funs::isEmail($userInfo['email'])){
                    $lang = self::getUserLang($uid);
                    if($lang){
                        $userArr[strtolower($lang)][] = ['email'=>$userInfo['email'],'nick'=>$userInfo['nick']];
                    }
                    if(!empty($next)){
                        oo::commonOprRedis('games')->zAdd(okeys::EmailRecall($next),$time,$uid);
                    }
                }
                oo::commonOprRedis('games')->zDelete($cacheKey,$uid);
            }
            foreach ($userArr as $lang=>$data){
                foreach ($data as $to){
                    try{
                        self::sendMail($to,"Don't get it twisted, we think you'll LOVE this!",$this->emailContent[$lang]);
                        oo::commonOprRedis('Statistics')->incr(okeys::SendMailSta());
                    }catch (Exception $e){
                        var_dump($e->getMessage());
                    }
                }

            }
        }

    }

    //验证邮箱邮件
    public function verifyEmail($utype=3){
        $stime =oo::getMsectime();
        echo "===send verifyEmail start===\r\n";
        $logTb = otable::EmailSendLog();
        $w = "mtype=3 and status=1";// and utype={$utype}

        $sql = "Select * from {$logTb} where {$w}";
        $taskInfo = oo::commonOprDb('games')->getOne($sql,1);
        if(!empty($taskInfo)){
            $list =[];
            $key =okeys::waitSendVerifyUidList();
            $len = oo::commonOprRedis('games')->lSize($key);
            echo "need send userNum:{$len}\r\n";
            if($len>0) {
                if ($len > 5000) {
                    $len = 5000;
                }
                $uidList = oo::commonOprRedis('games')->lGetRange($key,0,$len-1);
                foreach ($uidList as $infoJson){
                    $info  =json_decode($infoJson,true);
//                    $info = oo::commonOprRedis('games')->hGetAll(okeys::userEmailInfo($uid));ACT_USER_STAGE_RATE:666666*
                    if(!empty($info['email'])&&!empty($info['uid'])){
                        $list[] = $info;
                    }
                }
                oo::commonOprRedis('games')->lTrim($key,$len,-1);
                $res =$this->sendToUidList($taskInfo,$list);
                foreach ($res as $uid=>$re){
                    $tb3 = otable::userEmailNew($uid);
                    $updata = ["isVerified"=>$re?2:3];
                    $sql3 = funs::db_updateSQL($tb3,$updata," uid={$uid} ");
                    $res3[$uid] = oo::commonOprDb('games')->query($sql3);
//                    $this->getUserEmailInfoNew($uid,true);
                }
                oo::logs()->commlog(["mtype"=>3,"sendRes"=>$res,"toDbRes"=>$res3],"sendEmail");
            }
            $etime =oo::getMsectime();
            oo::logs()->commlog(["type"=>"verifyEmail","mtype"=>3,"ts"=>($etime-$stime),"sendNum"=>$len],"sendEmail");
        }
        $etime =oo::getMsectime();
        echo "===send verifyEmail end===\r\n";
        echo "耗时：".($etime-$stime)."\r\n";
    }

    public function emailTitle($lang ,$typ=0){
        if(isset($this->emailTitle[$lang])&&!empty($this->emailTitle[$lang])){
            return  $this->emailTitle[$lang];
        }
        $titleLangs = [
            3=>[
                'en'=>'Get your email surprise now!',
                'zh'=>'领取你的邮箱惊喜奖励！',
                'tw'=>'領取你的郵箱驚喜獎勵！',
                'fr'=>'Recevez votre é-mail surprise maintenant !',
                'de'=>'Hol dir jetzt deine E-Mail-Überraschung!',
                'es'=>'¡Consigue tu sorpresa ahora!',
                'pt'=>'Pegue sua surpresa agora!',
                'th'=>'รับความประหลาดใจของคุณตอนนี้!',
                'vi'=>'Nhận bất ngờ của bạn ngay bây giờ!',
                'no'=>'Få overraskelsen din nå!',
                'id'=>'Dapatkan kejutan Anda sekarang!',
                'ro'=>'Primește-ți surpriza acum!',
                'my'=>'Dapatkan kejutan anda sekarang!',
                "it"=>'Ottieni la tua sorpresa ora!'
            ],
        ];
        if($titleLangs[$typ][$lang]){
            return $titleLangs[$typ][$lang];
        }
        if($titleLangs[$typ]){
            return $titleLangs[$typ]["en"];
        }
        return "Think you'll LOVE Crazy Fox";
    }

    /**
     * Notes:数据组装批量发送
     * User: wsc
     * Time: 2022/1/13 21:13
     * @param $tid
     * @param $cid
     * @param $list array | [["uid"=>1,"email","nick"]]
     * @return int|array
     */
    public function sendToUidList($taskInfo,$list){
        $resultArr =[];
        $tid = $taskInfo['id'];
        $cid = $taskInfo['cid'];
        $count = intval($taskInfo['sendNum']);

        $this->setEmailContent($cid);//获取各语言内容
        $logTb = otable::EmailSendLog();
        $stime = strtotime(date("Y-m-d H:i",time()));
        $log =["success"=>0,"lose"=>0];
        $log['stime'] = time();
        $w = " id={$tid}";

        if(!empty($list)){
            $uInfoList = array_column($list,null,'uid');
            $uidList = implode(',',array_keys($uInfoList));
            $count += count($uInfoList);
        }

        $tb2 = otable::xg_push();
        $sql2 = "SELECT uid,lang FROM {$tb2} where uid in ({$uidList})";
        $list2 = oo::commonOprDb('slavedb')->getAll($sql2,1);
        $uLangList = array_column($list2,null,'uid');
        foreach ($uLangList as $k=>$v){
            if(empty($v['lang'])||!in_array($v['lang'],array_keys($this->_langList))){
                $v['lang'] = 'en';
                $uLangList[$k] = $v;
            }
            $langs[$v['lang']][]=$uInfoList[$k];
        }
        $log['success'] = $log['fail'] = 0;
        foreach (array_keys($langs) as $lang){
            $title = $this->emailTitle($lang,3);
            $lang2 = $lang;
            if(empty($lang)||!in_array($v['lang'],array_keys($this->_langList))){
                $lang2 = "en";
            }
            $content = $this->emailContent[$lang2];
            foreach ($langs[$lang] as $info){
                $res  =$this->sendMailNew($info['email'],$title,$content);
                $resultArr[$info['uid']] = $res===true?$info['email']:$res;
                if($res){
                    $log['success']+=count($langs[$lang]);
                }else{
                    $log['fail']+=count($langs[$lang]);
                }
            }
        }
        $sorf=explode('-',$taskInfo['s_f_num']);
        $update['sendNum']=$count;
        $update['s_f_num'] =($log['success']+intval($sorf[0])).'-'.($log['fail']+intval($sorf[1]));
        $update['send_time'] = $stime;
        if($taskInfo['type']==1){
            $update['status'] =2;
        }
        $sql = funs::db_updateSQL($logTb,$update,$w);
        $res2 = oo::commonOprDb('games')->query($sql);
        $log['res'] = $res2;
        $log['etime'] = time();
        $log['resultArr'] = $resultArr;
        oo::logs()->commlog($log,'sendEmail');
        return $resultArr;
    }



    /**
     * Notes:群发邮件(--弃用)
     * User: wsc
     * Time: 2021/3/15 18:41
     * @param int $cid
     * @param int $ts
     * @return bool
     * @throws phpmailerException
     */
    public function sendAllUser_old($ts=0){
        $logTb = otable::EmailSendLog();
        $stime = strtotime(date("Y-m-d H:i",time()));
        $sql = "SELECT * FROM {$logTb} where (type=1 and status=1) or (type=2 and send_time='{$stime}') or (type=3 and status=1)";
        $task = oo::commonOprDb('slavedb')->getOne($sql,1);
        if(empty($task)){
            return 0;
        }else{
            $w = " id={$task['id']}";
            $update['status']=2;
//            $sql = funs::db_updateSQL($logTb,$update,$w);
//            $res = oo::commonOprDb('games')->query($sql);
//            if(!$res){
//                return 1;
//            }
        }
        $cid = $task['cid'];
        $log =["success"=>0,"lose"=>0];
        $log['stime'] = time();

        $this->setEmailContent($cid);//获取各语言内容
        $langs =$list=$list1=$list2=[];
        $count=0;
        $tb = otable::userinfo();
        if($task['ext']){
            $uidList = $task['ext'];
            $sql = "SELECT uid,nick,email FROM {$tb} WHERE email!=2 and email!='' and uid in({$uidList})";
            $list1 = oo::commonOprDb('slavedb')->getAll($sql,1);
        }

        if($task['mtype']==2){
            $ts = $ts>0?$ts:time();
            $ts_s_1 = $ts-86400*3;
            $ts_s_2 = $ts-86400*4;
            $ts_s_3 = $ts-86400*7;
            $ts_s_4 = $ts-86400*8;
            $ts_s_5 = $ts-86400*15;
            $ts_s_6 = $ts-86400*16;
            $sql = "SELECT uid,nick,email FROM {$tb} WHERE email!=2 and email!='' and ((lasttime<{$ts_s_1} and  lasttime>{$ts_s_2}) or (lasttime<{$ts_s_3} and  lasttime>{$ts_s_4}) or (lasttime<{$ts_s_5} and  lasttime>{$ts_s_6}))";
            $list2 = oo::commonOprDb('slavedb')->getAll($sql,1);
        }

        $list = array_merge($list1,$list2);
        if(!empty($list)){
            $uInfoList = array_column($list,null,'uid');
            $uidList = implode(',',array_keys($uInfoList));
            $count += count($uInfoList);
        }

        $tb2 = otable::xg_push();
        $sql2 = "SELECT uid,lang FROM {$tb2} where uid in ({$uidList})";
        $list2 = oo::commonOprDb('slavedb')->getAll($sql2,1);
        $uLangList = array_column($list2,null,'uid');
        foreach ($uLangList as $k=>$v){
            $langs[$v['lang']][]=$uInfoList[$k];
        }


        foreach (array_keys($langs) as $lang){
            $content = $this->emailContent[$lang];
            $res = $this->sendMail($langs[$lang],"Don't get it twisted, we think you'll LOVE this!",$content);
            if($res){
                $log['success']+=count($langs[$lang]);
            }else{
                $log['fail']+=count($langs[$lang]);
            }
        }
        $update['sendNum']=$count;
        $update['s_f_num'] =$log['success'].'-'.$log['fail'];
        $update['send_time'] = $stime;
        $sql = funs::db_updateSQL($logTb,$update,$w);
        $res2 = oo::commonOprDb('games')->query($sql);
        $log['res'] = $res2;
        $log['etime'] = time();
        oo::logs()->commlog($log,'sendEmail');
        return 2;
    }
    public function sendMail2($to, $title,$content, $sendName = 'Crazy fox'){
        $mail = new PHPMailer();

        $mail->CharSet="UTF-8";           //设定邮件编码，默认ISO-8859-1，如果发中文此项必须设置为 UTF-8
        $mail->IsSMTP();                  //设定使用SMTP服务
        $mail->SMTPAuth = true;           //启用SMTP验证功能
        $mail->SMTPSecure = "ssl";        //启用SSL
        $mail->SMTPDebug = 2;
        $mail->Host = "smtpdm.aliyun.com";     //SMTP服务器
        $mail->Port = 465;                //SMTP服务器的端口号
        $mail->Username = "service@mail.astakplay.com";                                      //SMTP服务器用户名
        $mail->Password = "MG6nzEWAp9jWfIrn";//base64_encode("MG6nzEWAp9jWfIrn");                                     //SMTP服务器密码
        $mail->SetFrom('service@mail.astakplay.com', $sendName);                      //设置发件人地址和名称
        $mail->AddReplyTo("service@mail.astakplay.com",$sendName);                    //设置邮件回复人地址和名称
        $mail->Subject = $title;                                     //设置邮件标题
//        $mail->AltBody = "为了查看该邮件，请切换到支持HTML的邮件客户端"; //可选项，向下兼容考虑
        $mail->MsgHTML($content);                             //设置邮件内容
        foreach ($to as $k=>$v){
            $mail->addAddress($v['email'],$v['nick']);
//            $mail->addBCC($v['email'],$v['nick'],$k);
        }
//        $mail->AddAttachment("images/phpmailer.gif");                    //附件
        if(!$mail->Send()) {
            echo "发送失败：" . $mail->ErrorInfo;
        } else {
            echo "恭喜，邮件发送成功！";
        }
    }
    /**
     * 发送邮件
     * @param $to
     * @param $title
     * @param $content
     * @param string $sendName
     * @return bool
     * Created by: Owen
     * Created on: 2020/7/4 15:26
     */
    function sendMail($to, $title,$content, $sendName = 'CrazyCoin'){
        //实例化PHPMailer核心类
        $mail = new PHPMailer();
//        $mail->SMTPDebug = 2;
        //使用smtp鉴权方式发送邮件
        $mail->isSMTP();

        //smtp需要鉴权 这个必须是true
        $mail->SMTPAuth=true;

        //链接qq域名邮箱的服务器地址
//        $mail->Host = 'smtp.gmail.com';
        $mail->Host = 'smtp.feishu.cn';//smtp.exmail.qq.com //

        //设置使用ssl加密方式登录鉴权
        $mail->SMTPSecure = 'ssl';

        //设置ssl连接smtp服务器的远程服务器端口号，以前的默认是25，但是现在新的好像已经不可用了 可选465或587
        $mail->Port =465;//465;// 465;//25; // ssl 使用465,不用ssl 就25 端口

        //设置发件人的主机域 可有可无 默认为localhost 内容任意，建议使用你的域名
//        $mail->Hostname = 'http://god.superant.vip';

        //设置发送的邮件的编码 可选GB2312 我喜欢utf-8 据说utf8在某些客户端收信下会乱码
        $mail->CharSet = 'utf-8';

        //设置发件人姓名（昵称） 任意内容，显示在收件人邮件的发件人邮箱地址前的发件人姓名
        $mail->FromName = $sendName;

        //smtp登录的账号 这里填入字符串格式的邮箱号即可
        $mail->Username ='service@astakplay.com';//crazycoin@superant.cc //service@astakplay.com

        //smtp登录的密码 使用生成的授权码（就刚才保存的最新的授权码）
        $mail->Password = "MG6nzEWAp9jWfIrn";//J2RfwZ3zLsqMavBG //MG6nzEWAp9jWfIrn

        //设置发件人邮箱地址 这里填入上述提到的“发件人邮箱”
        $mail->From = 'service@astakplay.com';//'';

        //邮件正文是否为html编码 注意此处是一个方法 不再是属性 true或false
        $mail->isHTML(true);

        //设置收件人邮箱地址 该方法有两个参数 第一个参数为收件人邮箱地址 第二参数为给该地址设置的昵称 不同的邮箱系统会自动进行处理变动 这里第二个参数的意义不大
//        $mail->addAddress($to['email'],$to['nick']);
        //添加多个收件人 则多次调用方法即可
        // $mail->addAddress('xxx@163.com','尊敬的客户');
        foreach ($to as $k=>$v){
//            $mail->addAddress($v['email'],$v['nick']);
            $mail->addBCC($v['email'],$v['nick'],$k);
        }
        //添加该邮件的主题
        $mail->Subject = $title;

        //添加邮件正文 上方将isHTML设置成了true，则可以是完整的html字符串
        $mail->Body = $content;

        $status = $mail->send();
        //判断与提示信息
        if($status) {
            return true;
        }else{
            var_dump($mail->ErrorInfo);
            return false;
        }
    }

    public function sendMailNew($to,$title,$content, $sendName= 'Crazy Fox'){
        $mailto=$to;//'收信地址';
        $mailsubject=$title;//标题
        $mailbody=$content;//内容
        $smtpserver     = "smtpdm.aliyun.com";//阿里地址
        $smtpserverport = 80;
        $smtpusermail   = 'service@mail.astakplay.com';//"发信地址";
// 发件人的账号，填写控制台配置的发信地址,比如xxx@xxx.com
        $smtpuser       = "service@mail.astakplay.com";
// 访问SMTP服务时需要提供的密码(在控制台选择发信地址进行设置)
        $smtppass       = "MG6nzEWAp9jWfIrn";
        $mailsubject    = "=?UTF-8?B?" . base64_encode($mailsubject) . "?=";
        $mailtype       = "HTML";
//可选，设置回信地址
        $smtpreplyto    = "service@astakplay.com";
        $smtp           = new EmailSmtp($smtpserver, $smtpserverport, true, $smtpuser, $smtppass);
        $smtp->debug    = false;
        $cc   ="";
        $bcc  = "";
        $additional_headers = "";
//设置发件人名称，名称用户可以自定义填写。
        $sender  = $sendName;
       $res =  $smtp->sendmail($mailto,$smtpusermail, $mailsubject, $mailbody, $mailtype, $cc, $bcc, $additional_headers, $sendName, $smtpreplyto);
       return $res;
    }

}
