<?php

namespace app\common\arw\adjfut\src\WeChat;

use think\facade\Cache;
use app\common\arw\adjfut\src\Curl;
use think\facade\Log;
use think\helper\Arr;

class XcxCommon
{
    /**
     * 微信小程序 appid
     *
     * @var string
     */
    protected $appid = '';
    /**
     * 微信小程序 secret
     *
     * @var string
     */
    protected $secret = '';
    /**
     * 缓存key
     *
     * @var string
     */
    protected $cache_key = '';
    /**
     * 日志通道
     *
     * @var string
     */
    protected $log_channel = '';
    /**
     * 异常
     *
     * @var string
     */
    protected $error = '';
    /**
     * 中控层服务器 access_key
     *
     * @var string
     */
    private $access_key = '';
    /**
     * 中控层服务器 server_base
     *
     * @var string
     */
    private $server_base = '';
    /**
     * access_token 缓存
     *
     * @var string
     */
    private $access_token = '';

    /**
     * 初始化
     *
     * @date 2022-05-18
     * @example
     * @author arw
     * @since 1.0.0
     */
    public function __construct()
    {
        $this->access_key = Config::get('access_key');
        $this->server_base = Config::get('server_base');

        $this->appid = Config::get('xcx.appid');
        $this->secret = Config::get('xcx.secret');
        $this->cache_key = Config::get('xcx.cache_key');
        $this->log_channel = Config::get('xcx.log_channel');
    }

    /**
     * 获取access_token
     * 如果不刷新并且有缓存【 access_token 】的话
     * 直接返回缓存的【 access_token 】
     * 否则将看情况请求【 access_token 】
     *
     * @return string/false
     * @date 2020-04-20
     * @example
     * @author arw
     * @since 1.0.2
     */
    protected function _AccessToken($refresh = false)
    {
        $cache_key = $this->getAccessTokenCacheKey();
        if ($refresh && $cache_key) {
            Cache::delete($cache_key);
        }
        if ($refresh === false && $this->access_token) {
            return $this->access_token;
        }
        $access_token = $this->_GetAccessToken($refresh);
        if ($access_token) {
            $this->access_token = $access_token;
            return $access_token;
        } else {
            $access_token = $this->_GetCacheAccessToken();
            if (!$access_token) {
                $access_token = $this->_CurlAccessToken();
            }
            $this->access_token = $access_token;
            return $access_token;
        }
        return false;
    }

    /**
     * 异常记录
     *
     * @param array $content
     * @param string $level alert | error | warning | notice | info | debug
     * @return void
     * @date 2020-05-29
     * @example
     * @author arw
     * @since 1.0.0
     */
    protected function log(array $data, string $level = 'log')
    {
        $log_channel = $this->log_channel;
        if ($log_channel) {
            Log::channel($log_channel)->log($level, json_encode($data));
        }
    }

    /**
     * 请求【中控层服务器】 获取access_token
     * @param boolean $refresh
     * @return string/false
     * @date 2020-04-20
     * @example
     * @author arw
     * @since 2.0.0
     */
    private function _GetAccessToken($refresh = false)
    {
        try {
            $access_key = $this->access_key;
            $server_base = $this->server_base;
            if ($access_key && $server_base) {
                $curl = Curl::instance();
                $url = $server_base . "api/v2/xcx/accessToken/$access_key";
                $param = [];
                if ($refresh) {
                    $param['refresh'] = 'refresh';
                }
                $info = $curl->setParams($param)->get($url);

                $req_id = Arr::get($info, 'req_id', false);
                $code = Arr::get($info, 'code', false);
                $access_token = Arr::get($info, 'data.access_token', false);

                if ($access_token) {
                    return $access_token;
                }
                $this->log([
                    'action' =>  __FUNCTION__,
                    'url' =>  $curl->getUrl(),
                    'params' => $curl->getParams(),
                    'content' =>  $curl->getContent(),
                    'msg' =>  '获取access_token失败',
                ], 'error');
            }
        } catch (\Throwable $th) {
            $this->log([
                'action' =>  __FUNCTION__,
                'msg' => '客户端错误：' . $th->getMessage(),
                'line' =>  $th->getLine(),
                'file' =>  $th->getFile(),
            ], 'error');
        }
        return false;
    }

    /**
     * 获取本地缓存【access_token】
     *
     * @return string|false
     * @date 2022-12-26
     * @example
     * @author arw
     * @since 1.0.0
     */
    private function _GetCacheAccessToken()
    {
        try {
            $cache_key = $this->getAccessTokenCacheKey();
            if ($cache_key) {
                $access_token = Cache::get($cache_key);
                if ($access_token) {
                    return $access_token;
                }
            }
        } catch (\Throwable $th) {
            $this->log([
                'action' =>  __FUNCTION__,
                'msg' => '客户端错误：' . $th->getMessage(),
                'line' =>  $th->getLine(),
                'file' =>  $th->getFile(),
            ], 'error');
        }
        return false;
    }

    /**
     * 请求【微信服务器】 获取access_token
     *
     * @return string/false
     * @date 2020-04-20
     * @example
     * @author arw
     * @since 1.0.0
     */
    private function _CurlAccessToken()
    {
        try {
            $cache_key = $this->getAccessTokenCacheKey();
            $curl = Curl::instance();
            $url = 'https://api.weixin.qq.com/cgi-bin/token';
            $param = [];
            $param['grant_type'] = 'client_credential';
            $param['appid'] = $this->appid;
            $param['secret'] = $this->secret;
            $info = $curl->setParams($param)->get($url);

            $judge = (isset($info['access_token']) && isset($info['expires_in']));
            if ($judge) {
                $access_token = $info['access_token'];
                if ($cache_key) {
                    $expires_in = $info['expires_in'];
                    Cache::set($cache_key, $access_token, $expires_in);
                }
                return $access_token;
            } else {
                $this->log([
                    'action' =>  __FUNCTION__,
                    'url' =>  $curl->getUrl(),
                    'params' => $curl->getParams(),
                    'content' =>  $curl->getContent(),
                    'msg' =>  '获取access_token失败',
                ], 'error');
            }
        } catch (\Throwable $th) {
            $this->log([
                'action' =>  __FUNCTION__,
                'msg' => '客户端错误：' . $th->getMessage(),
                'line' =>  $th->getLine(),
                'file' =>  $th->getFile(),
            ], 'error');
        }
        return false;
    }

    /**
     * 获取access_key缓存key
     *
     * @return string|false
     * @date 2022-12-26
     * @example
     * @author arw
     * @since 1.0.0
     */
    private function getAccessTokenCacheKey()
    {
        if ($this->cache_key) {
            return $this->cache_key . '.access_token';
        }
        return false;
    }
}
