<?php

declare(strict_types=1);

namespace app\models;

use yii;
use yii\base\Model;

use app\models\Account;
use Exception;

/**
 * AccountForm is the model behind the login form.
 *
 * @property-read Account|null $account This property is read-only.
 *
 */
class AccountForm extends Model
{
    const SCENARIO_REGISTRATION = 'registration';
    const SCENARIO_REGISTRATION_END = 'registration_end';
    const SCENARIO_AUTHENTICATION = 'authentication';

    public $mail;
    public $pswd;
    public $auto = false;
    public $rept;
    public $pols;

    private $account = false;


    public function rules()
    {
        return [
            // Обязательные поля
            [
                [
                    'mail',
                ],
                'required',
                'message' => 'Заполните поле'
            ],
            // Обязательные поля для аутентификации
            [
                [
                    'pswd',
                ],
                'required',
                'message' => 'Заполните поле',
                'on' => self::SCENARIO_AUTHENTICATION
            ],
            // Функция "Запомнить меня"
            [
                'auto',
                'boolean',
                'on' => self::SCENARIO_AUTHENTICATION
            ],
            // Проверка почты,
            [
                'mail',
                'email',
                'message' => 'Проверьте почту'
            ],
            [
                'mail',
                'validateMail',
                'on' => self::SCENARIO_REGISTRATION
            ],
            // Проверка пароля
            [
                'pswd',
                'validatePassword',
                'on' => self::SCENARIO_AUTHENTICATION
            ]
        ];
    }

    public function attributeLabels()
    {
        return [
            'mail' => 'Почта',
            'pswd' => 'Пароль',
            'auto' => '<i class="fas fa-unlock"></i>',
            'pols' => 'Политика конфедециальности'
        ];
    }

    public function validateMail($attribute, $params)
    {
        if (!$this->hasErrors()) {
            // Проблем нет, обрабатывается событие регистрации

            $account = $this->getAccount();

            if (is_null($account)) {
                // Не удалось проверить аккаунт

                return;
            }

            if (!$account || $account->validateMail($this->mail)) {
                // Проверка не пройдена

                $this->addError($attribute, 'Почта уже привязана');
            }
        }
    }

    public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            // Проблем нет, обрабатывается событие аутентификации

            $account = $this->getAccount();

            if (is_null($account)) {
                // Не удалось проверить аккаунт

                return;
            }

            if ($account) {
                // Удалось инициализировать аккаунт

                try {
                    if (!$account->validatePasswordWithHash($this->pswd)) {
                        // Не пройдена проверка с хешем

                        throw new exception;
                    }
                } catch (Exception $e) {
                    // Не пройдена проверка с хешем

                    try {
                        if (!$account->validatePasswordWithoutHash($this->pswd)) {
                            // Не пройдена проверка с паролем

                            throw new exception;
                        }
                    } catch (Exception $e) {
                        // Проверка без хеша не пройдена

                        $this->addError($attribute, 'Проверьте пароль');
                    }
                }
            } else {
                $this->addError($attribute, 'Не удалось идентифицировать аккаунт');
            }
        }
    }

    /**
     * Logs in a account using the provided accountname and password.
     * @return bool whether the account is logged in successfully
     */
    public function authentication(string $mail = null, string $pswd = null)
    {
        if (isset($mail, $pswd)) {
            $this->mail = $mail;
            $this->pswd = $pswd;
        }

        // Регистронезависимая почта
        $this->mail = mb_strtolower($this->mail);

        if (isset($this->mail, $this->pswd) && $this->validate()) {
            // Проверка пройдена

            // Аутентификация
            return yii::$app->user->login($this->getAccount(), $this->auto ? 3600 * 24 * 30 : 0);
        }

        return false;
    }

    /**
     * @return bool
     */
    public function registration()
    {
        // Инициализация нового аккаунта
        $this->account = new Account();

        if ($this->validate()) {
            // Проверка пройдена

            // Запись параметров
            $this->account->mail = $this->mail;
            // $this->account->pswd = yii::$app->security->generatePasswordHash(Account::passwordGenerate());
            $this->account->pswd = $this->pswd = Account::passwordGenerate();

            if (($account = Account::findByMail($this->mail)) || isset($account) && $account->vrfy !== true) {
                // Аккаунт найден, но не подтверждён

                // Удаление аккаунта (сейчас его создадим снова)
                $account->delete();
            }

            // Регистрация
            if ($this->account->save()) {
                // Успешно завершена регистрация или обновлены данные не до конца зарегистрировавшегося пользователя

                // Генерация индекса
                Account::generateIndexes([$this->account]);

                // Отправка письма для подтверждения почты
                $this->account->sendMailVerify();

                return true;
            }
        }

        return false;
    }

    /**
     * Finds account by [[accountname]]
     *
     * @return Account|null
     */
    public function getAccount()
    {
        if ($this->account === false) {
            $this->account = Account::findByMail($this->mail);
        }

        return $this->account;
    }
}
