<?php

declare(strict_types=1);
/**
 * Created by Aurélien RICHAUD (14/02/2018 10:03).
 */
class OAuthClient extends ObjectModel
{
    public const TABLE = 'oauth_client';

    /**
     * @var int
     */
    public $id_oauth_client;

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

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

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

    /**
     * Séparés par des ",".
     *
     * @var string
     */
    public $redirect_uris;

    /**
     * Séparés par des ",".
     *
     * @var string
     */
    public $allowed_grant_types;

    /**
     * @var array<string, mixed>
     *
     * @see ObjectModel::$definition
     */
    public static $definition
        = [
            'table' => self::TABLE,
            'primary' => 'id_oauth_client',
            'multilang' => false,
            'multilang_shop' => false,
            'fields' => [
                'name' => ['type' => self::TYPE_STRING, 'required' => true, 'size' => 50],
                'random_id' => ['type' => self::TYPE_STRING, 'required' => true, 'size' => 20],
                'secret' => ['type' => self::TYPE_STRING, 'required' => true, 'size' => 20],
                'redirect_uris' => ['type' => self::TYPE_STRING, 'required' => true],
                'allowed_grant_types' => ['type' => self::TYPE_STRING, 'required' => false],
            ],
        ];

    public static function generateToken(): string
    {
        $bytes = false;
        if (function_exists('openssl_random_pseudo_bytes') && 0 !== stripos(\PHP_OS, 'win')) {
            $bytes = openssl_random_pseudo_bytes(32, $strong);

            if (true !== $strong) {
                $bytes = false;
            }
        }

        // let's just hope we got a good seed
        if (false === $bytes) {
            $bytes = hash('sha256', uniqid((string) mt_rand(), true), true);
        }

        return base_convert(bin2hex($bytes), 16, 36);
    }

    /**
     * @param bool $null_values
     * @param bool $auto_date
     *
     * @throws PrestaShopException
     *
     * {@inheritDoc}
     */
    public function save($null_values = false, $auto_date = true): bool
    {
        if (!$this->random_id) {
            $this->random_id = self::generateToken();
        }

        if (!$this->secret) {
            $this->secret = self::generateToken();
        }

        return parent::save($null_values, $auto_date);
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public static function getByRandomId(string $random_id): ?self
    {
        $db = Db::getInstance();

        $result = $db->executeS('SELECT * FROM `' . _DB_PREFIX_ . 'oauth_client` WHERE `random_id` = "' . $db->escape($random_id) . '"');

        if (!is_array($result)) {
            $result = [];
        }

        $clients = ObjectModel::hydrateCollection(self::class, $result);

        if (count($clients)) {
            return $clients[0];
        }

        return null;
    }

    public static function install(): bool
    {
        $query = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . static::TABLE . '` (
              `id_oauth_client` INT(11) NOT NULL AUTO_INCREMENT,
              `name` VARCHAR(50) NOT NULL,
              `random_id` VARCHAR(50) NOT NULL,
              `secret` VARCHAR(50) NOT NULL,
              `redirect_uris` VARCHAR(512) NOT NULL,
              `allowed_grant_types` VARCHAR(512) NOT NULL,

               PRIMARY KEY (`id_oauth_client`),
               KEY (random_id)
            );';

        return Db::getInstance()->execute($query);
    }
}
