<?php
declare(strict_types=1);

/**
 * Copyright 2010 - 2019, Cake Development Corporation (https://www.cakedc.com)
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright Copyright 2010 - 2019, Cake Development Corporation (https://www.cakedc.com)
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
 */

namespace CakeDC\Auth\Controller\Component;

use Cake\Controller\Component;
use Cake\Core\Configure;
use RobThree\Auth\TwoFactorAuth;

/**
 * OneTimePasswordAuthenticator Component.
 *
 * @link https://github.com/RobThree/TwoFactorAuth
 */
class OneTimePasswordAuthenticatorComponent extends Component
{
    /**
     * @var \RobThree\Auth\TwoFactorAuth $tfa
     */
    public TwoFactorAuth $tfa;

    /**
     * initialize method
     *
     * @param array $config The config data
     * @return void
     */
    public function initialize(array $config): void
    {
        parent::initialize($config);

        if (Configure::read('OneTimePasswordAuthenticator.login')) {
            try {
                $this->tfa = new TwoFactorAuth(
                    qrcodeprovider: Configure::read('OneTimePasswordAuthenticator.qrcodeprovider'),
                    issuer: Configure::read('OneTimePasswordAuthenticator.issuer'),
                    digits: Configure::read('OneTimePasswordAuthenticator.digits'),
                    period: Configure::read('OneTimePasswordAuthenticator.period'),
                    algorithm: Configure::read('OneTimePasswordAuthenticator.algorithm'),
                    rngprovider: Configure::read('OneTimePasswordAuthenticator.rngprovider')
                );
            } catch (\Throwable $t) {
                throw new \RuntimeException(
                    message:__d(
                        'cake_d_c/users',
                        'An error has occurred configuring OneTimePasswordAuthenticator. ' .
                        'Please ensure you have installed robthree/twofactorauth and endroid/qr-code ' .
                        '(or your preferred QR provider): {0}', $t->getMessage()
                    ),
                    previous: $t
                );
            }
        }
    }

    /**
     * createSecret
     *
     * @return string base32 shared secret stored in users table
     */
    public function createSecret(): string
    {
        return $this->tfa->createSecret();
    }

    /**
     * verifyCode
     * Verifying tfa code with shared secret
     *
     * @param string $secret of the user
     * @param string $code from verification form
     * @return bool
     */
    public function verifyCode(string $secret, string $code): bool
    {
        return $this->tfa->verifyCode($secret, $code);
    }

    /**
     * getQRCodeImageAsDataUri
     *
     * @param string $issuer issuer
     * @param string $secret secret
     * @return string base64 string containing QR code for shared secret
     */
    public function getQRCodeImageAsDataUri(string $issuer, string $secret): string
    {
        return $this->tfa->getQRCodeImageAsDataUri($issuer, $secret);
    }
}
