<?php

namespace Server\unipush;

use App\Services\HttpService;
use App\Services\MicroService;
use JPush\Client;

class UnipushService extends MicroService
{

    public $uniacid = 0;

    public $configs = array(
        'unipush'=>array(
            'switch'=>false,
            'appId'=>'',
            'appKey'=>'',
            'masterSecret'=>''
        ),
        'jpush'=>array(
            'switch'=>false,
            'appKey'=>'',
            'masterSecret'=>'',
            'debugMode'=>0
        )
    );

    function __construct(){
        parent::__construct('unipush');
        if (empty($uniacid)){
            $uniacid = $GLOBALS['_W']['uniacid'];
        }
        $this->Unique=true;
        $this->uniacid = $uniacid;
        $config = pdo_get("unipush", array('uniacid'=>$uniacid));
        if (!empty($config)){
            $unipush = $config['unipush'] ? unserialize($config['unipush']) : [];
            $jpush = $config['jpush'] ? unserialize($config['jpush']) : [];
            if (!empty($unipush)) $this->configs['unipush'] = $unipush;
            if (!empty($jpush)) $this->configs['jpush'] = $jpush;
        }
    }

    public function getMethods($data = array()){
        $data["uniPush"] = array(
            "name"=>"uniPush1.0",
            "summary"=>"使用uniPush向APP推送消息",
            "params"=>array(
                "cid"=>["设备唯一标识，通过前端脚本获取", "string"],
                "payload"=>["推送消息体，含title、desc、url、badgeNum等", "array"],
                "config"=>["推送接口配置，可以自定义appId、appKey等参数，默认读取后台配置", "array|null"]
            ),
            "requires"=>["cid", "payload"],
            "return"=>["推送结果","object"]
        );
        $data['jPush'] = array(
            "name"=>"极光推送",
            "summary"=>"使用极光推送向APP推送消息",
            "params"=>array(
                "toUser"=>["推送的对象", "string|array"],
                "payload"=>["推送消息体，含title、desc、url、ios_sound、extras等", "array"],
                "config"=>["推送接口配置，可以自定义appKey和masterSecret，默认读取后台配置", "array|null"],
                "userType"=>["接收对象类型，支持alias（默认）、registration_id、tag","string|null", "alias"]
            ),
            "requires"=>["toUser", "payload"],
            "return"=>["推送结果","object"]
        );
        return parent::getMethods($data); // TODO: Change the autogenerated stub
    }

    public function jPush($toUser, array $payload, $config=[], $userType='alias'){
        if (!$this->configs['jpush']['switch']) return error(-1, "暂未开放极光推送功能");
        $this->Composer();
        if (empty($config)) $config = $this->configs['jpush'];
        $client  = new Client($config['appKey'],$config['masterSecret']);
        $pusher = $client->push();
        $pusher->setPlatform('all');
        if (empty($toUser)){
            $pusher->addAllAudience();
        }else{
            switch ($userType){
                case "registration_id" : {
                    $pusher->addRegistrationId($toUser);
                    break;
                }
                case "alias" : {
                    $pusher->addAlias($toUser);
                    break;
                }
                case "tag" : {
                    $pusher->addTag($toUser);
                    break;
                }
                default :;
            }
        }
        try {
            $pusher->setNotificationAlert($payload['desc']?:"");
            $pusher->iosNotification($payload['title']?:"", array(
                'sound' => $payload['ios_sound'] ?? 'sound.caf',
                'extras' => $payload['extras'] ?? [],
                'badge'=> '+1'
            ));
            $pusher->androidNotification($payload['title'], array(
                'extras' => $payload['extras'] ?? []
            ));
            $options = array(
                'third_party_channel'=>[
                    "huawei"=>[
                        "importance"=>"NORMAL"
                    ]
                ]
            );
            if (empty($config['debugMode'])){
                $options['apns_production'] = true;
            }
            $pusher->options($options);
            return $pusher->send();
        }catch (Exception $exception){
            return error(-1, $exception->getMessage());
        }
    }

    public function uniPush($cid,$payload, $config = []){
        if (!$this->configs['unipush']['switch']) return error(-1, "暂未开放uni-push功能");
        if (empty($config)){
            $config = $this->configs['unipush'];
        }

        if (is_array($cid)){
            return $this->pushMessageToList($cid, $payload, $config);
        }
        return $this->pushMessageToSingle($cid, $payload, $config);
    }

