<?php

namespace common\models\forms;

use backendApi\modules\v1\models\Admin;
use common\components\Model;
use common\helpers\Date;
use common\helpers\Form;
use common\helpers\Tool;
use common\helpers\user\Balance;
use common\helpers\user\Cash;
use common\helpers\user\Info;
use common\libs\logging\operate\AdminOperate;
use common\models\BalanceAudit;
use common\models\DealType;
use common\models\User;
use common\models\UserBonus;
use common\models\UserInfo;
use common\models\UserWallet;
use common\models\Withdraw;
use yii\base\Exception;

/**
 * Login form
 */
class ChangeBalanceForm extends Model {
    public $id;
    public $selected;
    public $userName;
    public $realName;
    public $type;
    public $dealType;
    public $amount;
    public $remark;
    public $auditStatus;
    public $isShow;
    public $allowMinus;
    public $balanceCode;

    private $_model;
    private $_userId;

    public function init() {
        parent::init();
        $this->adminOperateLogger = new AdminOperate([
            'fetchClass' => UserBonus::class,
        ]);
    }

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['id', 'selected', 'userName', 'type', 'amount', 'remark', 'auditStatus', 'isShow', 'dealType', 'allowMinus'], 'trim'],
            [['id', 'userName', 'type', 'amount', 'remark', 'auditStatus', 'dealType','balanceCode'], 'required'],
            [['id'], 'exist', 'targetClass' => BalanceAudit::class, 'targetAttribute' => 'ID', 'message' => '余额变动申请不存在'],
            [['id'], 'initModel'],
            [['userName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME', 'message' => '会员不存在'],
            [['userName'], 'isUserName'],
            [['type'], 'isType'],
            [['dealType'], 'isDealType'],
            [['amount'], 'fullPrice'],
            [['amount'], 'isAmount'],
            [['auditStatus'], 'isStatus'],
            [['selected'], 'isSelected'],
            [['balanceCode'], 'validateRejectCode'],
        ];
    }

    /**
     * 指定场景
     * @return array
     */
    public function scenarios() {
        $parentScenarios = parent::scenarios();
        $customScenarios = [
            'changeAdd' => ['userName', 'type', 'amount', 'remark', 'isShow', 'dealType', 'balanceCode'],
            'changeAudit' => ['selected', 'allowMinus', 'remark', 'auditStatus', 'balanceCode'],
            'edit' => ['id', 'type', 'amount', 'remark', 'isShow', 'dealType'],
            'pass' => ['id', 'type', 'amount', 'auditStatus', 'remark', 'isShow', 'dealType', 'balanceCode'],
            'excelChangeBalance' => ['userName', 'realName', 'type', 'amount', 'dealType', 'remark', 'isShow'],
        ];
        return array_merge($parentScenarios, $customScenarios);
    }

    /**
     * @return array
     */
    public function attributeLabels() {
        return [
            'id' => '余额变动申请的ID',
            'userName' => '会员编号',
            'type' => '余额类型',
            'amount' => '变动金额',
            'remark' => '备注',
            'auditStatus' => '状态',
            'isShow' => '前台显示备注',
            'dealType' => '交易类型',
            'balanceCode' => '余额调整校验码',
        ];
    }

    /**
     * 初始化广告model类
     * @param $attribute
     */
    public function initModel($attribute) {
        $model = $this->_model = BalanceAudit::findOne(['ID' => $this->id]);
        $this->_userId = $model['USER_ID'];
        if ($model->AUDIT_STATUS > \Yii::$app->params['auditStatus']['un']['value']) {
            $this->addError($attribute, '该申请已经被审核，不能重复审核');
        }
    }

    /**
     * 设置userId
     * @param $attribute
     */
    public function isUserName($attribute) {
        $userInfo = UserInfo::find()->select('USER_ID')->where(['USER_NAME' => $this->userName])->asArray()->one();
        if ($userInfo) {
            $this->_userId = $userInfo['USER_ID'];
            if ($this->scenario == 'excelChangeBalance') {
                $realName = Info::getUserRealNameByUserId($this->_userId);
                if ($realName != $this->realName) {
                    $this->addError($attribute, '会员编号与会员姓名不匹配');
                }
            }
        } else {
            $this->addError($attribute, '会员不存在');
        }
    }

    /**
     * 校验余额类型
     * @param $attribute
     */
    public function isType($attribute) {
        if (!key_exists($this->type, BalanceAudit::TYPE)) {
            $this->addError($attribute, '余额类型不正确');
        }
        // 查看表里面是否有想同类型的未审核单，如果有的话，不允许再申请，需等审核完成以后，才能申请
        /*if(BalanceAudit::find()->where('USER_ID=:USER_ID AND TYPE=:TYPE AND STATUS=:STATUS', [':USER_ID'=>$this->_userId, ':TYPE'=>$this->type, ':STATUS'=>BalanceAudit::STATUS_APPLIED])->exists()){
            $this->addError($attribute, '已提交过该会员的其他余额调整申请，等待审核后，才可以申请新的余额调整申请');
        }*/
    }


    /**
     * 校验交易类型
     * @param $attribute
     */
    public function isDealType($attribute) {
        if (!key_exists($this->dealType, DealType::getTypes())) {
            $this->addError($attribute, '交易类型不正确');
        }
    }

    /**
     * 金额是否正确
     * @param $attribute
     */
    public function isAmount($attribute) {
        if ($this->amount == 0) $this->addError($attribute, '调整金额不能为0');
        if ($this->amount < 0 && $this->type == 'reconsume_points' && abs($this->amount) > Balance::getBalanceReconsumePoints($this->_userId)) {
            $this->addError('scenario', '会员复销点数余额不足，不允许调整');
        }
//        if ($this->amount < 0 && $this->type == 'lx' && abs($this->amount) > Balance::getBalanceLX($this->_userId)) {
//            $this->addError('scenario', '会员领袖分红余额不足，不允许调整');
//        }
    }

    /**
     * 校验状态
     * @param $attribute
     */
    public function isStatus($attribute) {
        // 获取当前提现单的状态
        $oneData = BalanceAudit::findOneAsArray(['ID' => $this->id]);
        if (empty($oneData) && empty($this->id) && !empty($this->selected)) {
            if (is_array($this->selected) && count($this->selected) == 1) {
                $oneData = BalanceAudit::findOneAsArray(['ID' => $this->selected[0]]);
            }
        }
        switch ($this->auditStatus) {
            case 'un':
                $this->addError($attribute, '不能设置为待审核状态' . $this->auditStatus);
                break;
            case 'true':
                if (isset($oneData['AUDIT_STATUS']) && $oneData['AUDIT_STATUS'] == \Yii::$app->params['auditStatus']['true']['value']) {
                    $this->addError($attribute, '已经审核通过不能重复审核');
                } elseif (isset($oneData['AUDIT_STATUS']) && $oneData['AUDIT_STATUS'] == \Yii::$app->params['auditStatus']['reject']['value']) {
                    $this->addError($attribute, '已经审核拒绝不能重复审核');
                }
                break;
            case 'reject':
                if ($oneData['AUDIT_STATUS'] == \Yii::$app->params['auditStatus']['true']['value']) {
                    $this->addError($attribute, '已经审核通过不能重复审核');
                } elseif ($oneData['AUDIT_STATUS'] == \Yii::$app->params['auditStatus']['reject']['value']) {
                    $this->addError($attribute, '已经审核拒绝不能重复审核');
                }
                break;
            default:
                $this->addError($attribute, '状态参数有误');
        }
    }

    public function validateRejectCode($attribute) {
        $adminId = \Yii::$app->user->id;
        $redisCode = \Yii::$app->redis->getset('balanceCode_'.$adminId,'');
        if ($this->balanceCode!=$redisCode) {
            $this->addError($attribute, '余额调整审核校验码失败');
        }
    }

    /**
     * 批量数据
     * @param $attributes
     */
    public function isSelected($attributes) {
        if (!$this->selected) {
            $this->addError($attributes, '必须选择一条数据');
        }
        if (!is_array($this->selected)) {
            $this->selected = [$this->selected];
        }
        $this->selected = array_unique($this->selected);
        if ($this->auditStatus == 'true') {
            foreach ($this->selected as $key => $select) {
                $model = BalanceAudit::findOne(['ID' => $select]);
                if (!$this->allowMinus) {
                    $oneUserBonusModel = UserBonus::findOneAsArray(['USER_ID' => $model->USER_ID]);
                    if ($model->AMOUNT < 0 && abs($oneUserBonusModel[strtoupper($model->TYPE)]) < abs($model->AMOUNT)) unset($this->selected[$key]);
                } else {
                    if (in_array($model->TYPE, ['cf', 'lx'])) {
                        $oneUserBonusModel = UserBonus::findOneAsArray(['USER_ID' => $model->USER_ID]);
                        if ($model->AMOUNT < 0 && abs($oneUserBonusModel[strtoupper($model->TYPE)]) < abs($model->AMOUNT)) unset($this->selected[$key]);
                    }
                }
                if ($model->AUDIT_STATUS > \Yii::$app->params['auditStatus']['un']['value']) unset($this->selected[$key]);
            }
        }
        $this->selected = array_values($this->selected);

        if (!$this->selected) {
            $this->addError($attributes, '没有符合条件的数据');
        }
    }

    /**
     * 添加变动申请
     * @return BalanceAudit|null
     * @throws \yii\db\Exception
     */
    public function changeAdd() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            // 添加申请
            $userInfo = Info::baseInfo($this->_userId);
            $model = new BalanceAudit();
            $model->USER_ID = $this->_userId;
            $model->LAST_DEC_LV = $userInfo['DEC_LV'];
            $model->LAST_EMP_LV = $userInfo['EMP_LV'];
            $model->LAST_DEC_ROLE_ID = $userInfo['DEC_ROLE_ID'];
            $model->TYPE = $this->type;
            $model->DEAL_TYPE = $this->dealType;
            $model->AMOUNT = $this->amount;
            $model->CREATE_REMARK = $this->remark;
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['un']['value'];
            $model->REMARK_IS_SHOW = $this->isShow;
            $model->UPDATE_ADMIN_ID = \Yii::$app->user->id;
            $model->CREATED_AT = Date::nowTime();

            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            $adminId = \Yii::$app->user->id;
            \Yii::$app->redis->del('balanceCode_'.$adminId);
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('changeAdd', $e->getMessage());
            return null;
        }

        // 记录日志
        $this->adminOperateLogger->fetchClass = BalanceAudit::class;
        $this->adminOperateLogger->afterInsert($model)->clean()->save([
            'optType' => '申请变动会员余额',
            'userId' => $model->USER_ID,
            'userName' => $userInfo['USER_NAME'],
            'remark' => $model->CREATE_REMARK,
        ]);

        return $model;
    }

    /**
     * 修改信息
     * @return null
     * @throws \yii\db\Exception
     */
    public function edit() {
        //关闭修改
        return null;
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = $this->_model;
            $model->TYPE = $this->type;
            $model->DEAL_TYPE = $this->dealType;
            $model->AMOUNT = $this->amount;
            $model->CREATE_REMARK = $this->remark;
            $model->REMARK_IS_SHOW = $this->isShow;
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('edit', $e->getMessage());
            return null;
        }
        return $model;
    }

    /**
     * 审核通过
     * @return null
     * @throws \yii\db\Exception
     */
    public function pass() {
        if (!$this->validate()) {
            return null;
        }

        // 日志记录操作前的数据
        if($this->type=='cash'){
            $beforeData = UserWallet::getCashByUserId($this->_userId);
            $this->adminOperateLogger->fetchClass = UserWallet::class;
        }else {
            $beforeData = UserBonus::getBonusByUserId($this->_userId);
            $this->adminOperateLogger->fetchClass = UserBonus::class;
        }
        $this->adminOperateLogger->beforeUpdate($beforeData);

        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = $this->_model;
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus'][$this->auditStatus]['value'];
            $model->AUDIT_ADMIN_ID = \Yii::$app->user->id;
            $model->TYPE = $this->type;
            $model->DEAL_TYPE = $this->dealType;
            $model->AMOUNT = $this->amount;
            $model->REMARK_IS_SHOW = $this->isShow;
            $model->AUDIT_REMARK = $this->remark;
            $model->AUDITED_AT = Date::nowTime();
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            // 如果是审核通过状态
            if ($this->auditStatus == 'true') {
                if($model->TYPE=='cash') {
                    Cash::changeUserCash($model->USER_ID, 'CASH', $model->AMOUNT, ['REMARK' => $this->isShow == 1 ? $this->_model->CREATE_REMARK : '']);
                }else{
                    Balance::changeUserBonus($model->USER_ID, $model->TYPE, $model->AMOUNT, ['REMARK' => $model->CREATE_REMARK, 'REMARK_IS_SHOW' => $model->REMARK_IS_SHOW, 'DEAL_TYPE_ID' => $model->DEAL_TYPE, 'DEAL_TYPE_IS_PRESET' => 0, 'ADMIN_NAME' => Admin::getAdminNameById(\Yii::$app->user->id)]);
                }
            }
            $adminId = \Yii::$app->user->id;
            \Yii::$app->redis->del('balanceCode_'.$adminId);
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('pass', $e->getMessage());
            return null;
        }

        // 记录日志
        if($this->type=='cash'){
            $afterData = UserWallet::getCashByUserId($this->_userId);
            $this->adminOperateLogger->fetchClass = UserWallet::class;
        }else {
            $afterData = UserBonus::getBonusByUserId($this->_userId);
            $this->adminOperateLogger->fetchClass = UserBonus::class;
        }
        $this->adminOperateLogger->afterInsert($afterData)->clean()->save([
            'optType' => '审核变动会员余额',
            'userId' => $model->USER_ID,
            'userName' => Info::getUserNameByUserId($model->USER_ID),
            'remark' => $model->CREATE_REMARK,
        ]);

        return $model;
    }

    /**
     * 审核余额变动
     * @return null
     * @throws \yii\db\Exception
     */
    public function changeAudit() {
        if (!$this->validate()) {
            return null;
        }
        $uids=[];
        if($this->auditStatus=='true'){
            foreach ($this->selected as $select) {
                $oneBalanceAudit = BalanceAudit::findOneAsArray('ID=:ID',[':ID'=>$select],'USER_ID');
                $uids[]=$oneBalanceAudit['USER_ID'];
            }
        }
        if($this->auditStatus=='true'){
            $this->adminOperateLogger->fetchClass = UserBonus::class;
            $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($uids, 'USER_ID');
        }else{
            $this->adminOperateLogger->fetchClass = BalanceAudit::class;
            $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($this->selected, 'ID');
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        $logs=[];
        try {
            foreach ($this->selected as $select) {
                $model = BalanceAudit::findOne(['ID' => $select]);
                $model->AUDIT_STATUS = \Yii::$app->params['auditStatus'][$this->auditStatus]['value'];
                $model->AUDIT_ADMIN_ID = \Yii::$app->user->id;
                $model->AUDIT_REMARK = $this->remark;
                $model->AUDITED_AT = Date::nowTime();
                if (!$model->save()) {
                    throw new Exception(Form::formatErrorsForApi($model->getErrors()));
                }
                if ($model->AUDIT_STATUS == \Yii::$app->params['auditStatus']['true']['value']) {
                    Balance::changeUserBonus($model->USER_ID, $model->TYPE, $model->AMOUNT, ['REMARK' => $model->CREATE_REMARK, 'REMARK_IS_SHOW' => $model->REMARK_IS_SHOW, 'DEAL_TYPE_ID' => $model->DEAL_TYPE, 'DEAL_TYPE_IS_PRESET' => 0, 'ADMIN_NAME' => Admin::getAdminNameById(\Yii::$app->user->id)]);
                }
                $logs[]=['userId'=>$select,'type'=>$model->TYPE];
            }
            $adminId = \Yii::$app->user->id;
            \Yii::$app->redis->del('balanceCode_'.$adminId);
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('changeAudit', $e->getMessage());
            return null;
        }
        if($this->auditStatus=='true'){
            $this->adminOperateLogger->fetchClass = UserBonus::class;
            $this->adminOperateLogger->setIsBatch(true)->afterUpdate($uids, 'USER_ID')->clean()->save([
                'optType' => '审核会员余额',
                'remark' => $this->remark,
            ]);
        }else{
            $this->adminOperateLogger->fetchClass = BalanceAudit::class;
            $this->adminOperateLogger->setIsBatch(true)->afterUpdate($this->selected, 'ID')->clean()->save([
                'optType' => '审核会员余额',
                'remark' => $this->remark,
            ]);
        }
        return $logs;
    }

    /**
     * 导入会员余额调整
     * @return null|static
     * @throws \yii\db\Exception
     */
    public function excelChangeBalance() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $userInfo = Info::baseInfo($this->_userId);
            // 添加申请
            $model = new BalanceAudit();
            $model->USER_ID = $this->_userId;
            $model->LAST_DEC_LV = $userInfo['DEC_LV'];
            $model->LAST_EMP_LV = $userInfo['EMP_LV'];
            $model->LAST_DEC_ROLE_ID = $userInfo['DEC_ROLE_ID'];
            $model->TYPE = $this->type;
            $model->DEAL_TYPE = $this->dealType;
            $model->AMOUNT = $this->amount;
            $model->CREATE_REMARK = $this->remark;
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['un']['value'];
            $model->REMARK_IS_SHOW = $this->isShow;
            $model->UPDATE_ADMIN_ID = \Yii::$app->user->id;
            $model->CREATED_AT = Date::nowTime();

            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('auditStatus', $e->getMessage());
            return null;
        }

        // 日志记录操作前的数据
        $beforeData = UserBonus::getBonusByUserId($this->_userId);
        $this->adminOperateLogger->fetchClass = UserBonus::class;
        $this->adminOperateLogger->beforeUpdate($beforeData);

        // 记录日志
        $this->adminOperateLogger->fetchClass = BalanceAudit::class;
        $this->adminOperateLogger->afterInsert($model)->clean()->save([
            'optType' => '批量申请变动会员余额',
            'userId' => $model->USER_ID,
            'userName' => $userInfo['USER_NAME'],
            'remark' => $model->CREATE_REMARK,
        ]);
        return $model;
    }

    /**
     * 删除前
     * @param $selected
     */
    public function beforeDelete($selected) {
        $this->adminOperateLogger->fetchClass = BalanceAudit::class;
        $this->adminOperateLogger->setIsBatch(true)->beforeDelete($selected, 'ID');
    }
    /**
     * 删除
     * @param $selected
     * @throws Exception
     */
    public function delete($selected) {
        $this->adminOperateLogger->clean()->save([
            'optType' => '删除余额调整待审核数据',
        ]);
    }
}
