<?php

use Phalcon\Mvc\Model\Resultset\Simple as Resultset;

class ApiToken extends \Phalcon\Mvc\Model
{

    /**
     *
     * @var string
     */
    public $api_name;

    /**
     *
     * @var string
     */
    public $token;

    /**
     *
     * @var string
     */
    public $created_at;

    const KEY_BOS_MADRASAH = "BOS_MADRASAH";
    const KEY_BOS_MADRASAH_CACHED = "BOS_MADRASAH_CACHED";
    const KEY_RS_ONLINE = "RS_ONLINE";

    const KEY_KEMDIKBUD_PDDIKTI = "KEMDIKBUD_PDDIKTI";

    /**
     * Initialize method for model.
     */
    public function initialize()
    {
        $this->setSchema("jaga");
        $this->setSource("api_token");
    }

    /**
     * Returns table name mapped in the model.
     *
     * @return string
     */
    public function getSource()
    {
        return 'api_token';
    }

    /**
     * Allows to query a set of records that match the specified conditions
     *
     * @param mixed $parameters
     * @return ApiToken[]|ApiToken|\Phalcon\Mvc\Model\ResultSetInterface
     */
    public static function find($parameters = null)
    {
        return parent::find($parameters);
    }

    /**
     * Allows to query the first record that match the specified conditions
     *
     * @param mixed $parameters
     * @return ApiToken|\Phalcon\Mvc\Model\ResultInterface
     */
    public static function findFirst($parameters = null)
    {
        return parent::findFirst($parameters);
    }

    /**
     * @param string $apiName
     * @param string $expiration (e.g. 1 hour)
     * @param array $callback (e.g. array($clientObject, 'clientFunctionNameThatReturnStringToken')
     * @return string (token)
     */
    public static function findTokenOrCreateOne(string $apiName, string $expiration, array $callback): string
    {
        $e = new ApiToken();
        $connection = $e->getReadConnection();
        $tokenData = new ResultSet(
            null,
            $e,
            $connection->query("select *, (NOW() - created_at > INTERVAL '$expiration') AS is_expired from jaga.api_token where api_name = '$apiName'")
        );
        $token = "";
        if(count($tokenData->toArray()) == 0) {
            $apiToken = self::createOne($apiName, $callback);
            $token = $apiToken->token;
        }
        else {
            foreach ($tokenData as $apiToken) {
                if($apiToken->is_expired) {
                    $connection->execute("delete from jaga.api_token where api_name = '$apiName' and token = '".$apiToken->token."'");
                }
                else {
                    $token = $apiToken->token;
                }
            }
            if(empty($token)) {
                $apiToken = self::createOne($apiName, $callback);
                $token = $apiToken->token;
            }
        }
        return $token;
    }

    public static function createOne($apiName, $callback): ApiToken
    {
        $token = call_user_func($callback);
        $apiToken = new ApiToken();
        $apiToken->api_name = $apiName;
        $apiToken->token = $token;
        $apiToken->save();
        return $apiToken;
    }
}
