<?php

namespace App\Helper\UniPlatform;

/**
 * Class ByteDance.
 *
 * @property string  $appId
 * @property string  $slat
 * @property string  $secret
 * @property string  $token
 * @property string  $accessTokenDir
 * @property string  $accessTokenFile
 * @property string  $accessToken
 * @property string  $noticeUrl
 * @property string  $validTimestamp
 * @property BaseAPI $API
 */
abstract class BaseUniPlatform
{
    protected $appId;
    protected $mchId;
    protected $mchKey;
    protected $secret;
    protected $slat;
    protected $token;

    protected $accessTokenDir;
    protected $accessTokenFile;
    protected $accessToken;
    protected $noticeUrl;
    // 订单过期时间(秒);
    protected $validTimestamp = 24 * 60 * 60;

    protected $API;

    /**
     * @return $this
     */
    public function factory(array $config = [])
    {
        $this->appId  = $config['app_id'];
        $this->secret = $config['app_secret'];
        $this->slat   = $config['slat']    ?? null;
        $this->token  = $config['token']   ?? null;
        $this->mchId  = $config['mch_id']  ?? null;
        $this->mchKey = $config['mch_key'] ?? null;

        $this->setAccessFileDir();
        $this->setAccessFilePath();
        $this->setNoticeUrl();
        $this->accessToken = $this->checkAccessToken();

        return $this;
    }

    /**
     * @throws \Exception
     */
    public function decryptData(string $sessionKey, string $iv, string $encrypted): array
    {
        $decrypted = openssl_decrypt(
            base64_decode($encrypted, true),
            'AES-128-CBC',
            base64_decode($sessionKey),
            OPENSSL_RAW_DATA,
            base64_decode($iv)
        );
        $decrypted = json_decode($decrypted, true);
        if (empty($decrypted)) {
            throw new \Exception('解密数据错误');
        }

        return $decrypted;
    }

    /**
     * 校验access token 是否过期
     */
    protected function checkAccessToken()
    {
        try {
            $dir = $this->accessTokenDir;
            if (!is_dir($dir)) {
                mkdir($dir, 0755);
            }
            if (!is_file($this->accessTokenFile)) {
                touch($this->accessTokenFile);
            }

            $accessToken = file_get_contents($this->accessTokenFile);
            $accessToken = $accessToken ? json_decode($accessToken, true) : null;
            // 改为 还有5分钟过期就刷新，不然会出现没有过期但是抖音会返回过期的信息
            if (empty($accessToken) || $accessToken['expires_at'] < time() + 300) {
                $accessToken = $this->getAccessToken();
            } else {
                $accessToken = $accessToken['access_token'];
            }

            return $accessToken;
        } catch (\Exception $e) {
        }
    }

    /**
     * 登陆.
     */
    abstract protected function login($code): array;

    /**
     * 接口请求
     *
     * @param string $uri
     * @param array  $data
     */
    abstract protected function post($uri = '', $data = []): array;

    /**
     * 获取Access token.
     */
    abstract protected function getAccessToken(): string;

    /**
     * 创建支付订单.
     */
    abstract public function createOrder($outOrderNo, $totalAmount, $openId): array;

    /**
     * 设置 access token 目录.
     */
    abstract protected function setAccessFileDir(): void;

    /**
     * 设置 access token路径.
     */
    abstract protected function setAccessFilePath(): void;

    abstract protected function setNoticeUrl(): void;
}
