<?php
// +----------------------------------------------------------------------
// | A3Mall
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.a3-mall.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: xzncit <158373108@qq.com>
// +----------------------------------------------------------------------

namespace app\common\library\sms;

use xzncit\SMS as SMSUtils;
use app\common\exception\BaseException;
use app\common\service\Config;
use app\common\model\SmsTemplate as SmsTemplateModel;
use app\common\model\SmsLog as SmsLogModel;

/**
 * @package app\common\library\sms
 * @class Sms
 * @author xzncit 2024-01-23
 */
class Sms {

    /**
     * @var mixed
     */
    private $client = null;

    /**
     * @var array|mixed|null
     */
    private $config = [];

    /**
     * Sms init.
     * @throws \xzncit\exception\ClassNotFoundException
     * @throws \xzncit\exception\ConfigNotFoundException
     */
    public function initialize(){
        $config = Config::getArray("sms");
        $this->config = $config[$config["type"]];
        $this->config["type"] = $config["type"];
        $this->client = SMSUtils::create($config["type"],$this->config);
    }

    /**
     * 发送短信
     * @param $scene_id  场景ID
     * @param $mobile    用户手机
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function send($scene_id,$mobile){
        $this->initialize();
        $row = SmsTemplateModel::where(["scene_id"=>$scene_id])->find();
        if(empty($row)){
            throw new \Exception("该模板不存在",0);
        }

        if($row["status"] == 0){
            throw new \Exception("短信模板已关闭",0);
        }

        $params = [
            "mobile"        => $mobile,
            "singName"      => $this->config["singName"],
            "templateCode"  => $row["template_id"]??"",
            "templateParam" => ""
        ];

        $num = mt_rand(100000,999999);
        if($this->config["type"] == "aliyun"){
            $params["templateParam"] = str_replace('${code}',$num,$row["template_params"]);
        }else{
            $params["templateParam"] = [$num];
        }

        $log = [
            "scene_id"      => $row["scene_id"],
            "mobile"        => $mobile,
            "content"       => json_encode($params,JSON_UNESCAPED_UNICODE),
            "code"          => $num,
            "verify_status" => 0,
            "send_status"   => 0,
            "create_time"   => time()
        ];

        try{
            $this->client->send($params);
            $log["send_status"] = 1;
            $log["send_time"]   = time();
            $log["results"]     = "短信发送成功";
        }catch (\Exception $ex){
            $log["send_status"] = 2;
            $log["send_time"]   = time();
            $log["results"]     = $ex->getMessage();
        }

        SmsLogModel::create($log);
        return true;
    }

    /**
     * 检测验证码
     * @param int        $scene_id 场景ID
     * @param string|int $mobile   手机号
     * @param string|int $code     验证码
     * @param int        $num      验证次数,0为不验证
     * @return bool
     * @throws BaseException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function verifyStatus($scene_id,$mobile,$code,$num=0){
        $condition = [
            ["scene_id","=",$scene_id],
            ["mobile","=",$mobile]
        ];

        $row = SmsLogModel::where($condition)->order("id","DESC")->find();
        if(empty($row)){
            throw new BaseException("您还未发送验证码",0);
        }

        $timeLimit = 60 * 5;
        if(($row["send_time"] + $timeLimit) < time()){
            throw new BaseException("您的验证码已过期，请重新发送。",0);
        }

        if($row["verify_status"] == 1){
            throw new BaseException("验证码已使用，请重新发送",0);
        }

        if($num > 0 && $row["nums"] > $num){
            throw new BaseException("该验证码超过验证次数，请重新发送",0);
        }

        if($row["code"] != $code){
            throw new BaseException("您输入的验证码错误",0);
        }

        return true;
    }

    /**
     * 更新验证码状态
     * @param $scene_id
     * @param $mobile
     * @param string $code
     */
    public static function updateSmsStatus($scene_id,$mobile,$code=""){
        $condition = [
            ["scene_id","=",$scene_id],
            ["mobile","=",$mobile]
        ];

        if(!empty($code)){
            $condition[] = ["code","=",$code];
        }

        SmsLogModel::where($condition)->save([
            "verify_status" => 1,
            "update_time"   => time()
        ]);
    }

}