<?php

namespace Mnv\Admin\Controllers;

use Mnv\Core\Config;
use Mnv\Core\Database\Throwable\IntegrityConstraintViolationException;
use Mnv\Core\Design;
use Mnv\Core\UserInfo;

use Mnv\Core\Auth\Administration;
use Mnv\Core\Auth\Errors\AuthError;
use Mnv\Core\Auth\Errors\UsernameRequiredError;
use Mnv\Core\Auth\Exceptions\UserRoleExistsException;
use Mnv\Core\Auth\Exceptions\InvalidPasswordException;
use Mnv\Core\Auth\Exceptions\TooManyRequestsException;
use Mnv\Core\Auth\Exceptions\UnknownUsernameException;
use Mnv\Core\Auth\Exceptions\AttemptCancelledException;
use Mnv\Core\Auth\Exceptions\EmailNotVerifiedException;
use Mnv\Core\Auth\Exceptions\ValidatePasswordException;
use Mnv\Models\Users\UserGroups;

/**
 * Class AuthAdmin
 * @package Mnv\Admin\Controllers
 */
class AuthAdmin
{
    private Administration $authAdmin;
    private $smarty;

    private $login;
    private int $limit_error = 10;

    private ?int $rememberDuration;

    public array $errors = array();
    public array $messages = array();

    /**
     * Login constructor.
     */
    public function __construct()
    {

        try {
            $this->authAdmin = new Administration(UserInfo::get_ip(), true, 60 * 5);
            $this->smarty    = Design::init()->design();
            loadLanguage(Config::init()->get('admin_language'));

            $action      = request('action');
            $this->login = request('login','');

//            print_r($this->login);
            if ($this->authAdmin->getUserBanned()) {
                $this->numberAttempts($this->authAdmin->getBanned());
            }

            if (isset($this->login['remember']) && $this->login['remember'] === 'on') {
                // оставаться в системе в течение одного года
                $this->rememberDuration = (int) (60 * 60 * 24 * 365.25);
            } else {
                // не оставаться в системе после окончания сеанса
                $this->rememberDuration = null;
            }

            if (!empty($action)) {
                if ($action === 'login') {
                    $this->adminLogin($this->authAdmin);
                } else if ($action === 'logout') {
                    $this->logout($this->authAdmin);
                }
            }

            $this->smarty->assign('login', $this->login);

            if (!empty($this->errors)) {
                $this->smarty->assign('errors', $this->errors);
            }
            if (!empty($this->messages)) {
                $this->smarty->assign('messages', $this->messages);
            }

        } catch (IntegrityConstraintViolationException | AuthError $e) {
            $this->smarty->assign('errors', $e->getMessage());
        }
    }


    /**
     * @param Administration $authAdmin
     */
    public function adminLogin(Administration $authAdmin): void
    {
        try {
            $this->login['loginName'] = htmlspecialchars($this->login['loginName']);
            $this->login['password']  = htmlspecialchars($this->login['password']);

            $authAdmin->login($this->login['loginName'], $this->login['password'], $this->rememberDuration);

            $this->redirectRoleAdmin($authAdmin);

        }  catch (UsernameRequiredError $e) {
            $this->errors[] = lang('login:errors:5'); //lang('login:errors:0');
        } catch (UnknownUsernameException|InvalidPasswordException $e) {
                $this->authAdmin->insert_history($this->login['loginName'], 0, 'login', 'error');
            if ($this->authAdmin->getUserBanned()) $authAdmin->setBanned();
            $this->errors[] = 'Incorrect username or password.'; // Вы ввели неверный логин или пароль. Пожалуйста, попробуйте еще раз.
        }  catch (ValidatePasswordException $e) {
            $this->errors[] = lang('login:errors:6');
        } catch (EmailNotVerifiedException $e) {
            $this->errors[] =  'Email has not been confirmed'; //'Email не подтвержден';
        } catch (UserRoleExistsException $e) {
            if ($this->authAdmin->getUserBanned()) $authAdmin->setBanned();
            $this->errors[] = 'There is no access for this account'; //'Нет доступа для этого аккаунта';
        } catch (TooManyRequestsException $e) {
            if ($this->authAdmin->getUserBanned()) $this->authAdmin->setUserBanned();
            $this->errors[] = 'Too many requests';//'Слишком много запросов';
        } catch (AuthError|AttemptCancelledException $e) {
            $this->errors[] = $e->getMessage();
        }
    }

    /**
     * @param Administration $authAdmin
     */
    private function redirectRoleAdmin(Administration $authAdmin): void
    {
        if ($authAdmin->hasAnyRole(array_keys(UserGroups::arrayGroup()))) {
            redirect('/admin/main');
        }
    }

    /**
     * Выход
     * @param Administration $authAdmin
     */
    public function logout(Administration $authAdmin): void
    {
        $authAdmin->logOut();
        if (!$authAdmin->check()) {
            redirect('/admin/auth');
        }
    }


    /**
     * Проверка на количество попыток
     * @param $number
     */
    public function numberAttempts($number): void
    {
        if (!empty($number)) {
            $limit_cnt = $this->limit_error - $number;
            if ($number >= 0 && $number <= 8) {
                $this->smarty->assign('error_message', 'auth_wrong');
                $this->smarty->assign('limit_cnt', $limit_cnt);
            } else if ($number === 9) {
//                $this->smarty->assign('message_limit', "Осталась последняя попытка!<br>Советуем не тратить свое время)");
                $this->smarty->assign('message_limit', "There is one last attempt left! We advise you not to waste your time)");
            } else if ($number === 10) {
                $this->authAdmin->setUserBanned();
                $this->smarty->assign('isBanned', 'banned_message');
            }
        }
    }

    public function fetch()
    {
//        print_r($_SESSION);
        if ($this->authAdmin->isLoggedIn()) {
            $this->redirectRoleAdmin($this->authAdmin);
        }

        try {
            return $this->smarty->fetch('views/auth/index.tpl');
        } catch (\SmartyException | \Exception $e) {
            print $e->getMessage();
        }
    }

}









