<?php
namespace App\Presentation\Sign;

use App\Model\FormData\LoginFormData;
use App\Core\MujAutentifikator;
use App\Core\TwoFactorService;
use Nette;
use Nette\Application\UI\Form;
use Nette\Application\Attributes\Persistent;
use Nette\Http\Session;
use Nette\Http\SessionSection;
use App\Model\Login\UserIdentity;
use App\Core\Funkce;

final class SignPresenter extends Nette\Application\UI\Presenter
{
	/**
	 * Stores the previous page hash to redirect back after successful login.
	 */
	#[Persistent]
	public string $backlink = '';

	// Dočasné úložiště pro identitu před ověřením 2FA
	private SessionSection $twoFactorSession;

	public function __construct(
		private MujAutentifikator $autentifikator,
		private TwoFactorService $twoFactorService,
		private Session $session
	) {
		$this->twoFactorSession = $session->getSection('2fa_auth');
		// $secret = $this->twoFactorService->generateSecret();
		// bdump($secret);
	}

	protected function createComponentSignInForm(): Form
	{
		$sifra = Funkce::encrypt("KFMUYZL5VHCV3P5ZVFIMMPQAAN2D6ZRPBRAVATSQITDRGRKIO7P4IA3DCHLETVCMT3Y7RTXVIULC4JJSKX2JBC33XT52TLKFFPQAVAI");
		bdump($sifra);

		$form = new Form();
		$form->addText('username', 'Uživatelské jméno:')
			->setRequired('Prosím vyplňte své uživatelské jméno.')
			->setValue(@$_COOKIE['user']);

		$form->addPassword('password', 'Heslo:');
		// setRequired nepoužívat!! kvůli soft logoutu!!!
		//->setRequired('Prosím vyplňte své heslo.');

		$form->addSubmit('send', 'Přihlásit');
		//$form->addProtection(); //ochrana pomocí TOKENu

		$form->onSuccess[] = $this->signInFormSucceeded(...);
		return $form;
	}

	private function signInFormSucceeded(Form $form, LoginFormData $data): void //moje vlastní třída LoginFormData
	{
		try {
			// 1. Ověříme heslo přes autentifikátor (manuálně bez volání $this->getUser()->login())
			$identity = $this->autentifikator->authenticate($data->username, $data->password);

			// 2. Zjistíme, zda má uživatel aktivní 2FA (např. má v DB uložený secret)
			$twoFactor = $identity->twoFactor ?? false;

			if ($twoFactor) {
				// Uživatel MÁ 2FA -> uložíme do session a jdeme na druhý krok
				$this->twoFactorSession->identity = $identity;
				$this->twoFactorSession->setExpiration('5 minutes');
				$this->redirect('twoFactor');
			} else {
				// Uživatel NEMÁ 2FA -> přihlásíme ho hned
				$this->getUser()->login($identity);
				$this->restoreRequest($this->backlink);
				$this->redirect(':Home:');
			}

		} catch (Nette\Security\AuthenticationException $e) {
			$form->addError('Neplatné jméno nebo heslo.');
		}
		// try {
		// 	$this->getUser()->setAuthenticator($this->autentifikator); // musíme ji registrovat!

		// 	// validace přihlášení je v třídě MujAutentifikator->authenticate(...)
		// 	$this->getUser()->login($data->username, $data->password);

		// 	// kam potom?
		// 	$this->restoreRequest($this->backlink); // vrátit se na požadovanou stránku
		// 	$this->redirect(':Home:'); // jinak přejdi sem
		// } catch (Nette\Database\ConnectionException) {
		// 	error_log("Obvody - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban)
		// 	$form->addError('Neplatné přihlášení.');
		// } catch (Nette\Security\AuthenticationException $e) {
		// 	error_log("Obvody - neplatne prihlaseni.", 0); //log je ve var/log/apache2/error.log (fail2ban)
		// 	$form->addError($e->getMessage());
		// }
	}

	protected function createComponentTwoFactorForm(): Form
	{
		$form = new Form();
		$form->addText('code', 'Ověřovací kód (OTP):')
			->setRequired()
			->addRule($form::Pattern, 'Kód musí mít 6 číslic', '\d{6}')
			->setHtmlAttribute('placeholder', '000 000')
			->setHtmlAttribute('autocomplete', 'one-time-code');
		$form->addSubmit('verify', 'Ověřit a přihlásit');
		$form->onSuccess[] = $this->twoFactorFormSucceeded(...);
		return $form;
	}

	private function twoFactorFormSucceeded(Form $form, \stdClass $data): void
	{
		/**
		 * Uživatelská identita = přihlášený user.
		 * @var UserIdentity
		 */
		$identity = $this->twoFactorSession->identity;

		if (!$identity) {
			$this->redirect('in');
		}

		bdump($identity);

		// Předpokládáme, že secret je uložen v identitě (z DB)
		$secret = $identity->totpSecret ?? null;

		if ($this->twoFactorService->verifyCode($secret, $data->code)) {
			// KÓD JE SPRÁVNÝ -> Přihlásíme uživatele do Nette nativně
			$this->getUser()->login($identity);

			// Vyčistíme dočasnou session
			$this->twoFactorSession->remove();

			$this->restoreRequest($this->backlink);
			$this->redirect(':Home:');
		} else {
			$form->addError('Neplatný ověřovací kód.');
		}
	}

	public function renderTwoFactor(): void
	{
		if (!$this->twoFactorSession->identity) {
			$this->redirect('in');
		}
	}

	public function renderIn(): void
	{
	}

	/**
	 * Normalní logout.
	 * @return void
	 */
	public function actionOut(): void
	{
		$this->getUser()->logout();
		$this->flashMessage('Odhlášení bylo úspěšné.');
		$this->redirect('Sign:in');
	}
}