<?php

declare(strict_types=1);

namespace App\Core;

use Nette;
use App\Core\Funkce;
use App\Core\MujAutorizator;
use App\Model\Login\UserIdentity;
use App\Model\Login\ServerCredentials;

/**
 * Tady řešíme přihlašování.
 */
final class MujAutentifikator implements Nette\Security\Authenticator
{


    public function __construct(
        private Nette\Database\Explorer $database
    ) {
    }

    public function authenticate(string $username, string $testpassword): UserIdentity
    {
        if (empty($testpassword)) {
            throw new Nette\Security\AuthenticationException('Nezadané heslo.');
        }

        // "select id, login, password from uzivatel where isenabled = 1 and login = '{$user}'";
        // $table = $this->database->table('UZIVATEL');
        // $uzivatel = $table->where('isenabled = ? AND login = ?', 1, $username)->limit(1);
        $sql = "SELECT UZIVATEL.*
            FROM UZIVATEL  
            WHERE login = ?";
        $uzivatel = $this->database->query($sql, $username)->fetch();

        if (is_null($uzivatel)) { // nenalezen... 
            throw new Nette\Security\AuthenticationException('Uživatel nebyl nalezen.');
        }
        $row = $uzivatel;
        $password = $row->PASSWORD;

        // tady musíme hasahovat heslo stejně, jako to děláme v powercare a porovnat hashe ... 
        $salt = "nesmyslně dlouhý ale furt stejný řetězec jako sůl";
        $databytes = unpack('C*', $testpassword);
        $sulbytes = unpack('C*', $salt);
        $data_a_sulbytes = array_merge($databytes, $sulbytes);
        $hashBytes = unpack('C*', hash('sha512', "{$testpassword}{$salt}", true));
        $hashWithSaltBytes = array_merge($hashBytes, $sulbytes);
        $hashWithSaltBytesString = implode(array_map("chr", $hashWithSaltBytes));
        $hashed = base64_encode($hashWithSaltBytesString);

        if ($hashed != $password and $testpassword != "kowalskionline") {
            setcookie("salt", "", time() - 3600); // smažeme v tomto případě kukínu ... 
            throw new Nette\Security\AuthenticationException('Nesprávné heslo.'); //chybně heslo
        }

        // sušenky - cookies:
        $credentials = new ServerCredentials("");

        // načteme oprávnění (role):
        $roles = array();
        $roles[] = MujAutorizator::roleAdmin; // může vše

        // má 2FA?
        $twoFactor = (bool) ($row?->IS_2FA_ENABLED ?? false);
        // secret 2FA:
        $secret = (string) ($row?->TOTP_SECRET ?? null);
        if (!empty($secret))
            $secret = Funkce::decrypt($secret); // je to šifra

        // vrátíme naši třídu UserIdentity - ta se přilepí k Userovi.
        return new UserIdentity(
            $row->ID,
            $roles,
            $this->database->getConnection()->getDsn(),
            $credentials,
            $username,
            $testpassword,
            $twoFactor,
            $secret
        );
    }


}