<?php


namespace App\Services;


use Illuminate\Support\Facades\Log;
use JPush\Client;
use PHPUnit\Util\Exception;

class JPushService
{
    protected static $client = null;

    //推送类型
    const PUSH_TYPE_ALL = 1;
    const PUSH_TYPE_TAG = 2;
    const PUSH_TYPE_ALIAS = 3;
    const PUSH_TYPE_REG_ID = 4;
    const JG_YJDL_POST_URL = 'https://api.verification.jpush.cn/v1/web/loginTokenVerify';

    private function __construct()
    {
    }

    private function __clone()
    {
    }

    /**
     * 获取实例
     */
    public static function getInstance()
    {
        if (!self::$client) {
            self::$client = new Client(config('jpush.app_key'), config('jpush.master_secret'), null);
        }
        return self::$client;
    }

    /**
     * 给android或ios推送消息
     */
    public static function pushNotify($params)
    {
        //推送平台
        $platform = $params['platform'] ?? 'all';
        //推送标题
        $title = $params['title'] ?? '';
        //推送内容
        $content = $params['content'] ?? '';
        //通知栏样式ID
        $builder_id = $params['builder_id'] ?? 0;
        //附加字段
        $extras = $params['extras'] ?? '';
        //推送类型
        $type = $params['type'] ?? '';

        //推送目标(注册ID)
        $reg_id = $params['reg_id'] ?? '';
        //推送目标(标签)
        $tag = $params['tag'] ?? '';
        //推送目标(别名)
        $alias = $params['alias'] ?? '';

        try {
            $push = self::getInstance()->push();

            //设置平台
            $push->setPlatform($platform);

            switch ($type) {
                case self::PUSH_TYPE_ALL:
                    $push->addAllAudience();
                    break;
                case self::PUSH_TYPE_TAG:
                    $push->addTag($tag);
                    break;
                case self::PUSH_TYPE_ALIAS:
                    $push->addAlias($alias);
                    break;
                case self::PUSH_TYPE_REG_ID:
                    $push->addRegistrationId($reg_id);
                    break;
            }

            $push->androidNotification($content, [
                'title' => $title,
                'builder_id' => $builder_id,
                'extras' => $extras,
            ])->iosNotification($content, [
                'sound' => 'sound',
                'badge' => '+1',
                'extras' => $extras
            ])->options([
                'apns_production' => config('jpush.apns_production', true),
                //表示离线消息保留时长(秒)
                'time_to_live' => 86400,
            ]);

            $response = $push->send();

            if ($response['http_code'] != 200) {
                Log::channel('jpush')->error(json_encode($response, JSON_UNESCAPED_UNICODE));
            }

            return $response;
        } catch (\Throwable $e) {
            Log::channel('jpush')->error(json_encode([
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $e->getMessage(),
                'params' => $params,
            ], JSON_UNESCAPED_UNICODE));
        }
    }

    /**
     * 获取指定设备的别名和标签
     */
    public static function getDevices($reg_id)
    {
        $response = self::getInstance()->device()->getDevices($reg_id);

        if ($response['http_code'] == 200) {
            return $response['body'];
        }

        return [];
    }

    /**
     * 给指定设备添加标签
     */
    public static function addTags($reg_id, $tags = [])
    {
        $response = self::getInstance()->device()->addTags($reg_id, $tags);

        if ($response['http_code'] == 200) {
            return true;
        }
        return false;
    }

    /**
     * 清空指定设备的标签
     */
    public static function clearTags($reg_id)
    {
        $response = self::getInstance()->device()->clearTags($reg_id);

        if ($response['http_code'] == 200) {
            return true;
        }

        return false;
    }

    /**
     * 清空指定设备的标签
     */
    public static function removeTags($reg_id, $tags = [])
    {
        $response = self::getInstance()->device()->removeTags($reg_id, $tags);

        if ($response['http_code'] == 200) {
            return true;
        }

        return false;
    }

    /**
     * 更新指定设备的别名
     */
    public static function updateAlias($reg_id, $alias)
    {
        $response = self::getInstance()->device()->updateAlias($reg_id, $alias);

        if ($response['http_code'] == 200) {
            return true;
        }

        return false;
    }


    /**
     * jgOpensslPrivateDecrypt($encrypted)     (加密) 手机号码解密获取手机号
     * @param   $encrypted        string       (加密) 手机号码
     * @param
     *
     * @return              string         手机号|false
     *  err:错误信息
     *
     */
    public static function jgOpensslPrivateDecrypt($encrypted){
        $prefix = '-----BEGIN RSA PRIVATE KEY-----';
        $suffix = '-----END RSA PRIVATE KEY-----';
        $result = '';

        $prikey = config('jpush.jg_yjdl_private_rsa');

        $key = $prefix . "\n" . $prikey . "\n" . $suffix;//拼接换行符
        $r = openssl_private_decrypt(base64_decode($encrypted), $result, openssl_pkey_get_private($key));
        if($r){
            return $result;
        }else{
            return false;
            throw new Exception("解密失败");
        }

    }

    /**
     * jgLoginTokenVerify($token)         提交loginToken，验证后返回手机号码(加密)
     * @param   $token        string       认证SDK获取到的loginToken
     * @param   $exId         开发者自定义的id，非必填
     *
     * @return              array         手机号
     *  err:错误信息
     *
     */
    public static function jgLoginTokenVerify($token,$exId)
    {
        $host    =  self::JG_YJDL_POST_URL;
        $method  = "POST";
//        $appcode = VERIFY_APPCODE;
        $headers = array();
        array_push($headers, "Authorization: Basic " .base64_encode(config('jpush.app_key').':'.config('jpush.master_secret')));
        //根据API的要求，定义相对应的Content-Type
        array_push($headers, "Content-Type".":"."application/json");

        $data = json_encode(["loginToken"=>$token,"exId"=>$exId]);

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_URL, $host);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_FAILONERROR, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        //设定返回信息中是否包含响应信息头，启用时会将头文件的信息作为数据流输出，true 表示输出信息头, false表示不输出信息头
        //如果需要将字符串转成json，请将 CURLOPT_HEADER 设置成 false
        curl_setopt($curl, CURLOPT_HEADER, false);

        $ret = curl_exec($curl);
        $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        // file_put_contents(PATH_USER_JG_LOGIN_LOG.date('Y-m-d').'.log', date('Y-m-d H:i:s').$ret.PHP_EOL,FILE_APPEND);//写入文件 常量需要自己在定义
        $ret  = json_decode($ret,true);
        if ($ret['code'] == 8000) {
//            if($ret['exID']!=$exId){
//                throw new Exception("exID 返回与发送不一致");
//            }
        } else {
            throw new Exception($ret['code']."：请重试");
            throw new Exception($ret['code'].':'.$ret['content']);
        }
        return $ret;
    }

}
