<?php
namespace frontendApi\modules\v1\models;

use common\components\Model;
use common\helpers\Date;
use common\libs\LoginIpChecker;
use common\models\BaUser;
use common\models\BaUserInfo;
use common\models\UserInfo;
use ReflectionProperty;
use Yii;
use yii\base\Exception;
use yii\captcha\Captcha;
use common\libs\logging\login\UserLogin as UserLoginLogger;
use \frontendApi\modules\v1\models\brand\User as Brand;

/**
 * Login form
 */
class LoginForm extends Model
{
    public $userName;
    public $password;
    public $verifyCode;
    public $rememberMe = true;
    public $version;

    private $_user;
    private $_userInfo;
    private $_whetherBA;

    const ERROR_IS_MODIFY_PASSWORD = 'ERROR_IS_MODIFY_PASSWORD';

    const FRONTEND_LOGIN_FAIL_TIMES = 'frontend:loginFail:times_%s';


    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            // username and password are both required
            [['userName', 'password'], 'required', 'on'=>['login', 'loginVerify']],
            [['verifyCode'], 'required', 'on'=>['loginVerify']],
            // rememberMe must be a boolean value
            ['rememberMe', 'boolean'],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
            ['verifyCode', 'captcha', 'captchaAction'=>'/v1/site/captcha', 'on'=>['loginVerify']],
        ];
    }

    /**
     * Validates the password.
     * This method serves as the inline validation for password.
     *
     * @param string $attribute the attribute currently being validated
     * @param array $params the additional name-value pairs given in the rule
     */
    public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            $user = $this->getUser();
            if(!$user){
                $this->addError($attribute, 'Member name error');// 用户名错误
            } else {

//                $userInfo = UserInfo::findOneAsArray('USER_ID=:USER_ID', [':USER_ID'=>$user['ID']]);
//                if($userInfo['CLOSE_LOGIN'] == 1){
//                    $this->addError($attribute, '会员已被禁止登录');
//                    return ;
//                }
            }
        }
    }

    /**
     * 更新失败次数
     * @param $transaction
     * @param $returnResult
     * @throws \Exception
     */
    private function _updateFailTimes($transaction,$returnResult){
        $userInfo = UserInfo::findOneAsArray('USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        if ($userInfo['FAIL_NUMS'] > 0) {
            UserInfo::updateAllCounters([
                'FAIL_NUMS' => 1,
            ], 'USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        } else {
            UserInfo::updateAll(['FAIL_NUMS' => 1], 'USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        }

        $transaction->commit();

        $cacheKey = sprintf(self::FRONTEND_LOGIN_FAIL_TIMES, $this->userName);
        Yii::$app->tokenRedis->incr($cacheKey);

        if(isset($this->_user)){
            UserLoginLogger::fail($this->_userInfo,$returnResult);
        }
    }

    /**
     * 更新成功次数
     */
    private function _updateSuccessTimes(){
        $cacheKey = sprintf(self::FRONTEND_LOGIN_FAIL_TIMES, $this->userName);
        Yii::$app->tokenRedis->del($cacheKey);

        $userInfo = UserInfo::findOneAsArray('USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        if ($userInfo['FAIL_NUMS'] > 0) {
            UserInfo::updateAllCounters([
                'LOGIN_NUMS' => 1,
            ], 'USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        } else {
            UserInfo::updateAll(['LOGIN_NUMS' => 1], 'USER_NAME=:USER_NAME', ['USER_NAME' => $this->userName]);
        }
    }

    /**
     * 登录
     * @return array|bool
     * @throws \yii\base\Exception
     * @throws \yii\db\Exception
     */
    public function login(){
        if(!$this->validate()){
            return false;
        }
        $transaction = \Yii::$app->db->beginTransaction();
        try{
            $this->getUser();
            if(!$this->_user){
                throw new Exception(Yii::t('app', 'accountDoesNotExist'));
            }

            if (!$this->_user->validatePassword($this->password)) {
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberNameOrPasswordIncorrect'));
                throw new Exception(Yii::t('app', 'memberNameOrPasswordIncorrect'));
            }
            // 找到会员的基本信息来判断其是否可登录
            if(!$this->_user['ALLOW_LOGIN']){
                $this->_updateFailTimes($transaction,Yii::t('app', 'abnormalMemberCode'));
                throw new Exception(Yii::t('app', 'abnormalMemberCode'));
            }
            if($this->_user['STATUS'] == Yii::$app->params['userStatus'][0]['value']){
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberNotActivated'));
                throw new Exception(Yii::t('app', 'memberNotActivated'));
            } elseif($this->_user['STATUS'] == Yii::$app->params['userStatus'][2]['value']){
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberHasBeenCancelled'));
                throw new Exception(Yii::t('app', 'memberHasBeenCancelled'));
            } elseif($this->_user['STATUS'] == Yii::$app->params['userStatus'][3]['value']){
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberHasBeenBlacklisted'));
                throw new Exception(Yii::t('app', 'memberHasBeenBlacklisted'));
            } elseif($this->_user['STATUS'] == Yii::$app->params['userStatus'][9]['value']){
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberHasBeenPermanentlySuspended'));
                throw new Exception(Yii::t('app', 'memberHasBeenPermanentlySuspended'));
            } elseif($this->_user['PART_FUNC_CLOSED'] == 1){
                $this->_updateFailTimes($transaction,Yii::t('app', 'memberPartOfFunctionClosed'));
                throw new Exception(Yii::t('app', 'memberPartOfFunctionClosed'));
            } elseif($this->_user['IS_MODIFY_PASSWORD'] == 1){
                throw new Exception(self::ERROR_IS_MODIFY_PASSWORD);
            }
            //验证IP
            /*$bindIp = trim($this->_user['BIND_IP']);
            if(!empty($bindIp) && !(new LoginIpChecker(Yii::$app->request->getUserIP(), $bindIp))->validate()){
                $this->_updateFailTimes($transaction,'登录IP与此账号绑定的IP不符');
                throw new Exception('登录IP与此账号绑定的IP不符'.$bindIp);
            }*/

            //更新clientid
            $clientId = Yii::$app->request->post('clientid');
            if( $clientId ) {
                $update = [
                    'BONUS_APP_CLIENT_ID' => $clientId,
                ];

//                if (!$this->_whetherBA) {
                    if (!User::updateAll($update, 'ID=:ID', ['ID' => $this->_user['ID']])) {
                        $this->_updateFailTimes($transaction, Yii::t('app', 'memberAppDeviceInformationUpdateFailed'));
                        throw new Exception(Yii::t('app', 'memberAppDeviceInformationUpdateFailed'));
                    }
//                } else {
//                    if (!BaUser::updateAll($update, 'ID=:ID', ['ID' => $this->_user['ID']])) {
//                        $this->_updateFailTimes($transaction, Yii::t('app', 'memberAppDeviceInformationUpdateFailed'));
//                        throw new Exception(Yii::t('app', 'memberAppDeviceInformationUpdateFailed'));
//                    }
//                }
            }


            $this->_updateSuccessTimes();
            $transaction->commit();

            UserLoginLogger::success($this->_userInfo, $this->version);

            // 把用户的登录时间存在操作时间里
            Yii::$app->tokenRedis->hset('user:timeOut', $this->_userInfo['USER_ID'], time());

//            if (!$this->_whetherBA) {
                return Yii::$app->user->loginWithUAndP($this->_user);
//            } else {
//                return Yii::$app->brand->loginWithUAndP($this->_user);
//            }
        }catch(\Exception $e){
            $transaction->rollBack();
//            $this->setError($e->getFile() . '  ' . $e->getLine() . '  ' . $e->getMessage());
            throw new Exception($e->getMessage());
        }
    }

    /**
     * Finds user by [[username]]
     *
     * @return User|null
     */
    public function getUser() {
        if ($this->_user === null) {
            $this->_user = User::findByUsername($this->userName);
            $this->_userInfo = UserInfo::findOne(['USER_NAME' =>$this->userName]);
            if (!$this->_user || !$this->_userInfo) {
                $this->_user = Brand::findByUsername($this->userName);
                $this->_userInfo = BaUserInfo::findOne(['USER_NAME' => $this->userName]);
                // 是否BA会员
                $this->_whetherBA = $this->_user && $this->_userInfo;
            }
        }
        return $this->_user;
    }

    /**
     * 登录是否需要验证
     * @return bool
     */
    public function isLoginVerify() {
        $cacheKey = sprintf(self::FRONTEND_LOGIN_FAIL_TIMES, $this->userName);
        $times = Yii::$app->tokenRedis->get($cacheKey);
        return $times && $times >= 3;
    }
}
