<?php

namespace common\models\forms;

use backendApi\modules\v1\models\Admin;
use common\helpers\Cache;
use common\helpers\Date;
use common\components\Model;
use common\helpers\Form;
use common\helpers\user\Reconsume;
use common\helpers\user\Info;
use common\helpers\Validator;
use common\libs\logging\operate\AdminOperate;
use common\models\PerfMonth;
use common\models\Period;
use common\models\ReconsumeAudit;
use common\models\ReconsumePool;
use common\models\ReconsumePoolFlow;
use common\models\UserInfo;
use yii\base\Exception;
use yii\validators\NumberValidator;

/**
 * Login form
 */
class ReconsumeForm extends Model {
    public $id;
    public $selected;
    public $userName;
    public $type;
    public $changeAmount;
    public $remark;
    public $auditStatus;
    public $calcYearMonth;
    public $isPass;
    public $isShow;

    private $_model;
    private $_userId;

    const TYPE_BALANCE = 0;     // 变动余额
    const TYPE_MONTH = 1;       // 变动月份

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

    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['id', 'selected', 'userName', 'type', 'changeAmount', 'remark', 'auditStatus', 'calcYearMonth', 'isShow'], 'trim'],
            [['id', 'userName', 'type', 'changeAmount', 'remark', 'auditStatus', 'calcYearMonth'], 'required'],
            [['id'], 'exist', 'targetClass' => ReconsumeAudit::class, 'targetAttribute' => 'ID'],
            [['id'], 'initModel'],
            [['userName'], 'exist', 'targetClass' => UserInfo::class, 'targetAttribute' => 'USER_NAME'],
            [['userName'], 'isUserName'],
            [['calcYearMonth'], 'yearMonth'],
            [['type'], 'isType'],
            [['auditStatus'], 'isAuditStatus'],
            [['selected'], 'isSelected'],
            [['changeAmount'], 'isChangeAmount'],
            [['calcYearMonth'], 'isCanDeduct'],
        ];
    }

    public function attributeLabels() {
        return [
            'userName' => '会员编号',
            'type' => '变动类型',
            'changeAmount' => '变动数',
            'remark' => '备注',
            'auditStatus' => '审核状态',
            'isShow' => '前台显示备注',
            'calcYearMonth' => '结算年月',
        ];
    }

    /**
     * 指定校验场景
     * @return array
     */
    public function scenarios() {
        $parentScenarios = parent::scenarios();
        $customScenarios = [
            'changeAdd' => ['userName', 'type', 'changeAmount', 'remark', 'isShow'],
            'changeAudit' => ['selected', 'remark', 'auditStatus'],
            'edit' => ['id', 'type', 'changeAmount', 'remark', 'isShow'],
            'pass' => ['id', 'type', 'changeAmount', 'remark', 'isShow'],
            'deductReConsume' => ['userName', 'remark', 'isPass'],
            'deductReConsumeAdd' => ['userName', 'calcYearMonth'],
            'deductReConsumeAudit' => ['id', 'remark', 'isShow', 'auditStatus'],
        ];
        return array_merge($parentScenarios, $customScenarios);
    }

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

    /**
     * 校验用户名
     * @param $attribute
     */
    public function isUserName($attribute) {
        // 如果该用户存在待审核状态的数据，如果有，则提示管理员先处理待审核的数据
        $this->_userId = Info::getUserIdByUserName($this->userName);
        /*$userId = $this->_userInfo['USER_ID'];
        $type = '';
        if ($this->scenario == 'changeAdd') {
            $type = ReconsumeAudit::TYPE_CHANGE;
        } elseif ($this->scenario == 'deductReConsumeAdd') {
            $type = ReconsumeAudit::TYPE_RECONSUME;
        }
        if (ReconsumeAudit::find()->where('USER_ID=:USER_ID AND AUDIT_STATUS=:AUDIT_STATUS AND TYPE=:TYPE', [':USER_ID' => $userId, ':AUDIT_STATUS' => \Yii::$app->params['auditStatus']['un']['value'], ':TYPE' => $type])->exists()) {
            $this->addError($attribute, '该会员存在一条待审核的记录，请等待待审核数据处理完毕');
        }*/
    }

    /**
     * 校验类型
     * @param $attribute
     */
    public function isType($attribute) {
        if (!in_array($this->type, [self::TYPE_BALANCE, self::TYPE_MONTH])) {
            $this->addError($attribute, '调整类型错误');
        }
    }

    /**
     * 审核状态是否正确
     * @param $attributes
     */
    public function isAuditStatus($attributes) {
        if (!array_key_exists($this->auditStatus, \Yii::$app->params['auditStatus'])) {
            $this->addError($attributes, '无效的审核状态');
        }
    }

    /**
     * 批量数据
     * @param $attributes
     */
    public function isSelected($attributes) {
        if (!$this->selected) {
            $this->addError($attributes, 'A piece of data must be selected'); // 必须选择一条数据
        }
        if (!is_array($this->selected)) {
            $this->selected = [$this->selected];
        }
    }

    /**
     * 变动内容
     * @param $attribute
     * @throws \yii\db\Exception
     */
    public function isChangeAmount($attribute) {
        if ($this->changeAmount == 0) {
            $this->addError($attribute, '调整值不能等于0');
        }
        $reConsumePool = Reconsume::getUserReconsumePool($this->_userId);
        if ($this->type == self::TYPE_BALANCE) {
            if (!Validator::validateQuickLy('fullPrice', $this->changeAmount)) {
                $this->addError($this->changeAmount, '调整金额不正确');
            }
            if(($reConsumePool['unusedPV']+$this->changeAmount)<0){
                $this->addError($this->changeAmount, '可用余额不足');
            }
        } elseif ($this->type == self::TYPE_MONTH) {
            $validator = Validator::createValidator(NumberValidator::class, $this, [['changeAmount'], 'integer']);
            $this->validators->append($validator);
            if(($reConsumePool['unusedMonth']+$this->changeAmount)<0){
                $this->addError($this->changeAmount, '可用月数不足');
            }
        }
    }

    /**
     * 是否能扣除复销
     * @param $attribute
     * @throws \yii\db\Exception
     */
    public function isCanDeduct($attribute) {

        $userId = Info::getUserIdByUserName($this->userName);
        if (!Reconsume::isCanDeduct($userId, $this->calcYearMonth)) {
            $this->addError($attribute, '会员已合格不能再次扣除');
        }
        //未来的结算年和月不能手动扣除，即未结算的结算月不能扣除
        if($periodPoint = Period::getPeriodPointFromMonth(substr($this->calcYearMonth, 0, 4), intval(substr($this->calcYearMonth, 4, 2)))){
            if(boolval($periodPoint['IS_CALCULATED'] != Period::CALCULATE_FINISH)){
                $this->addError($attribute, '所选结算月未结算不能扣除');
            }
        }
    }

    /**
     * 添加申请
     * @return ReconsumeAudit|null
     * @throws \yii\db\Exception
     */
    public function changeAdd() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = new ReconsumeAudit();
            $model->CREATED_AT = Date::nowTime();
            $model->USER_ID = Info::getUserIdByUserName($this->userName);
            if ($this->type == self::TYPE_BALANCE) {
                $model->CHANGE_PV = $this->changeAmount;
            } elseif ($this->type == self::TYPE_MONTH) {
                $model->CHANGE_MONTH = $this->changeAmount;
            }
            $model->TYPE = $this->type;//190715调整余额的类型
            $model->CREATE_ADMIN = \Yii::$app->user->id;
            $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('changeAdd', $e->getMessage());
            return null;
        }
        $this->adminOperateLogger->fetchClass= ReconsumeAudit::class;
        $this->adminOperateLogger->afterInsert($model)->clean()->save([
            'optType' => '申请调整复销池余额',
            'userId' => $model->USER_ID,
            'userName' => Info::getUserNameByUserId($model->USER_ID),
            'remark' => $this->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;
            if ($this->type == self::TYPE_BALANCE) {
                $model->CHANGE_PV = $this->changeAmount;
                $model->CHANGE_MONTH = 0;
            } elseif ($this->type == self::TYPE_MONTH) {
                $model->CHANGE_MONTH = $this->changeAmount;
                $model->CHANGE_PV = 0;
            }
            $model->REMARK_IS_SHOW = $this->isShow;
            $model->CREATE_REMARK = $this->remark;
            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;
        }
        $this->adminOperateLogger->beforeUpdate(ReconsumePool::findOne(['USER_ID'=>$this->_userId]));
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = $this->_model;
            if ($this->type == self::TYPE_BALANCE) {
                $model->CHANGE_PV = $this->changeAmount;
                $model->CHANGE_MONTH = 0;
            } elseif ($this->type == self::TYPE_MONTH) {
                $model->CHANGE_MONTH = $this->changeAmount;
                $model->CHANGE_PV = 0;
            }
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['true']['value'];
            $model->AUDIT_ADMIN = \Yii::$app->user->id;
            $model->CREATE_REMARK = $this->remark;
            $model->REMARK_IS_SHOW = $this->isShow;
            $model->AUDITED_AT = Date::nowTime();
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            // 查看该条记录中变化的是PV还是月数
            if ($model->CHANGE_PV != 0) {
                Reconsume::changePoolPV($model->USER_ID, $model->CHANGE_PV, [
                    'DEAL_TYPE' => Reconsume::TYPE_AUDIT_PV,
                    'REMARK' => $model->CREATE_REMARK,
                    'REMARK_IS_SHOW' => $this->isShow,
                    'ADMIN_NAME'=>Admin::getAdminNameById(\Yii::$app->user->id),
                ]);
            }
            if ($model->CHANGE_MONTH != 0) {
                Reconsume::changePoolMonthNum($model->USER_ID, $model->CHANGE_MONTH, ['DEAL_TYPE' => Reconsume::TYPE_AUDIT_MONTH, 'REMARK' => $model->CREATE_REMARK,'REMARK_IS_SHOW' => $this->isShow, 'ADMIN_NAME'=>Admin::getAdminNameById(\Yii::$app->user->id)]);
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('pass', $e->getMessage());
            return null;
        }
        $this->adminOperateLogger->afterUpdate(ReconsumePool::findOne(['USER_ID'=>$this->_userId]))->clean()->save([
            'optType' => '审核通过调整复销池余额',
            'userId' => $model->USER_ID,
            'userName' => Info::getUserNameByUserId($model->USER_ID),
            'remark' => $this->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 = ReconsumeAudit::findOneAsArray('ID=:ID',[':ID'=>$select],'USER_ID');
                $uids[]=$oneBalanceAudit['USER_ID'];
            }
        }
        if($this->auditStatus=='true'){
            $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($uids, 'USER_ID');
        }else{
            $this->adminOperateLogger->fetchClass = ReconsumeAudit::class;
            $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($this->selected, 'ID');
        }
        $model = new ReconsumeAudit();
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            foreach ($this->selected as $select) {
                $model = ReconsumeAudit::findOne(['ID' => $select]);
                if ($model->AUDIT_STATUS > \Yii::$app->params['auditStatus']['un']['value']) continue;
                $model->AUDIT_STATUS = \Yii::$app->params['auditStatus'][$this->auditStatus]['value'];
                $model->AUDIT_ADMIN = \Yii::$app->user->id;
                $model->CREATE_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']) {
                    // 查看该条记录中变化的是PV还是月数
                    if ($model->CHANGE_PV != 0) {
                        Reconsume::changePoolPV($model->USER_ID, $model->CHANGE_PV, [
                            'DEAL_TYPE' => Reconsume::TYPE_AUDIT_PV,
                            'REMARK' => $model->CREATE_REMARK,
                            'ADMIN_NAME'=>Admin::getAdminNameById(\Yii::$app->user->id)
                        ]);
                    }
                    if ($model->CHANGE_MONTH != 0) {
                        Reconsume::changePoolMonthNum($model->USER_ID, $model->CHANGE_MONTH, ['DEAL_TYPE' => Reconsume::TYPE_AUDIT_MONTH, 'REMARK' => $model->CREATE_REMARK, 'ADMIN_NAME'=>Admin::getAdminNameById(\Yii::$app->user->id)]);
                    }
                }
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('changeAudit', $e->getMessage());
            return null;
        }
        if($this->auditStatus=='true'){
            $this->adminOperateLogger->fetchClass = ReconsumePool::class;
            $this->adminOperateLogger->setIsBatch(true)->afterUpdate($uids, 'USER_ID')->clean()->save([
                'optType' => '批量审核调整复销池余额',
                'remark' => $this->remark,
            ]);
        }else{
            $this->adminOperateLogger->fetchClass = ReconsumeAudit::class;
            $this->adminOperateLogger->setIsBatch(true)->afterUpdate($this->selected, 'ID')->clean()->save([
                'optType' => '批量拒绝调整复销池余额',
                'remark' => $this->remark,
            ]);
        }
        return count($this->selected) == 1 ? $model : true;
    }

    /**
     * 扣除复销(当月是否合格)
     * @return null
     * @throws \yii\db\Exception
     */
    public function deductReConsume() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $userId = $this->_userId;
            $period = Period::instance();
            $yearMonth = $period->getNowYearMonth();
            $periodNum = $period->getNowPeriodNum();
            $lastYearMonth = $period->getLastMonth($periodNum);
            $lastYearMonth = $lastYearMonth['yearMonth'];
            if (!Reconsume::isCanDeduct($userId, $yearMonth)) {
                throw new Exception('该月不能扣除复销');
            }
            if (Reconsume::isCanGetBonus($userId, $yearMonth)) {
                throw new Exception('该月已有获奖资格，不能扣除');
            }
            $isPassText = $this->isPass ? '合格' : '不合格';
            $remark = $this->remark ? $this->remark : '手动扣除本月复销并设置为' . $isPassText;
            // 扣除复销
            $sysConfig = Cache::getSystemConfig();
            if (!Reconsume::deductFxByCalcMonth($userId, $yearMonth, ['DEAL_TYPE' => Reconsume::TYPE_MANUAL, 'REMARK' => $remark])) {
                throw new Exception('复销扣除失败，请检查会员复销余额是否充足');
            }
            if ($this->isPass) {
                // 把月业绩表中对应的该会员上个月的复销状态设置
                PerfMonth::updateAll(['FX_STATUS' => 1], 'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $userId, ':CALC_MONTH' => $lastYearMonth]);
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('deductReConsume', $e->getMessage());
            return null;
        }
        return $this->_userId;
    }

    /**
     * 审核扣除复销
     * @return null
     * @throws \yii\db\Exception
     */
    public function deductReConsumeAudit() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = $this->_model;
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus'][$this->auditStatus]['value'];
            $model->AUDIT_ADMIN = \Yii::$app->user->id;
            $model->CREATE_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']) {
                if (!Reconsume::isCanDeduct($model->USER_ID, $model->CALC_MONTH)) {
                    throw new Exception('该月不能扣除复销');
                }
                // 查看该条记录中变化的是PV还是月数
                $sysConfig = Cache::getSystemConfig();
                if (!Reconsume::deductFxByCalcMonth($model->USER_ID, $model->CALC_MONTH, ['DEAL_TYPE' => Reconsume::TYPE_MANUAL, 'REMARK' => $model->CREATE_REMARK, 'ADMIN_NAME'=>Admin::getAdminNameById(\Yii::$app->user->id)])) {
                    throw new Exception('复销扣除失败，请检查会员复销余额是否充足');
                }
                // 把月业绩表中对应的该会员您的复销状态设置
                PerfMonth::updateAll(['FX_STATUS' => 1], 'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH', [':USER_ID' => $model->USER_ID, ':CALC_MONTH' => $model->CALC_MONTH]);
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('changeAudit', $e->getMessage());
            return null;
        }
        return $model;
    }

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