<?php

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

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

    /**
     * @var int|null
     */
    public $client_id;

    /**
     * @var int|null
     */
    public $id_employee;

    /**
     * @var int|null
     */
    public $id_customer;

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

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

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

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

    /**
     * @var array<string, mixed>
     *
     * @see ObjectModel::$definition
     */
    public static $definition
        = [
            'table' => self::TABLE,
            'primary' => 'id_oauth_auth_code',
            'multilang' => false,
            'multilang_shop' => false,
            'fields' => [
                'client_id' => ['type' => self::TYPE_INT, 'required' => true],
                'id_employee' => ['type' => self::TYPE_INT, 'required' => false],
                'id_customer' => ['type' => self::TYPE_INT, 'required' => false],
                'redirect_uri' => ['type' => self::TYPE_STRING, 'required' => true],
                'token' => ['type' => self::TYPE_STRING, 'required' => true],
                'created' => ['type' => self::TYPE_INT, 'required' => true],
                'expires' => ['type' => self::TYPE_INT, 'required' => true],
            ],
        ];

    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->token) {
            $this->token = self::generateToken();
        }

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

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

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

        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_auth_code` INT(11) NOT NULL AUTO_INCREMENT,
              `client_id` INT(11) NOT NULL,
              `id_employee` INT(11) NOT NULL,
              `redirect_uri` VARCHAR(50) NOT NULL,
              `token` VARCHAR(50)  NOT NULL,
              `created` INT(11) NOT NULL,
              `expires` INT(11) NOT NULL,

               PRIMARY KEY (`id_oauth_auth_code`),
               KEY (token)
            );';

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