<?php

declare(strict_types=1);

namespace App\Master\Framework\Library\Easywechat;

use App\Master\Enum\RedisKeyEnum;
use App\Utils\RedisUtil;
use EasyWeChat\MiniApp\Application;
use EasyWeChat\Kernel\Contracts\Config;

/**
 * 微信小程序开发组
 * class MiniAppService
 */
class MiniApp extends EasyModule
{
    protected Application $app;
    protected Config      $config;

    /**
     * 实例化
     *
     */
    public function __construct()
    {
        parent::__construct();

        $this->app    = $this->miniApp();
        $this->config = $this->app->getConfig();
    }

    /**
     * openid 授权
     *
     * @param string $code
     * @return bool
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function jscode2session(string $code): bool
    {
        $app = $this->app;

        $api = $app->getClient();

        $response = $api->get('/sns/jscode2session', [
            'appid'      => $this->config['app_id'],
            'secret'     => $this->config['secret'],
            'js_code'    => $code,
            'grant_type' => 'authorization_code',
        ]);

        if (!$this->response($response)) {
            return false;
        }

        return true;
    }

    /**
     * 获取手机号
     *
     * @param string $code
     * @return bool
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    public function getUserPhone(string $code): bool
    {
        $app = $this->app;

        if (!$access_token = $this->getAccessToken()) {
            return false;
        }

        $api = $app->getClient();

        $response = $api->postJson("/wxa/business/getuserphonenumber?access_token={$access_token}", [
            'code' => $code
        ]);

        if (!$this->response($response)) {
            return false;
        }

        return true;
    }

    /**
     * 获取 access_token
     * @return false|mixed|\Redis|string
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    private function getAccessToken()
    {
        if ($access_token = RedisUtil::getInstance(RedisKeyEnum::WX_MINI_APP_ACCESS_TOKEN)->get()) {
            return $access_token;
        }

        if (!$this->stable_token()) {
            return false;
        }

        $data = $this->get();
        if (empty($data['access_token'])) {
            return false;
        }

        RedisUtil::getInstance(RedisKeyEnum::WX_MINI_APP_ACCESS_TOKEN)->setex($data['access_token'], (int)($data['expires_in'] ?? 0));

        return $data['access_token'];
    }

    /**
     * 获取 access_token
     * @return bool
     * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
     */
    private function stable_token(): bool
    {
        $app = $this->app;

        $api = $app->getClient();

        $response = $api->postJson('/cgi-bin/stable_token', [
            'grant_type'    => 'client_credential',
            'appid'         => $this->config['app_id'],
            'secret'        => $this->config['secret'],
            'force_refresh' => false,// 默认false:普通模式false;强制刷新模式true;
        ]);

        if (!$this->response($response)) {
            return false;
        }

        return true;
    }
}