<?php
namespace common\models\forms;

use common\helpers\Cache;
use common\helpers\Date;
use common\components\Model;
use common\helpers\Form;
use common\helpers\snowflake\SnowFake;
use common\helpers\user\Balance;
use common\helpers\user\Cash;
use common\helpers\user\Info;
use common\libs\logging\operate\AdminOperate;
use common\models\ApproachDecOrder;
use common\models\ApproachOrder;
use common\models\DealType;
use common\models\DecOrder;
use common\models\Order;
use common\models\OrderGoods;
use common\models\Period;
use common\models\ReceiveAddress;
use common\models\Region;
use common\models\ReturnOrder;
use common\models\ShopGoods;
use common\models\User;
use common\models\UserBonus;
use common\models\UserNetwork;
use common\models\UserWallet;
use yii\base\Exception;

/**
 * 删除订单
 */
class OrderDeleteForm extends Model
{
    public $orderSn;

    /**
     * @var Order
     */
    private $_model;

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['orderSn'], 'trim'],
            [['orderSn'], 'required'],
            [['orderSn'], 'checkOrderType'],
        ];
    }

    public function attributeLabels()
    {
        return [
            'orderSn' => '订单号',
        ];
    }

    /**
     * 指定校验场景
     * @return array
     */
    public function scenarios()
    {
        $parentScenarios =  parent::scenarios();
        $customScenarios = [
            // // 管理员发货
            // 'adminDelivery' => ['sn', 'expressCompany', 'orderTrackNo'],
            // // 会员确认收货
            // 'userConfirm' => ['sn', 'expressCompany', 'orderTrackNo'],
            // // 管理员修改订单状态
            // 'adminStatus' => ['sn', 'status'],
            // // 管理员修改备注
            // 'adminRemark' => ['sn', 'remark'],
            // // 会员下单
            // 'userOrder' => ['type','addressId', 'payType','goodsId','goodsNum', 'remark', 'payPassword'],
            // // 帮会员复消下单
            // 'reconsumeOrder' => ['type','userName', 'payType','goodsId','goodsNum', 'remark', 'payPassword','consignee','acceptMobile','province','city','county','detailaddress'],
        ];
        return array_merge($parentScenarios, $customScenarios);
    }

    /**
     * @throws Exception
     */
    public function returnOrder() {
        if(!$this->validate()){
            return null;
        }
        $sn = $this->orderSn;
        // 获取订单详情
        $orderInfo = Order::findUseDbCalc()
        ->select('ID,DEC_SN,SN,USER_ID,ORDER_TYPE,IS_DELETE,PAY_AMOUNT,PAY_TYPE,ORDER_AMOUNT,USER_NAME,PV,PAY_PV,PERIOD_NUM,PROVINCE,CITY,COUNTY,ADDRESS,STATUS,NOTE,ORDER_CATEGORY,CREATE_USER')
        ->where("SN=:SN", [':SN' => $sn])
        ->asArray()
        ->one();

        $approachOrderInfo = [];
        // 如果是PayStack支付,订单是未支付状态,则去中间表查询,如果两个表都没有数据,订单不存在
        if (!$orderInfo) {
            $approachOrderInfo = ApproachOrder::findUseDbCalc()
                ->select('ID,DEC_SN,SN,USER_ID,ORDER_TYPE,IS_DELETE,PAY_AMOUNT,PAY_TYPE,ORDER_AMOUNT,USER_NAME,PV,PAY_PV,PERIOD_NUM,PROVINCE,CITY,COUNTY,ADDRESS,STATUS,NOTE,ORDER_CATEGORY,CREATE_USER')
                ->where("SN=:SN", [':SN' => $sn])
                ->asArray()
                ->one();
        }
        if (!$orderInfo && !$approachOrderInfo) {
            throw new Exception('订单不存在');
        }

        $orderInfo = $orderInfo ?: $approachOrderInfo;

        // 如果会员已经是锁定状态了,删除订单的时候,是否还要退还金额
        $db = \Yii::$app->db;
        $transaction = $db->beginTransaction();
        try {
            $userId = $orderInfo['USER_ID'];
            $decInfo = [];
            $isLock = 0 ; // 是否锁定会员单
            // 如果是注册订单,则删除订单并退还金额,然后再冻结用户
            if ($orderInfo['ORDER_TYPE'] == 'ZC') {
                // 查询报单数据,因为如果是报单,则要退还给报单中心
                if (!$approachOrderInfo) {
                    $decInfo = DecOrder::findUseDbCalc()
                        ->select('USER_ID,TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,ORI_LV,UPGRADE_LV')
                        ->where("ORDER_SN=:ORDER_SN", [':ORDER_SN' => $sn])
                        ->asArray()
                        ->one();
                    // 删除报单
                    $delDecOrder = DecOrder::updateAll(
                        ['IS_DEL'=>1, 'DELETED_AT'=>Date::nowTime()],
                        'ORDER_SN=:ORDER_SN',
                        ['ORDER_SN'=>$sn]
                    );
                } else {
                    $decInfo = ApproachDecOrder::findUseDbCalc()
                        ->select('USER_ID,TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,ORI_LV,UPGRADE_LV')
                        ->where("ORDER_SN=:ORDER_SN", [':ORDER_SN' => $sn])
                        ->asArray()
                        ->one();
                    // 删除报单
                    $delDecOrder = ApproachDecOrder::updateAll(
                        ['IS_DEL'=>1, 'DELETED_AT'=>Date::nowTime()],
                        'ORDER_SN=:ORDER_SN',
                        ['ORDER_SN'=>$sn]
                    );
                }

                $userId = $decInfo['USER_ID'];

                if (!$delDecOrder) {
                    $transaction->rollBack();
                    throw new Exception(\Yii::t('ctx', 'shopDeleteDecOrderAndOrderFailedNotice'));
                }

                // 支付成功才需要处理
                if ($orderInfo['STATUS'] == \Yii::$app->params['orderStatus']['paid']['value']) {
                    // 如果删除的是升级单,则需要回退用户的级别
                    if ($decInfo['DETAIL_TYPE'] == 2) {
                        $oriLv = $decInfo['ORI_LV'];
                        $userModel = User::findOne(['ID' => $orderInfo['USER_ID']]);
                        $userModel->DEC_LV = $oriLv;
                        $userModel->UPDATED_AT = Date::nowTime();
                        if(!$userModel->save(false)) {
                            $transaction->rollBack();
                            throw new Exception(\Yii::t('ctx', 'shopBackOrderFailedNotice'));
                        }
                    } else {
                        // 锁定用户
                        $userModel = User::findOne(['ID' => $orderInfo['USER_ID']]);
                        $userModel->STATUS = 0;
                        $userModel->STATUS_AT = Date::nowTime();
                        if(!$userModel->save(false)) {
                            $transaction->rollBack();
                            throw new Exception(\Yii::t('ctx', 'shopLockFailedDeleteOrderFailed'));
                        }
                        $isLock = 1;
                    }
                }
                // PayStack支付退单不处理
            } else if (!$approachOrderInfo && $orderInfo['ORDER_CATEGORY'] === 'STUDIO') {
                // 工作室复消：退款给下单人
                $createUser = User::findOneAsArray('USER_NAME=:USER_NAME', [':USER_NAME' => $orderInfo['CREATE_USER']]);
                if (!$createUser) {
                    $transaction->rollBack();
                    throw new Exception('删除订单失败。查找下单人失败');
                }
                $userId = $createUser['ID'];
            }

            if (!$approachOrderInfo) {
                // 公共的退钱,删除订单操作
                $delOrder = Order::updateAll(
                    ['IS_DELETE' => 1, 'DELETED_AT' => Date::nowTime()],
                    'SN=:SN',
                    ['SN' => $sn]
                );
            } else {
                // 公共的退钱,删除订单操作
                $delOrder = ApproachOrder::updateAll(
                    ['IS_DELETE' => 1, 'DELETED_AT' => Date::nowTime()],
                    'SN=:SN',
                    ['SN' => $sn]
                );
            }
            if (!$delOrder) {
                $transaction->rollBack();
                throw new Exception(\Yii::t('ctx', 'shopDeleteOrderFailed'));
            }

            $payType = $orderInfo['PAY_TYPE']; // 支付方式
            if ($payType != 'pay_stack') {
                // 记录退还前的账户原资金
                $cash = $point = $bonus = $exchange = 0;
                $userBonus = UserBonus::findUseSlaves()
                    ->select('BONUS,RECONSUME_POINTS,EXCHANGE_POINTS')
                    ->where('USER_ID=:USER_ID', [':USER_ID' => $userId])
                    ->asArray()
                    ->one();
                if ($userBonus) {
                    $point = $userBonus['RECONSUME_POINTS'];
                    $bonus = $userBonus['BONUS'];
                    $exchange = $userBonus['EXCHANGE_POINTS'];
                }
                $cashWallet = UserWallet::findOneAsArray('USER_ID=:USER_ID', [':USER_ID' => $userId], 'CASH');
                if ($cashWallet) {
                    $cash = $cashWallet['CASH'];
                }
                // 开始退钱,退积分等
                $payAmount = $orderInfo['PAY_AMOUNT']; // 支付的金额
                //退还
                if ($payType == 'cash') {
                    $amountResult = Cash::changeUserCash($userId, 'CASH', +abs($payAmount), ['REMARK' => '退货退还余额', 'ORDER_SN' => $orderInfo['SN']]);
                } else if ($payType == 'exchange') {
                    $amountResult = Balance::changeUserBonus($userId, 'exchange_points', +abs($payAmount), ['DEAL_TYPE_ID' => DealType::EXCHANGE_POINTS_EXCHANGE, 'REMARK' => '退货退还无业绩兑换点数', 'ORDER_SN' => $orderInfo['SN']]);
                } else {
                    $amountResult = Balance::changeUserBonus($userId, 'reconsume_points', +abs($payAmount), ['DEAL_TYPE_ID' => DealType::RECONSUME_POINTS_EXCHANGE, 'REMARK' => '退货退还复销点数', 'ORDER_SN' => $orderInfo['SN']]);
                }

                if ($amountResult !== true) {
                    $transaction->rollBack();
                    throw new Exception(\Yii::t('ctx', 'shopBackAmountFailedDeleteOrderFailed'));
                }

                $upgradeType = 0; // 升级单类型
                $returnLv = '';
                $oriLvs = '';
                if (!empty($decInfo)) {
                    $upgradeType = $decInfo['UPGRADE_TYPE'];
                    $returnLv = $decInfo['ORI_LV'];
                    $oriLvs = $decInfo['UPGRADE_LV'];
                }

                // 退款成功,记录数据信息
                $periodObj = Period::instance();
                $nowPeriodNum = $periodObj->getNowPeriodNum();
                $returnOrderModel = new ReturnOrder();
                $returnOrderModel->ID = SnowFake::instance()->generateId();
                $returnOrderModel->SN = $sn;
                $returnOrderModel->DEC_SN = $orderInfo['DEC_SN'];
                $returnOrderModel->CREATE_AT = Date::nowTime();
                $returnOrderModel->ORDER_TYPE = $orderInfo['ORDER_TYPE'];
                $returnOrderModel->ORDER_AMOUNT = $orderInfo['ORDER_AMOUNT'];
                $returnOrderModel->PV = $orderInfo['PV'];
                $returnOrderModel->PAY_PV = $orderInfo['PAY_PV'];
                $returnOrderModel->PAY_AMOUNT = $orderInfo['PAY_AMOUNT'];
                $returnOrderModel->PAY_TYPE = $orderInfo['PAY_TYPE'];
                $returnOrderModel->USER_ID = $orderInfo['USER_ID'];
                $returnOrderModel->PERIOD_NUM = $nowPeriodNum;
                $returnOrderModel->PAY_STATUS = $orderInfo['STATUS'];
                $returnOrderModel->PAY_NOTE = $orderInfo['NOTE'];
                $returnOrderModel->ORDER_PERIOD_NUM = $orderInfo['PERIOD_NUM'];
                $returnOrderModel->UPGRADE_TYPE = $upgradeType;
                $returnOrderModel->USER_NAME = $orderInfo['USER_NAME'];
                $returnOrderModel->PROVINCE = $orderInfo['PROVINCE'];
                $returnOrderModel->CITY = $orderInfo['CITY'] ?? 0;
                $returnOrderModel->COUNTY = $orderInfo['COUNTY'] ?? 0;
                $returnOrderModel->ADDRESS = $orderInfo['ADDRESS'] ?? '';
                $returnOrderModel->ADMIN_ID = \Yii::$app->user->id;
                $returnOrderModel->ORI_CASH = $cash;
                $returnOrderModel->ORI_BONUS = $bonus;
                $returnOrderModel->ORI_EXCHANGE_POINTS = $exchange;
                $returnOrderModel->ORI_RECONSUME_POINTS = $point;
                $returnOrderModel->ORI_DEC_LV = $oriLvs;
                $returnOrderModel->RETURN_DEC_LV = $returnLv;
                $returnOrderModel->IS_LOCKING = $isLock;
                if (!$returnOrderModel->save()) {
                    $transaction->rollBack();
                    $this->addErrors($returnOrderModel->getErrors());
                    return false;
                }
            } else {
                // 如果是PayStack支付,只处理支付成功的
                $upgradeType = 0; // 升级单类型
                $returnLv = '';
                $oriLvs = '';
                if (!empty($decInfo)) {
                    $upgradeType = $decInfo['UPGRADE_TYPE'];
                    $returnLv = $decInfo['ORI_LV'];
                    $oriLvs = $decInfo['UPGRADE_LV'];
                }

                // 退款成功,记录数据信息
                $periodObj = Period::instance();
                $nowPeriodNum = $periodObj->getNowPeriodNum();
                $returnOrderModel = new ReturnOrder();
                $returnOrderModel->ID = SnowFake::instance()->generateId();
                $returnOrderModel->SN = $sn;
                $returnOrderModel->DEC_SN = $orderInfo['DEC_SN'];
                $returnOrderModel->CREATE_AT = Date::nowTime();
                $returnOrderModel->ORDER_TYPE = $orderInfo['ORDER_TYPE'];
                $returnOrderModel->ORDER_AMOUNT = $orderInfo['ORDER_AMOUNT'];
                $returnOrderModel->PV = $orderInfo['PV'];
                $returnOrderModel->PAY_PV = $orderInfo['PAY_PV'];
                $returnOrderModel->PAY_AMOUNT = $orderInfo['PAY_AMOUNT'];
                $returnOrderModel->PAY_TYPE = $orderInfo['PAY_TYPE'];
                $returnOrderModel->USER_ID = $orderInfo['USER_ID'];
                $returnOrderModel->PERIOD_NUM = $nowPeriodNum;
                $returnOrderModel->PAY_STATUS = $orderInfo['STATUS'];
                $returnOrderModel->PAY_NOTE = $orderInfo['NOTE'];
                $returnOrderModel->ORDER_PERIOD_NUM = $orderInfo['PERIOD_NUM'];
                $returnOrderModel->UPGRADE_TYPE = $upgradeType;
                $returnOrderModel->USER_NAME = $orderInfo['USER_NAME'];
                $returnOrderModel->PROVINCE = $orderInfo['PROVINCE'];
                $returnOrderModel->CITY = $orderInfo['CITY'] ?? 0;
                $returnOrderModel->COUNTY = $orderInfo['COUNTY'] ?? 0;
                $returnOrderModel->ADDRESS = $orderInfo['ADDRESS'] ?? '';
                $returnOrderModel->ADMIN_ID = \Yii::$app->user->id;
                $returnOrderModel->ORI_CASH = 0;
                $returnOrderModel->ORI_BONUS = 0;
                $returnOrderModel->ORI_EXCHANGE_POINTS = 0;
                $returnOrderModel->ORI_RECONSUME_POINTS = 0;
                $returnOrderModel->ORI_DEC_LV = $oriLvs;
                $returnOrderModel->RETURN_DEC_LV = $returnLv;
                $returnOrderModel->IS_LOCKING = $isLock;
                if (!$returnOrderModel->save()) {
                    $transaction->rollBack();
                    $this->addErrors($returnOrderModel->getErrors());
                    return false;
                }
            }

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

        return true;
    }

    // 判断订单类型
    public function checkOrderType($attribute) {
        $sn = $this->orderSn;
        $orderDetail = Order::findUseDbCalc()
        ->select('ID,DEC_SN,USER_ID,ORDER_TYPE,IS_DELETE,PERIOD_NUM')
        ->where("SN=:SN", [':SN' => $sn])
        ->asArray()
        ->one();

        $approachOrderDetail = [];
        if (!$orderDetail) {
            $orderDetail = $approachOrderDetail = ApproachOrder::findUseDbCalc()
                ->select('ID,DEC_SN,USER_ID,ORDER_TYPE,IS_DELETE,PERIOD_NUM')
                ->where("SN=:SN", [':SN' => $sn])
                ->asArray()
                ->one();
        }

        if (empty($orderDetail)) {
            $this->addError($attribute, \Yii::t('ctx', 'shopNotFindOrder').$this->orderSn);
            return ;
        }
        if ($orderDetail['IS_DELETE'] == 1) {
            $this->addError($attribute, \Yii::t('ctx', 'shopOrderAlreadyDeleted').$this->orderSn);
            return ;
        }
        // 已挂网或者挂网中的业绩期订单,不能进行删除操作
        $periodNum = $orderDetail['PERIOD_NUM'];
        $periodObj = Period::findOneAsArray(['PERIOD_NUM'=>$periodNum]);
        if (empty($periodObj)) {
            $this->addError($attribute, \Yii::t('ctx', 'shopOrderPeriodNumNotExist', [
                'sn' => $this->orderSn,
                'periodNum' => $periodNum
            ]));
            return ;
        }
        if ($periodObj['IS_SENT'] == 1) {
            $this->addError($attribute, \Yii::t('ctx', 'shopOrderPeriodNumIsSented', [
                'sn' => $this->orderSn,
                'periodNum' => $periodNum
            ]));
            return ;
        }
        if ($periodObj['IS_SENDING'] == 1) {
            $this->addError($attribute, \Yii::t('ctx', 'shopOrderPeriodNumSenting', [
                'sn' => $this->orderSn,
                'periodNum' => $periodNum
            ]));
            return ;
        }

        if ($orderDetail['ORDER_TYPE'] == 'ZC') {
            if (!$approachOrderDetail) {
                $decDetail = DecOrder::findUseDbCalc()
                    ->select('TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,IS_DEL')
                    ->where("ORDER_SN=:ORDER_SN", [':ORDER_SN' => $sn])
                    ->asArray()
                    ->one();
            } else {
                $decDetail = ApproachDecOrder::findUseDbCalc()
                    ->select('TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,IS_DEL')
                    ->where("ORDER_SN=:ORDER_SN", [':ORDER_SN' => $sn])
                    ->asArray()
                    ->one();
            }

            if (empty($decDetail)) {
                $this->addError($attribute, \Yii::t('ctx', 'shopNotFindDecOrder').$this->orderSn);
                return ;
            }
            if ($decDetail['IS_DEL'] == 1) {
                $this->addError($attribute, \Yii::t('ctx', 'shopDecAlreadyDeleted').$this->orderSn);
                return ;
            }

            if ($decDetail['DETAIL_TYPE'] == 2) {
                if (!$approachOrderDetail) {
                    // 如果删除升级单,则此升级单必须是用户的最后一个升级单
                    $lastUpgradeOrder = DecOrder::findUseDbCalc()
                        ->select('ORDER_SN')
                        ->where("TO_USER_ID=:TO_USER_ID AND IS_DEL=0 AND DETAIL_TYPE=2", [':TO_USER_ID' => $decDetail['TO_USER_ID']])
                        ->orderBy('CREATED_AT DESC')
                        ->asArray()
                        ->one();
                } else {
                    // 如果删除升级单,则此升级单必须是用户的最后一个升级单
                    $lastUpgradeOrder = ApproachDecOrder::findUseDbCalc()
                        ->select('ORDER_SN')
                        ->where("TO_USER_ID=:TO_USER_ID AND IS_DEL=0 AND DETAIL_TYPE=2", [':TO_USER_ID' => $decDetail['TO_USER_ID']])
                        ->orderBy('CREATED_AT DESC')
                        ->asArray()
                        ->one();
                }

                $lastUpgradeSn = $lastUpgradeOrder['ORDER_SN'];
                if ($sn != $lastUpgradeSn) {
                    $this->addError($attribute, \Yii::t('ctx', 'shopHasLaterOrder').$this->orderSn);
                    return ;
                }
            } else {
                // 如果是注册单,但是这个用户存在升级单,则也不能进行删除
                if (!$approachOrderDetail) {
                    $hasUpgradeOrder = DecOrder::findUseDbCalc()
                        ->select('TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,IS_DEL')
                        ->where("TO_USER_ID=:TO_USER_ID AND IS_DEL=0 AND DETAIL_TYPE=2", [':TO_USER_ID' => $decDetail['TO_USER_ID']])
                        ->asArray()
                        ->one();
                } else {
                    $hasUpgradeOrder = ApproachDecOrder::findUseDbCalc()
                        ->select('TO_USER_ID,DETAIL_TYPE,UPGRADE_TYPE,IS_DEL')
                        ->where("TO_USER_ID=:TO_USER_ID AND IS_DEL=0 AND DETAIL_TYPE=2", [':TO_USER_ID' => $decDetail['TO_USER_ID']])
                        ->asArray()
                        ->one();
                }

                if (!empty($hasUpgradeOrder)) {
                    $this->addError($attribute, \Yii::t('ctx', 'shopRegisterHasUpgradeOrder').$this->orderSn);
                    return ;
                }

                if (!$approachOrderDetail) {
                    // 删除注册单,判断是否有复消单,如果存在复消单,需要先删除复消单
                    $hasFxOrder = Order::findUseDbCalc()
                        ->select('SN')
                        ->where("USER_ID=:USER_ID AND IS_DELETE=0 AND ORDER_TYPE='FX'", [':USER_ID' => $decDetail['TO_USER_ID']])
                        ->asArray()
                        ->one();
                } else {
                    // 删除注册单,判断是否有复消单,如果存在复消单,需要先删除复消单
                    $hasFxOrder = ApproachOrder::findUseDbCalc()
                        ->select('SN')
                        ->where("USER_ID=:USER_ID AND IS_DELETE=0 AND ORDER_TYPE='FX'", [':USER_ID' => $decDetail['TO_USER_ID']])
                        ->asArray()
                        ->one();
                }
                if (!empty($hasFxOrder)) {
                    $this->addError($attribute, \Yii::t('ctx', 'shopRegisterHasFxOrder').$this->orderSn);
                    return ;
                }
            }
        }
        return true;
    }
}
