<?php

namespace app\controllers;

use Yii;
use app\models\Users;
use app\models\UsersSearch;
use app\models\EmailTemplates;
use app\models\Settings;
use app\models\LoginAttempts;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;

class UsersController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'rules' => [
                    [
                        'allow' => true,
                        'actions' => ['login', 'signup', 'forgot-password', 'reset-password'],
                        'roles' => ['?']
                    ],
                    [
                        'allow' => true,
                        'actions' => ['logout', 'change-password'],
                        'roles' => ['@']
                    ],
                    [
                        'allow' => true,
                        'actions' => ['index', 'create', 'update', 'delete', 'view', 'change-role', 'change-status',
                            'change-username', 'change-user-password'],
                        'roles' => ['Admin']
                    ]
                ],
                'denyCallback' => function(){
                    if(Yii::$app->user->isGuest){
                        return Yii::$app->response->redirect(['/users/login']);
                    }
                    else{
                        return Yii::$app->response->redirect(['/dashboard/index']);
                    }
                }
            ],
            'verbs' => [
                'class' => VerbFilter::class,
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    public function actions(){
        return [
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction'
            ]
        ];
    }

    public function actionIndex()
    {
        $searchModel = new UsersSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
        $dataProvider->setSort([
            'attributes' => [
                'id',
                'username',
                'email',
                'status',
                'role' => [
                    'asc' => ['auth_assignment.item_name' => SORT_ASC],
                    'desc' => ['auth_assignment.item_name' => SORT_DESC]
                ]
            ]
        ]);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    public function actionCreate()
    {
        $model = new Users();

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('create', [
            'model' => $model,
        ]);
    }

    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

    public function actionDelete($id)
    {
        $this->findModel($id)->delete();

        return $this->redirect(['index']);
    }

    protected function findModel($id)
    {
        if (($model = Users::findOne($id)) !== null) {
            return $model;
        }

        throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
    }

    public function actionSignup(){
        $model = new Users();
        $model->scenario = Users::SCENARIO_SIGNUP;

        if($model->load(Yii::$app->request->post())){
            if($model->save()){
                if($this->checkSendEmailSetting()){
                    $email_template = EmailTemplates::findOne(['dedicated_for' => 'EMAIL_TEMPLATE_WELCOME_MESSAGE_WHEN_SIGNUP']);
                    if($email_template && $email_template->is_active == 1){
                        $content = $email_template->content;
                        $template_variables = $email_template->variables;
                        if($template_variables != null){
                            foreach($template_variables as $variable){
                                $code = $variable->variable->var_code;
                                EmailTemplates::replaceVariablesCode($content, $code, null, null, null, null, $model);
                            }
                        }

                        $this->sendEmail($model->email, $content, 'مرحباً بكم في مشروع تدريب بنك البركة');
                    }
                }

                Yii::$app->user->login($model);
                $auth = Yii::$app->authManager;
                $auth->assign($auth->getRole('User'), $model->id);
                return $this->redirect(['training-requests/create']);
            }
        }

        return $this->render('signup', ['model' => $model]);
    }

    public function checkIfLoginAttemptsExceedSettings($ip_address){
        $login_attempt_count = Settings::findOne(['name' => 'login_attempt_count']);
        $login_attempt_duration = Settings::findOne(['name' => 'login_attempt_duration_in_seconds']);
        if($login_attempt_count && $login_attempt_duration){
            $attempts_count = LoginAttempts::find()
                ->where(['ip_address' => $ip_address])
                ->andWhere(['>=', 'UNIX_TIMESTAMP(attempt_date)', strtotime(date('Y-m-d H:i:s', strtotime("- {$login_attempt_duration->value} seconds", time())))])
                ->count();
            if($attempts_count >= $login_attempt_count->value){
                return true;
            }
        }
        return false;
    }

    public function actionLogin(){
        $model = new Users();
        $model->scenario = Users::SCENARIO_LOGIN;

        $ip_address = $_SERVER['REMOTE_ADDR'];
        $can_try_login = true;
        if($this->checkIfLoginAttemptsExceedSettings($ip_address)){
            $can_try_login = false;
        }
        else{
            if($model->load(Yii::$app->request->post())){
                $identity = Users::find()
                    ->where(['email' => $model->email])
                    ->one();
                // $identity->password == hash('md5', $model->password)
                // if($identity && Yii::$app->getSecurity()->validatePassword($model->password, $identity->password)){
                if($identity && $identity->password == hash('md5', $model->password)){
                    if($identity->status == 'Inactive'){
                        Yii::$app->session->setFlash('inactive_account', Yii::t('app', 'Inactive Account'));
                    }
                    else{
                        $user = Yii::$app->user;
                        $user->login($identity);
                        LoginAttempts::deleteAll(['ip_address' => $ip_address]);
                        return $this->redirect(['/dashboard/index']);
                    }
                }
                else{
                    Yii::$app->session->setFlash('incorrect_login', Yii::t('app', 'Incorrect Credentials'));
                    $login_attempt = new LoginAttempts();
                    $login_attempt->attributes = [
                        'ip_address' => $ip_address,
                        'attempt_date' => date('Y-m-d H:i:s')
                    ];
                    $login_attempt->save();
                    if($this->checkIfLoginAttemptsExceedSettings($ip_address)){
                        $can_try_login = false;
                    }
                }
            }
        }

        return $this->render('login', [
            'model' => $model,
            'can_try_login' => $can_try_login,
        ]);
    }

    public function actionLogout(){
        Yii::$app->user->logout();
        return $this->redirect(['login']);
    }

    public function actionChangeUserPassword($id){
        $model = $this->findModel($id);
        $model->scenario = Users::SCENARIO_CHANGE_USER_PASSWORD;

        if($model->load(Yii::$app->request->post())){
            if($model->save()){
                Yii::$app->session->setFlash('change-password', Yii::t('app', 'The password has changed successfully'));
                return $this->redirect(['view', 'id' => $model->id]);
            }
            return var_dump($model->getErrors());
        }

        return $this->render('change-user-password', ['model' => $model]);
    }

    public function actionChangeUsername($id){
        if(Yii::$app->request->isAjax){
            $data = Yii::$app->request->get();
            $username = $data['Users']['username'];
            $model = Users::findOne($id);
            if($model){
                $model->scenario = Users::SCENARIO_CHANGE_USERNAME;
                $model->username = $username;
                Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
                if($model->save()){
                    return ['status' => true, 'data' => Yii::t('app', 'The status has changed successfully')];
                }
                else{
                    return ['status' => false, 'message' => $model->getErrors()['username'][0]];
                }
            }
            return ['status' => true, 'error' => Yii::t('app', 'No Such User')];
        }
    }

    public function actionChangeStatus($id){
        if(Yii::$app->request->isAjax){
            $data = Yii::$app->request->get();
            $status = $data['Users']['status'];
            $model = Users::findOne($id);
            if($model){
                $model->scenario = Users::SCENARIO_CHANGE_STATUS;
                $model->status = $status;
                if($model->save()){
                    Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
                    return ['status' => true, 'data' => Yii::t('app', 'The status has changed successfully')];
                }
                else{
                    var_dump($model->getErrors());
                }
            }
            return ['status' => true, 'error' => Yii::t('app', 'No Such User')];
        }
    }

    public function actionChangeRole($id){
        if(Yii::$app->request->isAjax){
            $data = Yii::$app->request->get();
            $role = $data['Users']['_role'];
            $model = Users::findOne($id);
            if($model){
                $auth = Yii::$app->authManager;
                $auth->revokeAll($model->id);
                $auth->assign($auth->getRole($role), $model->id);
                Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
                return ['status' => true, 'data' => Yii::t('app', 'The role has changed successfully')];
            }
            return ['status' => true, 'error' => Yii::t('app', 'No Such User')];
        }
    }

    public function actionForgotPassword(){
        $model = new Users();
        $model->scenario = Users::SCENARIO_FORGOT_PASSWORD;

        if($model->load(Yii::$app->request->post())){
            $identity = Users::findOne(['email' => $model->email]);
            if(! $identity){
                Yii::$app->session->setFlash('email_not_exist', Yii::t('app', 'Email Not Exist'));
                return $this->render('forgot-password', [
                    'model' => $model
                ]);
            }

            $identity->reset_password = str_replace('#', '_', Yii::$app->security->generateRandomString(60));
            if($identity->save()){
                if($this->checkSendEmailSetting()){
                    $email_template = EmailTemplates::findOne(['dedicated_for' => 'EMAIL_TEMPLATE_RESET_PASSWORD']);
                    if($email_template && $email_template->is_active == 1){
                        $content = $email_template->content;
                        $template_variables = $email_template->variables;
                        if($template_variables != null){
                            foreach($template_variables as $variable){
                                $code = $variable->variable->var_code;
                                EmailTemplates::replaceVariablesCode($content, $code, null, null, null, null, $identity);
                            }
                        }

                        $this->sendEmail($identity->email, $content, 'استعادة كلمة المرور');
                    }
                }
                
                Yii::$app->session->setFlash('reset_password_token_sent', Yii::t('app', 'Reset password token has been sent'));
                return $this->redirect(['login']);
            }
            return var_dump($identity->getErrors());
        }

        return $this->render('forgot-password', [
            'model' => $model
        ]);
    }

    public function actionResetPassword($token){
        $model = Users::findOne(['reset_password' => $token]);
        if(! $model){
            Yii::$app->session->setFlash('invalid_token', Yii::t('app', 'Invalid Token'));
            return $this->render('reset-password', [
                'model' => null
            ]);
        }

        $model->scenario = Users::SCENARIO_RESET_PASSWORD;

        if($model->load(Yii::$app->request->post())){
            $model->reset_password = null;
            if($model->save()){
                Yii::$app->session->setFlash('password_has_been_reset', Yii::t('app', 'Password has been reset'));
                return $this->redirect(['login']);
            }
            return var_dump($model->getErrors());
        }

        return $this->render('reset-password', [
            'model' => $model
        ]);
    }

    public function actionChangePassword(){
        $model = Users::findOne(Yii::$app->user->getId());
        $model->scenario = Users::SCENARIO_CHANGE_PASSWORD;
        $old_password = $model->password;

        if($model->load(Yii::$app->request->post())){
            // if(! Yii::$app->getSecurity()->validatePassword($model->old_password, $old_password)){
            if(hash('md5', $model->old_password) != $old_password){
                Yii::$app->session->setFlash('incorrect_old_password', Yii::t('app', 'Incorrect old password'));
                return $this->render('change-password', [
                    'model' => $model
                ]);
            }

            if($model->save()){
                Yii::$app->session->setFlash('password_changed_successfully', Yii::t('app', 'Password changed successfully'));
                return $this->redirect(['change-password']);
            }
        }

        return $this->render('change-password', [
            'model' => $model
        ]);
    }

    public function checkSendEmailSetting(){
        $sending_emails_setting = Settings::findOne(['name' => 'sending_emails']);
        if($sending_emails_setting && $sending_emails_setting->value == 1){
            return true;
        }
        return false;
    }

    public function sendEmail($email, $content, $subject){
        Yii::$app->mailer->compose('mail', ['content' => $content])
            ->setFrom(Yii::$app->params['emailToSendMails'])
            ->setTo($email)
            ->setSubject($subject)
            ->send();
    }
}
