<?php

namespace onespace\tools\activeApi\components\clients;

use bizley\jwt\Jwt;
use DateTimeImmutable;
use Yii;
use yii\base\Component;
use yii\httpclient\Client;

/**
 * @property string $apiUrl
 * @property string $tokenKey
 * @property string $authUsername
 * @property string $authPassword
 */
class OneSpaceImageServiceClient extends Component {
    public $apiUrl = 'https://image.1s.co.za/';
    public $authUsername = '';
    public $authPassword = '';
    public $tokenKey = '';
    public $tokenAudience = 'https://image.1s.co.za/';
    public $tokenIssuer = 'https://id.1s.co.za/';
    private $_tokens = [];

    public function save($path, $base64): bool {

        $client = new Client(['baseUrl' => $this->apiUrl]);
        $url = 'save';

        $payload = [
            'filename' => $path,
            'base64image' => $base64,
        ];

        $headers = [
            'Authorization' => 'Basic ' . base64_encode($this->authUsername . ':' . $this->authPassword),
        ];

        $response = $client->post($url, $payload, $headers)->setFormat(Client::FORMAT_JSON)->send();

        if ($response->isOk) {
            return true;
        } else {
            Yii::warning("Failed saving image! {$response->statusCode} - {$response->content}", __METHOD__);
            return false;
        }
    }

    public function generateLink($path, $expiryTime = 120, ?int $width = null) {

        // check if we have this path cached
        if (array_key_exists($path, $this->_tokens)) {
            return $this->_tokens[$path];
        }

        // time to generate a JWT
        /** @var Jwt $jwt */
        $jwt = Yii::$app->jwt;

        $signer = $jwt->buildSigner('HS256');
        $key = $jwt->buildKey($this->tokenKey);

        $time = new DateTimeImmutable('now');

        $builder = $jwt->getBuilder()
            ->issuedBy($this->tokenIssuer) // Configures the issuer (iss claim)
            ->permittedFor($this->tokenAudience) // Configures the audience (aud claim)
            ->identifiedBy(Yii::$app->security->generateRandomString(8), true) // Configures the id (jti claim), replicating as a header item
            ->issuedAt($time) // Configures the time that the token was issue (iat claim)
            // ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
            ->expiresAt($time->modify("+ {$expiryTime} seconds")) // Configures the expiration time of the token (exp claim)
            ->withClaim('data', $path); // Configures a new claim, called "data"

        if ($width !== null) {
            $builder->withClaim('width', $width);
        }

        // if there is a logged in user, also send the user id for logging purposes
        if (isset(Yii::$app->user) && Yii::$app->user != null && !Yii::$app->user->isGuest) {
            $builder->withClaim('uid', Yii::$app->user->identity->guid);
        }

        $token = $builder->getToken($signer, $key); // Retrieves the generated token

        // build the url
        $url = $this->apiUrl . '?' . http_build_query(['t' => $token->toString()]);

        // cache for any future requests
        $this->_tokens[$path] = $url;
        return $url;
    }
}
