<?php

namespace common\models\forms;

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\Info;
use common\libs\logging\operate\AdminOperate;
use common\models\BalanceAudit;
use common\models\PerfAudit;
use common\models\PerfMonth;
use common\models\PerfPeriod;
use common\models\Period;
use common\models\User;
use common\models\UserBonus;
use common\models\UserInfo;
use common\models\UserPerf;
use common\models\Withdraw;
use yii\base\Exception;
use yii\db\Expression;

/**
 * Login form
 */
class ChangePerfForm extends Model {

    public $id;
    public $selected;
    public $periodNum;
    public $perfType;
    public $userName;
    public $location;
    public $amount;
    public $remark;
    public $auditStatus;

    private $_periodNum;
    private $_userId;
    private $_locationField;
    private $_model;

    public function init() {
        parent::init();
        $this->adminOperateLogger = new AdminOperate([
            'fetchClass' => PerfAudit::class,
        ]);
    }
    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['id', 'selected', 'userName', 'perfType', 'location', 'amount', 'remark', 'auditStatus'], 'trim'],
            [['id', 'userName', 'perfType', 'location', 'amount', 'remark', 'auditStatus'], 'required'],
            [['id'], 'exist', 'targetClass' => PerfAudit::class, 'targetAttribute' => 'ID', 'message' => '该申请不存在'],
            [['id'], 'initModel'],
            [['userName'], 'isUserName'],
            //[['periodNum'], 'isPeriodNum'],
            [['perfType'], 'isPerfType'],
            [['location'], 'isLocation'],
            [['amount'], 'fullPrice'],
            [['amount'], 'isAmount'],
            [['auditStatus'], 'isStatus'],
            [['selected'], 'isSelected'],
        ];
    }

    /**
     * 指定场景
     * @return array
     */
    public function scenarios() {
        $parentScenarios = parent::scenarios();
        $customScenarios = [
            'add' => ['userName', 'perfType', 'location', 'amount', 'remark'],
            'changeAudit' => ['selected', 'remark', 'auditStatus'],
            'pass' => ['id', 'perfType', 'location', 'amount', 'remark', 'auditStatus'],
        ];
        return array_merge($parentScenarios, $customScenarios);
    }

    /**
     * @return array
     */
    public function attributeLabels() {
        return [
            'id' => '申请的ID',
            'userName' => '会员编号',
            'location' => '区域',
            'amount' => '变动数额',
            'remark' => '备注',
            'auditStatus' => '状态',
        ];
    }

    /**
     * 初始化model
     */
    public function initModel($attribute) {
        $model = $this->_model = PerfAudit::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) {
        $this->_userId = Info::getUserIdByUserName($this->userName);
        if ($this->_userId) {
            // 如果该会员已经存在一个待审核的申请，直接提示错误
            if (PerfAudit::find()->where('USER_ID=:USER_ID AND AUDIT_STATUS=:AUDIT_STATUS', [':USER_ID' => $this->_userId, ':AUDIT_STATUS' => \Yii::$app->params['auditStatus']['un']['value']])->exists()) {
                $this->addError($attribute, '该会员审核列表中如果有待审记录，需等待待审核记录审核后才可提交');
            }
        } else {
            $this->addError($attribute, '会员不存在');
        }
    }

    /**
     * 期数是否符合条件
     * @param $attribute
     */
    public function isPeriodNum($attribute) {
        $period = Period::instance();
        if (!$period->isSent($this->periodNum)) {
            $this->addError($attribute, '该期【' . $this->periodNum . '】未挂网，无法调整');
        }
        if (Period::find()->where('IS_SENT=:IS_SENT AND PERIOD_NUM>=:START_PERIOD_NUM AND PERIOD_NUM<=:END_PERIOD_NUM', [':IS_SENT' => Period::SEND_FINISH, ':START_PERIOD_NUM' => $this->periodNum + 1, ':END_PERIOD_NUM' => $this->periodNum + 1])->count() == 1) {
            $this->addError($attribute, '下一期【' . ($this->periodNum + 1) . '】已挂网，该期无法调整');
        }
    }

    /**
     * 类型是否符合条件
     * @param $attribute
     */
    public function isPerfType($attribute) {
        if (!in_array($this->perfType, array_keys(PerfAudit::CHANGE_PERF_TYPE))) {
            $this->addError($attribute, '调整类型不正确');
        }
        $this->_periodNum = Period::sentMaxPeriodNum();
    }

    /**
     * 校验区域
     * @param $attribute
     */
    public function isLocation($attribute) {
        if ($this->perfType==PerfAudit::PERF_TYPE_PV && !in_array($this->location, [1, 2, 3, 4, 5])) {
            $this->addError($attribute, '区位不正确');
        }
        if ($this->perfType==PerfAudit::PERF_TYPE_SURPLUS && !in_array($this->location, [1, 2, 3, 4, 5, 6])) {
            $this->addError($attribute, '区位不正确');
        }
    }

    /**
     * 金额是否正确
     * @param $attribute
     */
    public function isAmount($attribute) {
        if ($this->amount == 0) $this->addError($attribute, '变动数额不能为0');
        if ($this->perfType == PerfAudit::PERF_TYPE_PV) {
            $userPerf = UserPerf::findOneAsArray('USER_ID=:USER_ID', [':USER_ID' => $this->_userId]);
            if ($this->amount < 0 && (abs($this->amount) > $userPerf['PV_' . $this->location . 'L'])) {
                $this->addError('scenario', '该会员该区域的数额不足');
            }
        } elseif ($this->perfType == PerfAudit::PERF_TYPE_SURPLUS) {
            $perfPeriod = PerfPeriod::findOneAsArray('USER_ID=:USER_ID AND PERIOD_NUM=:PERIOD_NUM', [':USER_ID' => $this->_userId, ':PERIOD_NUM' => $this->_periodNum]);
            if($this->location==6){
                if ($this->amount < 0 && (abs($this->amount) > $perfPeriod['SURPLUS_LS'])) {
                    $this->addError('scenario', '该会员当期该区域剩余数额不足');
                }
            }else {
                if ($this->amount < 0 && (abs($this->amount) > $perfPeriod['SURPLUS_' . $this->location . 'L'])) {
                    $this->addError('scenario', '该会员当期该区域剩余数额不足');
                }
            }
        }
    }

    /**
     * 校验状态
     * @param $attribute
     */
    public function isStatus($attribute) {
        // 获取当前提现单的状态
        $oneData = PerfAudit::findOneAsArray(['ID' => $this->id]);
        switch ($this->auditStatus) {
            case 'un':
                $this->addError($attribute, '不能设置为待审核状态' . $this->auditStatus);
                break;
            case 'true':
                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;
            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, '状态参数有误');
        }
    }

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

    /**
     * 添加变动申请
     * @return BalanceAudit|null
     * @throws \yii\db\Exception
     */
    public function add() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            // 添加申请
            $model = new PerfAudit();
            $model->USER_ID = $this->_userId;
            $model->PERF_TYPE = $this->perfType;
            $model->PERF_LOCATION = $this->location;
            $model->PERIOD_NUM = $this->_periodNum;
            $model->AMOUNT = $this->amount;
            $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['un']['value'];
            $model->CREATE_ADMIN = \Yii::$app->user->id;
            $model->REMARK = $this->remark;
            $model->CREATED_AT = Date::nowTime();
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('add', $e->getMessage());
            return null;
        }

        // 记录日志
        $this->adminOperateLogger->fetchClass = PerfAudit::class;
        $this->adminOperateLogger->afterInsert($model)->clean()->save([
            'optType' => '申请调整会员业绩',
            'userId' => $model->USER_ID,
            'userName' => Info::getUserNameByUserId($model->USER_ID),
            'remark' => $model->REMARK,
        ]);

        return $model;
    }

    /**
     * 管理员审核状态
     * @return BalanceAudit|null
     * @throws \yii\db\Exception
     */
    /*public function changeStatus() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $model = $this->_model;
            if ($this->auditStatus == 'reject') {
                $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['reject']['value'];
            } elseif ($this->auditStatus == 'true') {
                $model->AUDIT_STATUS = \Yii::$app->params['auditStatus']['true']['value'];
            }
            $model->AUDIT_ADMIN = \Yii::$app->user->id;
            $model->AUDITED_AT = Date::nowTime();
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            // 如果是审核通过状态改变会员的业绩
            if ($this->auditStatus == 'true') {
                UserPerf::updateAllCounters([$this->_locationField => $this->amount], 'USER_ID=:USER_ID', [':USER_ID' => $model['USER_ID']]);
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('status', $e->getMessage());
            return null;
        }
        return $model;
    }*/

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

        // 日志记录操作前的数据
        $beforeData = UserPerf::getPvByUserId($this->_userId);
        $this->adminOperateLogger->fetchClass = UserPerf::class;
        $this->adminOperateLogger->beforeUpdate($beforeData);
        $perfData = $this->adminOperateLogger->saveBeforeContent;
        $beforeData = PerfPeriod::getPeriodSurplusPerf($this->_model->PERIOD_NUM,$this->_userId);
        $this->adminOperateLogger->fetchClass = PerfPeriod::class;
        $this->adminOperateLogger->beforeUpdate($beforeData);
        $periodData = $this->adminOperateLogger->saveBeforeContent;
        $this->adminOperateLogger->saveBeforeContent=array_merge($perfData,$periodData);

        $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->AMOUNT = $this->amount;
            $model->REMARK = $this->remark;
            $model->AUDITED_AT = Date::nowTime();

            $perfModel = UserPerf::findOne(['USER_ID' => $model->USER_ID]);
            $periodModel = PerfPeriod::findOne(['USER_ID' => $model->USER_ID, 'PERIOD_NUM' => $model->PERIOD_NUM]);

            $perfBefore = 0;
            $perfAfter = 0;
            // 如果是审核通过状态
            if ($this->auditStatus == 'true') {
                if ($model->PERF_TYPE == PerfAudit::PERF_TYPE_PV) {
                    //给上月累计
                    $period = Period::instance();
                    $lastMonth = $period->getLastMonth();
                    PerfMonth::updateAll(['PV_' . $model->PERF_LOCATION . 'L_TOTAL'=> new Expression('PV_' . $model->PERF_LOCATION . 'L_TOTAL+'.$model->AMOUNT)],'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH',[':USER_ID'=>$model->USER_ID,':CALC_MONTH'=>$lastMonth['yearMonth']]);

                    $locaionField = 'PV_' . $model->PERF_LOCATION . 'L';
                    $perfBefore = $perfModel->$locaionField;
                    $perfAfter = $perfModel->$locaionField + $model->AMOUNT;
                    $perfModel->$locaionField = $perfAfter;
                    if (!$perfModel->save()) {
                        throw new Exception(Form::formatErrorsForApi($perfModel->getErrors()));
                    }
                } elseif ($model->PERF_TYPE == PerfAudit::PERF_TYPE_SURPLUS) {
                    if($model->PERF_LOCATION==6){
                        $locaionField = 'SURPLUS_LS';
                    }else{
                        $locaionField = 'SURPLUS_' . $model->PERF_LOCATION . 'L';
                    }
                    $perfBefore = $periodModel->$locaionField;
                    $perfAfter = $periodModel->$locaionField + $model->AMOUNT;
                    $periodModel->$locaionField = $perfAfter;
                    if (!$periodModel->save()) {
                        throw new Exception(Form::formatErrorsForApi($periodModel->getErrors()));
                    }
                }
            }
            $model->PV_1L = $perfModel->PV_1L;
            $model->PV_2L = $perfModel->PV_2L;
            $model->PV_3L = $perfModel->PV_3L;
            $model->PV_4L = $perfModel->PV_4L;
            $model->PV_5L = $perfModel->PV_5L;
            $model->SURPLUS_1L = $periodModel->SURPLUS_1L;
            $model->SURPLUS_2L = $periodModel->SURPLUS_2L;
            $model->SURPLUS_3L = $periodModel->SURPLUS_3L;
            $model->SURPLUS_4L = $periodModel->SURPLUS_4L;
            $model->SURPLUS_5L = $periodModel->SURPLUS_5L;
            $model->SURPLUS_LS = $periodModel->SURPLUS_LS;
            $model->PERF_BEFORE = $perfBefore;
            $model->PERF_AFTER = $perfAfter;
            if (!$model->save()) {
                throw new Exception(Form::formatErrorsForApi($model->getErrors()));
            }
            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('pass', $e->getMessage());
            return null;
        }

        // 记录日志
        $beforeData = UserPerf::getPvByUserId($this->_userId);
        $this->adminOperateLogger->fetchClass = UserPerf::class;
        $this->adminOperateLogger->afterUpdate($beforeData);
        $perfData = $this->adminOperateLogger->saveAfterContent;
        $beforeData = PerfPeriod::getPeriodSurplusPerf($this->_model->PERIOD_NUM,$this->_userId);
        $this->adminOperateLogger->fetchClass = PerfPeriod::class;
        $this->adminOperateLogger->afterUpdate($beforeData);
        $periodData = $this->adminOperateLogger->saveAfterContent;
        $this->adminOperateLogger->saveAfterContent=array_merge($perfData,$periodData);
        $this->adminOperateLogger->clean()->save([
            'optType' => '审核通过会员业绩',
            'userId' => $model->USER_ID,
            'userName' => Info::getUserNameByUserId($model->USER_ID),
            'remark' => $model->REMARK,
        ]);

        return $model;
    }

    /**
     * 修改审核状态
     * @return array|null
     * @throws \yii\db\Exception
     */
    public function changeAudit() {
        if (!$this->validate()) {
            return null;
        }
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        $logs = [];
        $uids=[];
        if($this->auditStatus=='true'){
            foreach ($this->selected as $select) {
                $oneBalanceAudit = PerfAudit::findOneAsArray('ID=:ID',[':ID'=>$select],'USER_ID');
                $uids[]=$oneBalanceAudit['USER_ID'];
            }
        }
        try {
            if($this->auditStatus=='true'){
                $this->adminOperateLogger->fetchClass = UserPerf::class;
                $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($uids, 'USER_ID');
                $perfData = $this->adminOperateLogger->saveBeforeContent;
                $this->adminOperateLogger->fetchClass = PerfPeriod::class;
                $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($uids, 'USER_ID');
                $periodData = $this->adminOperateLogger->saveBeforeContent;
                $this->adminOperateLogger->saveBeforeContent=Tool::mergeArrayWithKey($perfData,$periodData);
            }else{
                $this->adminOperateLogger->fetchClass = PerfAudit::class;
                $this->adminOperateLogger->setIsBatch(true)->beforeUpdate($this->selected, 'ID');
            }
            foreach ($this->selected as $select) {
                $model = PerfAudit::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->REMARK = $this->remark;
                $model->AUDITED_AT = Date::nowTime();
                $perfModel = UserPerf::findOne(['USER_ID' => $model->USER_ID]);
                $periodModel = PerfPeriod::findOne(['USER_ID' => $model->USER_ID, 'PERIOD_NUM' => $model->PERIOD_NUM]);
                $perfBefore = 0;
                $perfAfter = 0;
                if ($model->AUDIT_STATUS == \Yii::$app->params['auditStatus']['true']['value']) {
                    if ($model->PERF_TYPE == PerfAudit::PERF_TYPE_PV) {
                        //给上月累计
                        $period = Period::instance();
                        $lastMonth = $period->getLastMonth();
                        PerfMonth::updateAll(['PV_' . $model->PERF_LOCATION . 'L_TOTAL'=> new Expression('PV_' . $model->PERF_LOCATION . 'L_TOTAL+'.$model->AMOUNT)],'USER_ID=:USER_ID AND CALC_MONTH=:CALC_MONTH',[':USER_ID'=>$model->USER_ID,':CALC_MONTH'=>$lastMonth['yearMonth']]);

                        $locaionField = 'PV_' . $model->PERF_LOCATION . 'L';
                        $perfBefore = $perfModel->$locaionField;
                        $perfAfter = $perfModel->$locaionField + $model->AMOUNT;
                        $perfModel->$locaionField = $perfAfter;
                        if (!$perfModel->save()) {
                            throw new Exception(Form::formatErrorsForApi($perfModel->getErrors()));
                        }
                    } elseif ($model->PERF_TYPE == PerfAudit::PERF_TYPE_SURPLUS) {
                        if($model->PERF_LOCATION==6){
                            $locaionField = 'SURPLUS_LS';
                        }else{
                            $locaionField = 'SURPLUS_' . $model->PERF_LOCATION . 'L';
                        }
                        $perfBefore = $periodModel->$locaionField;
                        $perfAfter = $periodModel->$locaionField + $model->AMOUNT;
                        $periodModel->$locaionField = $perfAfter;
                        if (!$periodModel->save()) {
                            throw new Exception(Form::formatErrorsForApi($periodModel->getErrors()));
                        }
                    }
                }
                $model->PV_1L = $perfModel->PV_1L;
                $model->PV_2L = $perfModel->PV_2L;
                $model->PV_3L = $perfModel->PV_3L;
                $model->PV_4L = $perfModel->PV_4L;
                $model->PV_5L = $perfModel->PV_5L;
                $model->SURPLUS_1L = $periodModel->SURPLUS_1L;
                $model->SURPLUS_2L = $periodModel->SURPLUS_2L;
                $model->SURPLUS_3L = $periodModel->SURPLUS_3L;
                $model->SURPLUS_4L = $periodModel->SURPLUS_4L;
                $model->SURPLUS_5L = $periodModel->SURPLUS_5L;
                $model->SURPLUS_LS = $periodModel->SURPLUS_LS;
                $model->PERF_BEFORE = $perfBefore;
                $model->PERF_AFTER = $perfAfter;
                if (!$model->save()) {
                    throw new Exception(Form::formatErrorsForApi($model->getErrors()));
                }
                $logs[] = ['userId' => $select];
            }

            if($this->auditStatus=='true'){
                $this->adminOperateLogger->fetchClass = UserPerf::class;
                $this->adminOperateLogger->setIsBatch(true)->afterUpdate($uids, 'USER_ID');
                $perfData = $this->adminOperateLogger->saveAfterContent;
                $this->adminOperateLogger->fetchClass = PerfPeriod::class;
                $this->adminOperateLogger->setIsBatch(true)->afterUpdate($uids, 'USER_ID');
                $periodData = $this->adminOperateLogger->saveAfterContent;
                $this->adminOperateLogger->saveAfterContent=Tool::mergeArrayWithKey($perfData,$periodData);
                $this->adminOperateLogger->setBatchField('USER_ID')->setOptObjField('USER_ID')->clean()->save([
                    'optType' => '审核会员业绩',
                    'remark' => $this->remark,
                ]);
            }else{
                $this->adminOperateLogger->fetchClass = PerfAudit::class;
                $this->adminOperateLogger->setIsBatch(true)->afterUpdate($this->selected, 'ID')->clean()->save([
                    'optType' => '审核会员业绩',
                    'remark' => $this->remark,
                ]);
            }

            $transaction->commit();
        } catch (Exception $e) {
            $transaction->rollBack();
            $this->addError('changeAudit', $e->getMessage());
            return null;
        }
        return $logs;
    }

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