    public function getToken($config){
        $cacheKey = "MicroServerUnipushToken" . $config['appId'];
        $token = Cache::get($cacheKey, '');
        if (!empty($token) && !is_error($token)) return $token;
        $timestamp = time() * 1000;
        $sign = hash('sha256', $config['appKey']. $timestamp. $config['masterSecret']);

        $headers = ['content-type'=>'application/json;charset=utf-8'];
        $data = [
            'sign' => $sign,
            'timestamp' => $timestamp,
            'appkey' => $config['appKey'],
        ];
        $response = HttpService::ihttp_request("https://restapi.getui.com/v2/{$config['appId']}/auth", json_encode($data), $headers);

        if (is_error($response)) return $response;
        $result = json_decode($response['content'], true);
        if ((int)$result['code'] != 0){
            return error(0-$result['code'], $result['msg']);
        }
        $token = $result['data']['token'];
        $tti = $result['data']['expire_time'] - time();
        Cache::put($cacheKey, $token, $tti);

        return $token;
    }

    public function pushMessageToSingle($clientId, $payload=array(), $config = []){
        if (empty($config)){
            $config = $this->configs['unipush'];
        }
        $token = $this->getToken($config);
        if (is_error($token)) return $token;
        $url = "https://restapi.getui.com/v2/{$config['appId']}/push/single/cid";

        $headers = ['content-type'=>'application/json;charset=utf-8', 'token'=>$token];

        $data = $this->genNotificationData($payload, $clientId);
        $data['request_id'] = md5(serialize($payload)."MessageToSingle".$clientId);
        $data['audience'] = array('cid'=>[$clientId]);

        $response = HttpService::ihttp_request($url, json_encode($data), $headers);
        if (is_error($response)) return $response;
        $result = json_decode($response['content'], true);
        if ((int)$result['code'] != 0){
            return error(0-$result['code'], $result['msg']);
        }
        return $result;
    }

    public function pushMessageToList($clients, $payload, $config = []){
        if (empty($clients)) return true;
        if (!is_array($clients)) $clients = [
            ['clientid'=>$clients]
        ];
        if (empty($config)){
            $config = $this->configs['unipush'];
        }

        $token = $this->getToken($config);
        if (is_error($token)) return $token;
        $url = "https://restapi.getui.com/v2/{$config['appId']}/push/list/cid";

        $headers = ['content-type'=>'application/json;charset=utf-8', 'token'=>$token];

        $data = $this->genNotificationData($payload);
        $res = HttpService::ihttp_request("https://restapi.getui.com/v2/{$config['appId']}/push/list/message", json_encode($data), $headers);
        if (is_error($res) || empty($res['content'])){
            return empty($res['content']) ? error(-1, "创建推送消息失败") : $res;
        }
        $taskInfo = json_decode($res['content'], true);
        if ($taskInfo['code']>0 || empty($taskInfo['data']['taskid'])){
            return error(0-$taskInfo['code'], $taskInfo['msg']);
        }

        $body = array(
            'audience'=>[
                'cid'=>array_column($clients, 'clientid')
            ],
            'taskid'=>$taskInfo['data']['taskid'],
            'is_async'=>false
        );
        $response = HttpService::ihttp_request($url, json_encode($body), $headers);
        if (is_error($response)) return $response;
        $result = json_decode($response['content'], true);
        if ((int)$result['code'] != 0){
            return error(0-$result['code'], $result['msg']);
        }
        return $result;
    }

    //通知透传模板
    public function genNotificationData($payload){
        $click_type = !empty($payload['url']) ? 'payload' : 'startapp';
        $notification = array(
            'title'=>$payload['title'],
            'body'=>empty($payload['desc'])?'您收到了一条新消息':$payload['desc'],
            'logo'=>'icon.png',
            'click_type'=>$click_type,
            'url'=>''
        );
        if (!empty($payload['url'])){
            $notification['payload'] = '{"pagePath":"'.$payload['url'].'"}';
        }
        return array(
            'settings'=>array(
                'ttl'=>7200000
            ),
            'push_message'=>array(
                'notification'=>$notification
            ),
            'push_channel'=>array(
                'ios'=>[
                    'type'=>'notify',
                    'auto_badge'=>"+1",
                    'payload'=>'{"pagePath":"'.$payload['url'].'"}',
                    'aps'=>[
                        'alert'=>[
                            'title'=>$notification['title'],
                            'body'=>$notification['body']
                        ],
                        'content-available'=>0
                    ]
                ],
                'android'=>[
                    'ups'=>[
                        'notification'=>$notification
                    ]
                ]
            )
        );
    }


}
