<?php

namespace Mnv\Modules\User;

use Mnv\Core\Config;
use Mnv\Core\Locale\I18N;
use Mnv\Core\Auth\Errors\AuthError;
use Mnv\Core\Auth\Exceptions\EmailNotPaidException;
use Mnv\Core\Auth\Exceptions\InvalidEmailException;
use Mnv\Core\Auth\Exceptions\TokenExpiredException;
use Mnv\Core\Auth\Exceptions\ResetDisabledException;
use Mnv\Core\Auth\Exceptions\TooManyRequestsException;
use Mnv\Core\Auth\Exceptions\InvalidPasswordException;
use Mnv\Core\Auth\Exceptions\EmailNotVerifiedException;
use Mnv\Core\Auth\Exceptions\AttemptCancelledException;
use Mnv\Core\Auth\Exceptions\DuplicateUsernameException;
use Mnv\Core\Auth\Exceptions\UserAlreadyExistsException;
use Mnv\Core\Auth\Exceptions\ValidatePasswordException;
use Mnv\Core\Auth\Exceptions\InvalidSelectorTokenPairException;
use Mnv\Models\Users\UserTypes;

class Email extends User implements UserInterface
{

    public function __construct() {
        parent::__construct();
    }

    /**
     * Авторизация с помощью email адреса
     * @param $user
     */
    public function auth($user)
    {
        global $userAuth;

        if (isset($user['email'])) {
            if (!empty($user['email']) && !empty($user['password'])) {
                $rememberDuration = (isset($user['remember']) && $user['remember'] == 1) ? (int)(60 * 60 * 24 * 365.25) : null;
                try {
                    $userAuth->login($user['email'], $user['password'], $rememberDuration);
                    $this->response = array('status' => 200, 'type' => 'success',
                        'message' => I18N::locale(
                            "Добро пожаловать!",
                            "Xush kelibsiz!",
                            "Welcome!"
                        )
                    );
                } catch (InvalidEmailException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            'Проверьте правильность указаного e-mail адреса',
                            "Belgilangan elektron pochta manzili to'g'ri yoki yo'qligini tekshiring",
                            "Check if the specified e-mail address is correct"
                        )
                    );
                } catch (InvalidPasswordException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            "Вы ввели не правильный пароль",
                            "Siz noto'g'ri parol kiritdingiz",
                            "You entered the wrong password"
                        )
                    );
                } catch (EmailNotVerifiedException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            "Вы не подтвердили e-mail",
                            "Siz elektron pochtangizni tasdiqlamadingiz",
                            "You have not verified your email"
                        )
                    );
                } catch (TooManyRequestsException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            "Слишком много запросов",
                            "Juda ko'p so'rovlar",
                            "Too many requests"
                        )
                    );
                } catch (AuthError $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            "Ошибка авторизации",
                            "Avtorizatsiya xatosi",
                            "Authorisation Error"
                        )
                    );
                } catch (AttemptCancelledException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale(
                            "Попытка авторизации отменена",
                            "Avtorizatsiyaga urinish bekor qilindi",
                            "Authorization attempt canceled"
                        )
                    );
                }
            } else {
                $this->response =  array(
                    'status'=> 403, 'type'=> 'error',
                    'message'=> I18N::locale(
                        "Отправляемые данные не должны быть пустыми!",
                        "Taqdim etilgan ma'lumotlar bo'sh bo'lmasligi kerak!",
                        "Submitted data must not be empty!"
                    )
                );
            }
        } else {
            $this->response = array('status' => 403, 'type'=> 'error',
                'message' => I18N::locale(
                    "Авторизация пользователь должна производиться с помощью e-mail",
                    "Foydalanuvchi avtorizatsiyasi elektron pochta orqali amalga oshirilishi kerak",
                    "User authorization must be done using e-mail"
                )
            );
        }
    }

    /**
     * Регистрация пользователя (user)
     * @param $user
     * @throws AuthError
     */
    public function registration($user)
    {
        global $smarty, $userAuth;

        if (!empty($user)) {
            if (!empty($user['email'])) {
                try {
                    if ((int)Config::getValue('twoFactorAuth') === 1) {
                        $callback = function ($selector, $token) use ($smarty, $user) {  /** подтверждение через email */
                            $smarty->assign('userData', $user);
                            $smarty->assign('selector', \urlencode($selector));
                            $smarty->assign('token', \urlencode($token));
                            $htmlBody = $smarty->fetch('mail/activation-email.tpl');
                            $emailHide = $this->maskEmail($user['email']);

                            // todo: отправку на почту
                            if ($this->sendToEmail($user['email'], Config::getValue('website_name') ,'Код подтверждения регистрация', $htmlBody, true)) {
                                $this->response = array('status' => 200, 'type'=> 'success',
                                    'message' => I18N::locale(
                                        "Ув. " . $user['firstName'] . " " . $user['lastName'] . ", на Ваш email $emailHide отправлен код подтверждения!",
                                        "Hurmatli " . $user['firstName'] . " " . $user['lastName'] . ", $emailHide elektron pochtangizga tasdiqlash kodi yuborildi!",
                                        "Dear " . $user['firstName'] . " " . $user['lastName'] . ", a confirmation code has been sent to your email $emailHide!"
                                    )
                                );
                            } else {
                                $this->response = array('status' => 403, 'type'=> 'error', 'message' => $this->errors);
                            }
                        };
                    } else {
                        $callback = null;
                        $this->response = array('status' => 200, 'type'=> 'success',
                            'message' => I18N::locale("Добро пожаловать!", "Xush kelibsiz!", "Welcome!")
                        );
                    }

                    $userAuth->registerWithUniqueUsername('email', $user, UserTypes::CUSTOMER, 'email', (int)Config::getValue('twoFactorAuth'), $callback);

                }  catch (InvalidEmailException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale("Неверный e-mail адрес", "Yaroqsiz elektron pochta manzili", "Invalid email address")
                    );
                } catch (ValidatePasswordException $e) {
                    $this->response = array('status' => 403, 'type'=> 'error',
                        'message' => I18N::locale("Пароль не должен быть пустым или кол-во символов не должно быть меньше 3", "Siz noto'g'ri parolni kiritdingiz", 'You entered the wrong password')
                    );
                } catch (InvalidPasswordException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale("Неправильный пароль", "Yaroqsiz parol", "Invalid password")
                    );
                } catch (UserAlreadyExistsException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale('Пользователь уже существует', 'Foydalanuvchi allaqachon mavjud', 'User already exists')
                    );
                } catch (DuplicateUsernameException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale("Пользователь с таком e-mail адресом уже зарегистрирован", "Ushbu elektron pochta manziliga ega foydalanuvchi allaqachon ro'yxatdan o'tgan", 'User with this e-mail address is already registered')
                    );
                } catch (TooManyRequestsException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale('Слишком много запросов', 'Juda koʻp soʻrovlar', 'Too many requests')
                    );
                } catch (AuthError $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error', 'message'=> $e->getMessage());
                }
            } else {
                $this->response =  array('status'=> 403, 'type'=> 'error',
                    'message'=> I18N::locale("Поле e-mail не должно быть пустым!", "Elektron pochta maydoni bo'sh bo'lmasligi kerak!", "The email field must not be empty!")
                );
            }
        } else {
            $this->response = array('status' => 403, 'type'=> 'error',
                'message'=> I18N::locale("Отправленные данные пусты!", "Yuborilgan maʼlumotlar boʻsh!", "Sent data is empty!")
            );
        }
    }

    /**
     * Подтверждение регистрации через email
     * @param $selector
     * @param $token
     */
    public function confirmEmail($selector, $token)
    {
        global $userAuth;

        if(!empty($selector) && !empty($token)) {

            try {
                $userAuth->confirmEmailAndSignIn($selector, $token, null);
                $this->response = array(
                    'status' => 200, 'type'=> 'error',
                    'message'=> I18N::locale("Добро пожаловать!", "Xush kelibsiz!", "Welcome!"),
                );
            } catch (AuthError $e) {
            } catch (InvalidSelectorTokenPairException $e) {
                $this->response = array(
                    'status' => 403, 'type'=> 'error',
                    'message'=> I18N::locale("Отправленные данные пусты!", "Yuborilgan ma'lumotlar boʻsh!", "Sent data is empty!"),
                );
            } catch (TokenExpiredException $e) {
                $this->response = array(
                    'status' => 403, 'type'=> 'error',
                    'message'=> I18N::locale("Отправленные данные пусты!", "Yuborilgan ma'lumotlar boʻsh!", "Sent data is empty!"),
                );
            } catch (TooManyRequestsException $e) {
                $this->response =  array(
                    'status'=> 403, 'type'=> 'error',
                    'message'=> I18N::locale('Слишком много запросов', 'Juda koʻp soʻrovlar', 'Too many requests')
                );
            } catch (UserAlreadyExistsException $e) {
                $this->response =  array(
                    'status'=> 403, 'type'=> 'error',
                    'message'=> I18N::locale('Пользователь уже существует', 'Foydalanuvchi allaqachon mavjud', 'User already exists')
                );
            }

        } else {
            $this->response = array(
                'status' => 403, 'type'=> 'error',
                'message'=> I18N::locale("Отправленные данные пусты!", "Yuborilgan ma'lumotlar boʻsh!", "Sent data is empty!"),
            );
        }
    }

    /**
     * Восстановление пароля
     *
     * https://admin.panel.loc/recovery/?selector=3iWhDpDCbD4H88FlQvoR&token=ZVZBY9PAluYsaT09ihs3
     * @param $user
     * @throws AuthError
     */
    public function recoveryEmail($user)
    {
        global $smarty, $userAuth;

        if (!empty($user) && !empty($user['email'])) {
            if ((int)Config::getValue('twoFactorAuth') == 1) {
                try {
                    $userAuth->forgotPassword($user['email'], function ($selector, $token) use ($user, $smarty) {
                        $smarty->assign('userData', $user);
                        $smarty->assign('selector', \urlencode($selector));
                        $smarty->assign('token', \urlencode($token));
                        $htmlBody = $smarty->fetch('mail/recovery-email.tpl');
                        $emailHide = $this->maskEmail($user['email']);

                        // todo: отправка на почту
                        if (empty($feedback->errors) && $this->sendToEmail($user['email'], Config::getValue('website_name'), 'Восстановление пароля', $htmlBody, true)) {
                            $this->response = array('status' => 200, 'type'=> 'success',
                                'message' => I18N::locale(
                                    "На Ваш email $emailHide отправлен код подтверждения!",
                                    "Tasdiqlash kodi $emailHide elektron pochtangizga yuborildi!!",
                                    "A confirmation code has been sent to your email $emailHide!"
                                )
                            );
                        } else {
                            $this->response = array('code' => 0, 'type'=> 'error', 'message' => $this->errors);
                        }

                    });
                }
                catch (InvalidEmailException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale(
                            "Проверьте правильность указаного e-mail адреса.",
                            "Belgilangan elektron pochta manzili to'g'ri yoki yo'qligini tekshiring.",
                            "Check if the specified e-mail address is correct."
                        )
                    );
                }
                catch (EmailNotPaidException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale(
                            "Не была призведена оплата",
                            "To'lov amalga oshirilmagan",
                            "Payment has not been made"
                        )
                    );
                }
                catch (EmailNotVerifiedException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale(
                            "Вы не подтвердили e-mail",
                            "Siz elektron pochtangizni tasdiqlamadingiz",
                            "You have not verified your email"
                        )
                    );
                }
                catch (ResetDisabledException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale(
                            "Сброс пароля отключен",
                            "Parolni tiklash o'chirilgan",
                            "Password reset is disabled"
                        )
                    );
                }
                catch (TooManyRequestsException $e) {
                    $this->response =  array('status'=> 403, 'type'=> 'error',
                        'message'=> I18N::locale(
                            'Слишком много запросов',
                            'Juda koʻp soʻrovlar',
                            'Too many requests'
                        )
                    );
                }
            }

        } else {
            $this->response =  array('status'=> 403, 'type'=> 'error',
                'message'=> I18N::locale(
                    "Отправленные данные пусты!",
                    "Yuborilgan maʼlumotlar boʻsh!",
                    "Sent data is empty!"
                )
            );
        }
    }

    /**
     * Подтверждение восстановление пароля
     *
     * @param $user
     * @throws AuthError
     */
    public function recoveryConfirmEmail($user)
    {
        global $userAuth;

        if (!empty($user['selector']) && !empty($user['token'])) {
            try {
                $userAuth->resetPassword($user['selector'], $user['token'], $user['newPassword']);
                $this->response = array('status' => 200, 'type'=> 'success',
                    'message' => I18N::locale(
                        "Ваш пароль успешно изменен, теперь можете войти.",
                        "Parolingiz muvaffaqiyatli o'zgartirildi, endi tizimga kirishingiz mumkin.",
                        "Your password has been successfully changed, you can now log in."
                    )
                );
            } catch (InvalidSelectorTokenPairException $e) {
                $this->response = array('status' => 403, 'type'=> 'error',
                    'message' => I18N::locale(
                        'Недействительный токен',
                        'Yaroqsiz token',
                        'Invalid token'
                    )
                );
            } catch (TokenExpiredException $e) {
                $this->response = array('status' => 403, 'type'=> 'error',
                    'message' => I18N::locale(
                        'Срок действия токена истек',
                        'Token muddati tugagan',
                        'Token expired'
                    )
                );
            } catch (ResetDisabledException $e) {
                $this->response = array('status' => 403, 'type'=> 'error',
                    'message' => I18N::locale(
                        'Сброс пароля отключен',
                        'Parolni tiklash o\'chirilgan',
                        'Password reset is disabled'
                    )
                );
            } catch (InvalidPasswordException $e) {
                $this->response = array('status' => 403, 'type'=> 'error',
                    'message' => I18N::locale(
                        'Неверный пароль',
                        'Yaroqsiz parol',
                        'Invalid password'
                    )
                );
            } catch (TooManyRequestsException $e) {
                $this->response = array('status' => 403, 'type'=> 'error',
                    'message' => I18N::locale(
                        "Слишком много запросов",
                        "Juda koʻp soʻrovlar",
                        "Too many requests"
                    )
                );
            }
        }
    }
}