<?php

namespace UtilityModule\Service;

use Doctrine\ORM\NoResultException;
use Firebase\JWT\JWT;
use Zend\Config\Config;
use Zend\Crypt\Password\Bcrypt;

class AuthService
{
    const CONFIG_KEY_NAME = 'hmac_key';
    const PASSWORD_COST = 14;

    /**
     * @var Config
     */
    private $config;

    public function __construct(
        Config $config
    ) {

        $this->config = $config;
    }

    /**
     * @param string $user
     * @param string $pass
     * @return string
     * @throws NoResultException
     */
    public function authenticate(string $user, string $pass): string
    {
        $cfgUser = $this->config->get('user');
        $cfgPass = $this->config->get('pass');

        $crypt = new Bcrypt();
        $crypt->setCost(self::PASSWORD_COST);

        if ($cfgUser===$user && $crypt->verify($pass, $cfgPass)) {
            return $this->generateJwt();
        }

        throw new NoResultException();
    }

    /**
     * @param $token
     * @return string
     */
    public function renewToken($token): string
    {
        return $this->renewJWT($token);
    }

    /**
     * @return string
     */
    private function generateJwt(): string
    {
        /** @var string $hmacKey */
        $hmacKey = $this->config->get('hmac_key');
        return JWT::encode([
            "jti" => uniqid(),
            "iat" => time(),
            "nbf" => time(),
            "exp" => time() + 3600,
        ], $hmacKey);
    }

    /**
     * @param $token
     * @return string
     */
    private function renewJWT($token): string
    {
        /** @var string $hmacKey */
        $hmacKey = $this->config->get('hmac_key');
        return JWT::encode([
            "jti" => $token['jti'],
            "iat" => time(),
            "nbf" => time(),
            "exp" => time() + 3600,
        ], $hmacKey);
    }

    /**
     * @param string $password
     * @return string
     */
    public function createPasswordHash(string $password): string
    {
        $crypt = new Bcrypt();
        $crypt->setCost(self::PASSWORD_COST);
        return $crypt->create($password);
    }
}
