<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Shop\Event;

use Admin\Data\Common;
use Admin\Data\Config;
use Admin\Entity\Region;
use Goods\Entity\GoodsVirtual;
use Goods\Service\GoodsVirtualManager;
use Operation\Service\Common\Discount;
use Operation\Service\UserCouponManager;
use Sales\Service\OrderDiscountRecordManager;
use Sales\Service\OrderGoodsManager;
use Sales\Service\OrderManager;
use Sales\Service\OrderSelfLocationManager;
use User\Entity\UserRecharge;
use User\Service\Common\IntegralCalculation;
use Admin\Service\Common\ShopMessage;
use Doctrine\ORM\EntityManager;
use Goods\Entity\Goods;
use Goods\Entity\GoodsInSpecGoods;
use Goods\Entity\GoodsInWholesale;
use Goods\Entity\GoodsStock;
use Goods\Entity\GoodsTag;
use Goods\Service\GoodsInSpecGoodsManager;
use Goods\Service\GoodsSalesRecordManager;
use Goods\Service\GoodsStockManager;
use Laminas\EventManager\Event;
use Laminas\EventManager\EventManagerInterface;
use Laminas\EventManager\ListenerAggregateInterface;
use Laminas\I18n\Translator\Translator;
use Laminas\Math\Rand;
use Sales\Entity\OrderGoods;
use Shop\Service\ShopUserManager;
use User\Entity\Cart;
use User\Entity\User;
use User\Service\BalanceLogManager;
use User\Service\IntegralLogManager;
use User\Service\UserIntegralConfirmManager;
use User\Service\UserManager;

class ShopListener implements ListenerAggregateInterface
{
    protected $listeners = [];

    private $entityManager;
    private $translator;
    private $writeEntityManager;
    private $shopUserManager;
    private $integralLogManager;
    private $goodsStockManager;
    private $goodsInSpecGoodsManager;
    private $goodsSalesRecordManager;
    private $balanceLogManager;
    private $userManager;
    private $userIntegralConfirmManager;
    private $orderDiscountRecordManager;
    private $goodsVirtualManager;
    private $orderManager;
    private $orderGoodsManager;
    private $orderSelfLocationManager;
    private $userCouponManager;

    public function __construct(
        EntityManager               $entityManager,
        EntityManager               $writeEntityManager,
        ShopUserManager             $shopUserManager,
        IntegralLogManager          $integralLogManager,
        GoodsStockManager           $goodsStockManager,
        GoodsInSpecGoodsManager     $goodsInSpecGoodsManager,
        GoodsSalesRecordManager     $goodsSalesRecordManager,
        BalanceLogManager           $balanceLogManager,
        UserManager                 $userManager,
        UserIntegralConfirmManager  $userIntegralConfirmManager,
        OrderDiscountRecordManager  $orderDiscountRecordManager,
        GoodsVirtualManager         $goodsVirtualManager,
        OrderManager                $orderManager,
        OrderGoodsManager           $orderGoodsManager,
        OrderSelfLocationManager    $orderSelfLocationManager,
        UserCouponManager           $userCouponManager
    )
    {
        $this->entityManager        = $entityManager;
        $this->writeEntityManager   = $writeEntityManager;
        $this->translator           = new Translator();
        $this->shopUserManager      = $shopUserManager;
        $this->integralLogManager   = $integralLogManager;
        $this->goodsStockManager    = $goodsStockManager;
        $this->goodsInSpecGoodsManager  = $goodsInSpecGoodsManager;
        $this->goodsSalesRecordManager  = $goodsSalesRecordManager;
        $this->balanceLogManager    = $balanceLogManager;
        $this->userManager          = $userManager;
        $this->userIntegralConfirmManager = $userIntegralConfirmManager;
        $this->orderDiscountRecordManager = $orderDiscountRecordManager;
        $this->goodsVirtualManager  = $goodsVirtualManager;
        $this->orderManager         = $orderManager;
        $this->orderGoodsManager    = $orderGoodsManager;
        $this->orderSelfLocationManager   = $orderSelfLocationManager;
        $this->userCouponManager    = $userCouponManager;
    }

    public function attach(EventManagerInterface $events, $priority = 1)
    {
        $shareEvents = $events->getSharedManager();

        //前台会员注册完成，发送邮件
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\UserController', 'shop.user.register.post', [$this, 'onSendRegisterMail'], 100
        );
        //前台会员注册完成，判断是否有默认值 如积分等
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\UserController', 'shop.user.register.post', [$this, 'onUserDefaultChange'], 100
        );
        //前台会员注册完成，如果需要验证，则进行此处理
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\UserController', 'shop.user.register.post', [$this, 'onUserRegisterAudi']
        );
        //购物车首页，对购物车进行处理
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CartController', 'shop.cart.index.show', [$this, 'onCartIndex'], 999
        );
        //商品添加购物车前，对商品进行检测和处理
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CartController', 'shop.cart.add.pre', [$this, 'onAddCartCheckGoods'], 999
        );
        //购物车修改商品购买数量
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CartController', 'shop.cart.editBuyNum.pre', [$this, 'onChangeGoodsBuyNum'], 999
        );

        //结账，对购物车内的商品进行处理
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.one.post', [$this, 'onShopCheckout'], 999
        );
        //结账，购物的商品库存减少（如果商品设置有货，则不减少）,销量修改
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.two.post', [$this, 'onShopGoodsChangeStock'], 99
        );
        //结账，添加优惠记录
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.two.post', [$this, 'onOrderDiscountRecord'], 95
        );
        //结账，购物获取的积分、优惠券等处理
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\CheckoutController', 'shop.checkout.two.post', [$this, 'onUserGetConfirm'], 90
        );

        //后台订单支付完成，进行处理
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.pay.post', [$this, 'onBackstageOrderPayFinish']
        );
        //后台订单发货完成，进行虚拟商品发货
        $this->listeners[] = $shareEvents->attach(
            'Sales\Controller\IndexController', 'backstage-order.ship.post', [$this, 'onSendVirtualGoods']
        );
        //订单支付完成，进行处理（跳转返回）
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\ReturnController', 'shop.order.returnPayFinish.post', [$this, 'onReturnPayFinishOperation']
        );
        //订单余额支付完成，进行处理（跳转返回）
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\ReturnController', 'shop.order.balancePayFinish.post', [$this, 'onReturnPayFinishOperation']
        );
        //订单支付完成，进行处理（通知返回）
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\NotifyController', 'shop.order.notifyPayFinish.post', [$this, 'onNotifyPayFinishOperation']
        );

        //充值跳转支付完成，修改客户余额
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\ReturnController', 'shop.recharge.returnPayFinish.post', [$this, 'onUserReturnBalanceChange']
        );
        //充值异步支付完成，修改客户余额
        $this->listeners[] = $shareEvents->attach(
            'Shop\Controller\NotifyController', 'shop.recharge.notifyPayFinish.post', [$this, 'onUserBalanceChange']
        );
    }

    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            $events->detach($listener);
            unset($this->listeners[$index]);
        }
    }

    /**
     * 注册客户发送欢迎电邮
     * @param Event $event
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onSendRegisterMail(Event $event)
    {
        $userInfo   = $event->getParam('user');
        $emailTitle = Common::configValue('welcome_email_title', 'customer');
        $emailBody  = Common::configValue('welcome_email_body', 'customer');
        if(
            Common::configValue('register_welcome_email', 'customer') == 1
            && !empty($emailTitle)
            && !empty($emailBody)
            && !empty($userInfo->getUserEmail())
        ) {
            ShopMessage::sendMail([
                'mail'      => $userInfo->getUserEmail(),
                'subject'   => str_replace(['{userName}', '{shopName}'], [$userInfo->getUserName(), Common::configValue('base', 'config')['shop_name']], $emailTitle),
                'body'      => str_replace(
                    ['{userName}', '{shopNameUrl}', '{shopName}', '{time}'],
                    [$userInfo->getUserName(), '<a href="'.$event->getTarget()->url()->fromRoute('shop', [], ['force_canonical' => true]).'" target="_blank">'.Common::configValue('base', 'config')['shop_name'].'</a>', Common::configValue('base', 'config')['shop_name'], date("Y-m-d H:i", time())],
                    $emailBody)
            ]);
        }
    }

    /**
     * 注册客户需要验证时的处理
     * @param Event $event
     * @throws \PHPMailer\PHPMailer\Exception
     */
    public function onUserRegisterAudi(Event $event)
    {
        $userInfo = $event->getParam('user');
        if($userInfo->getUserStatus() == 3) {
            $userRegisterAudit = Common::configValue('user_register_audit', 'customer');
            if($userRegisterAudit == 'audit') $event->getTarget()->flashMessenger()->addSuccessMessage($this->translator->translate('注册成功，请等待官方审核'));

            if($userRegisterAudit == 'email' && !empty($userInfo->getUserEmail())) {
                $emailAuditCode = Rand::getString(50);
                $auditUrl       = $event->getTarget()->url()->fromRoute('shop-user', ['action' => 'userEmailAudit'], ['query' => ['auditCode' => $emailAuditCode], 'force_canonical' => true]);
                $this->shopUserManager->updateUserEmailAuditCode($emailAuditCode, $userInfo->getUserId());
                ShopMessage::sendMail([
                    'mail'      => $userInfo->getUserEmail(),
                    'subject'   => $this->translator->translate('会员注册审核邮件'),
                    'body'      => $userInfo->getUserName() . '：<br>' . $this->translator->translate('您好，感谢您注册我们的会员，请点击会员审核链接完成会员的身份认证') . '<br><a href="'.$auditUrl.'" target="_blank">'.$auditUrl.'</a>'
                ]);

                $event->getTarget()->flashMessenger()->addSuccessMessage($this->translator->translate('认证邮件已经发送到您的邮箱，请查看'));
            }
        }
    }

    /**
     * 会员注册，默认值设置
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onUserDefaultChange(Event $event)
    {
        $userInfo = $event->getParam('user');
        $defaultIntegralType1Num = Common::configValue('integral_type_1', 'integral')['integralDefaultNum'];
        $defaultIntegralType2Num = Common::configValue('integral_type_2', 'integral')['integralDefaultNum'];

        if($defaultIntegralType1Num == 0 && $defaultIntegralType2Num == 0) {//只有当积分类型的初始化值都为0时，启用积分规则中的会员注册类型
            $registerIntegralArray      = IntegralCalculation::userRegisterIntegral();
            $defaultIntegralType1Num    = $registerIntegralArray['integralType1'];
            $defaultIntegralType2Num    = $registerIntegralArray['integralType2'];
        }

        $updateIntegralArray = [];
        if($defaultIntegralType1Num > 0) $updateIntegralArray['integralType1Num'] = $userInfo->getIntegralType1Num() + $defaultIntegralType1Num;
        if($defaultIntegralType2Num > 0) $updateIntegralArray['integralType2Num'] = $userInfo->getIntegralType2Num() + $defaultIntegralType2Num;
        if(!empty($updateIntegralArray)) {
            if($this->shopUserManager->updateUserUserIntegral($updateIntegralArray, $userInfo->getUserId())) {
                if($defaultIntegralType1Num > 0) {
                    $this->integralLogManager->addIntegralLog([
                        'userId'            => $userInfo->getUserId(),
                        'userName'          => $userInfo->getUserName(),
                        'integralLogInfo'   => $this->translator->translate('客户注册').'+'.$defaultIntegralType1Num,
                        'changeIntegralNum' => $defaultIntegralType1Num,
                        'integralNum'       => $updateIntegralArray['integralType1Num'],
                        'integralTypeId'    => 1,
                        'integralLogTime'   => time(),
                        'adminId'           => 0
                    ]);
                }
                if($defaultIntegralType2Num > 0) {
                    $this->integralLogManager->addIntegralLog([
                        'userId'            => $userInfo->getUserId(),
                        'userName'          => $userInfo->getUserName(),
                        'integralLogInfo'   => $this->translator->translate('客户注册').'+'.$defaultIntegralType2Num,
                        'changeIntegralNum' => $defaultIntegralType2Num,
                        'integralNum'       => $updateIntegralArray['integralType2Num'],
                        'integralTypeId'    => 2,
                        'integralLogTime'   => time(),
                        'adminId'           => 0
                    ]);
                }
            }
        }
    }

    /**
     * 购物车首页，对购物车进行处理
     * @param Event $event
     * @return mixed|null
     */
    public function onCartIndex(Event $event)
    {
        $cartGoodsList      = $event->getParam('cartGoodsList');
        $cartAmount         = 0.00;
        $haveGoodsChecked   = false;
        $cartGoodsArray     = [];
        if($cartGoodsList) {
            $userGroupId = $event->getParam('user_group_id');
            foreach ($cartGoodsList as $key => $value) {
                $goodsGroupPrice = [];
                if($value[0]->getInSpecGoodsId() > 0) {//有商品规格
                    if(!empty($value['specGoodsUserGroupPrice'])) $goodsGroupPrice = unserialize($value['specGoodsUserGroupPrice']);
                    $goodsPrice     = $value['specGoodsPrice'];
                    $goodsItem      = $value['specGoodsItem'];
                    $goodsStockOut  = $value['specGoodsStock'] < $value[0]->getBuyNum();
                    $value['specGoodsTagInfo'] = $this->entityManager->getRepository(GoodsTag::class)->findGoodsTagAndTagGroup(explode('-', $value['specTagId']));
                } else {//无商品规格
                    if(!empty($value['goodsUserGroupPrice'])) $goodsGroupPrice = unserialize($value['goodsUserGroupPrice']);
                    $goodsPrice = $value['goodsPrice'];
                    $goodsItem  = $value['goodsItem'];
                    $goodsStockOut  = $value['stockNum'] < $value[0]->getBuyNum();
                }

                $value['goodsStockOut'] = $value['stockShowState'] == 0 ? $goodsStockOut : false;//缺货状态，true 缺货，false 不缺货

                //价格判断处理，会员价、批发价、正常价
                if($value['wholesaleState'] == 1 && $value['wholesalePrice'] > 0) $value['goodsPrice'] = $value['wholesalePrice'];
                else $value['goodsPrice'] = (isset($goodsGroupPrice[$userGroupId]) && $goodsGroupPrice[$userGroupId] > 0) ? $goodsGroupPrice[$userGroupId] : $goodsPrice;

                //判读是否有有效的优惠价格，如果有，则优先使用
                if ($value['discountPrice'] > 0 && Common::checkTime($value['discountStartTime'], $value['discountEndTime']) && Common::checkUser($userGroupId, $value['discountUserGroupType'], unserialize($value['discountUserGroup']))) {
                    $value['goodsPrice'] = $value['discountPrice'];
                }

                $value['goodsItem']     = $goodsItem;
                $value['goodsAmount']   = $value['goodsPrice'] * $value[0]->getBuyNum();

                $cartGoodsArray[$key]    = $value;

                if($value[0]->getGoodsChecked() == 1 && !$value['goodsStockOut'] && $value['goodsState'] == 1) {
                    if(!$haveGoodsChecked) $haveGoodsChecked = true;
                    $cartAmount = $cartAmount + $value['goodsAmount'];
                }
            }
        }

        return ['cartAmount' => $cartAmount, 'cartGoodsList' => $cartGoodsArray, 'haveGoodsChecked' => $haveGoodsChecked];
    }

    /**
     * 结账，对购物车内的商品进行处理
     * @param Event $event
     * @return array
     */
    public function onShopCheckout(Event $event)
    {
        $cartGoodsList  = $event->getParam('cartGoodsList');
        $userGroupId    = $event->getParam('userGroupId');
        $addressInfo    = $event->getParam('addressInfo');
        $deliveryType   = $event->getParam('deliveryType');
        $totalWeight        = 0;    //商品总重量
        $deliveryFee        = 0;    //配送费用
        $goodsIntegralBuy   = 0;    //可用积分购买的积分数量
        $cartAmount         = 0.00; //商品金额
        $allGoodsVirtual    = true;
        $haveGoodsVirtual   = false;
        $cartGoodsArray     = [];
        if ($cartGoodsList) {
            foreach ($cartGoodsList as $key => $value) {
                //下架商品
                if ($value['goodsState'] != 1) continue;

                $goodsGroupPrice = [];
                if ($value[0]->getInSpecGoodsId() > 0) {//有商品规格
                    if(!empty($value['specGoodsUserGroupPrice'])) $goodsGroupPrice = unserialize($value['specGoodsUserGroupPrice']);
                    $goodsPrice     = $value['specGoodsPrice'];
                    $goodsItem      = $value['specGoodsItem'];
                    $goodsStockOut  = $value['specGoodsStock'] < $value[0]->getBuyNum();
                    $totalWeight    = $totalWeight + $value['specGoodsWeight'] * $value['goodsWeightConversion'] * $value[0]->getBuyNum();
                    $value['specGoodsTagInfo'] = $this->entityManager->getRepository(GoodsTag::class)->findGoodsTagAndTagGroup(explode('-', $value['specTagId']));
                } else {//无商品规格
                    if(!empty($value['goodsUserGroupPrice'])) $goodsGroupPrice = unserialize($value['goodsUserGroupPrice']);
                    $goodsPrice     = $value['goodsPrice'];
                    $goodsItem      = $value['goodsItem'];
                    $goodsStockOut  = $value['stockNum'] < $value[0]->getBuyNum();
                    $totalWeight    = $totalWeight + $value['goodsWeight'] * $value['goodsWeightConversion'] * $value[0]->getBuyNum();
                }

                //判断商品里是否有实物商品，如果有则 $allGoodsVirtual 为false
                if ($value['goodsType'] == 1 && $allGoodsVirtual == true) $allGoodsVirtual = false;
                //判断商品里是否有虚拟商品，如果有则 $haveGoodsVirtual 为 true
                if ($value['goodsType'] == 2 && $haveGoodsVirtual == false) $haveGoodsVirtual = true;

                $goodsStockOut = $value['stockShowState'] == 0 ? $goodsStockOut : false;//缺货状态，true 缺货，false 不缺货
                if ($goodsStockOut) continue;

                //价格判断处理，会员价、批发价、正常价
                if ($value['wholesaleState'] == 1 && $value['wholesalePrice'] > 0) $value['goodsPrice'] = $value['wholesalePrice'];
                else $value['goodsPrice'] = (isset($goodsGroupPrice[$userGroupId]) && $goodsGroupPrice[$userGroupId] > 0) ? $goodsGroupPrice[$userGroupId] : $goodsPrice;

                //判读是否有有效的优惠价格，如果有，则优先使用
                if ($value['discountPrice'] > 0 && Common::checkTime($value['discountStartTime'], $value['discountEndTime']) && Common::checkUser($userGroupId, $value['discountUserGroupType'], unserialize($value['discountUserGroup']))) {
                    $value['goodsPrice'] = $value['discountPrice'];
                }

                $value['goodsItem']     = $goodsItem;
                $value['goodsAmount']   = $value['goodsPrice'] * $value[0]->getBuyNum();

                //如果该产品可以使用积分购买，则进行积分求和计算
                if ($value['goodsIntegralBuy'] == 1) $goodsIntegralBuy = $goodsIntegralBuy + $value['goodsAmount'] * Common::configValue('integral_type_1', 'integral')['integralCurrencyCon'] * 100;

                $cartGoodsArray[$key]   = $value;

                $cartAmount = $cartAmount + $value['goodsAmount'];
            }
        }

        //无有效商品，则跳转回购物车页面
        if (empty($cartGoodsArray)) {
            $event->getTarget()->flashMessenger()->addWarningMessage($this->translator->translate('购物车中无有效商品!'));
            header("Location: ".$event->getTarget()->url()->fromRoute('shop-cart'));
            exit();
        }

        //订单金额
        $orderAmount = $cartAmount;

        //配送费用
        $deliveryExist = false;
        if ($deliveryType != 'self-fetch' && $addressInfo != null && !$allGoodsVirtual) {
            $shopDelivery = Common::readConfigFile('delivery');
            if ($shopDelivery['deliverySet'] == 'T') {
                $deliveryExist  = true;
                $deliveryFee    = $event->getTarget()->deliveryPlugin()->calculateCost(Common::readConfigFile('delivery')['deliveryPrice'], $totalWeight, $cartAmount);
            } else {
                $regionInfo     = $this->entityManager->getRepository(Region::class)->findOneBy(['regionId' => $addressInfo->getRegionId()]);
                $regionIdArray  = explode(',', $regionInfo->getRegionPath());
                if (!empty($regionIdArray) && !empty($shopDelivery['G'])) {
                    foreach ($shopDelivery['G'] as $deliveryG) {
                        if(array_intersect($regionIdArray, $deliveryG['area']) != null) {
                            if(!$deliveryExist) $deliveryExist = true;
                            $price      = $event->getTarget()->deliveryPlugin()->calculateCost($deliveryG['price'], $totalWeight, $cartAmount);
                            $deliveryFee= ($deliveryFee > 0 && $deliveryFee < $price) ? $deliveryFee : $price;
                        }
                    }
                }
            }
            if ($deliveryFee > 0) $orderAmount = $orderAmount + $deliveryFee;
        }

        //优惠促销
        $discountCost = Discount::discountCalculation($cartGoodsArray, ['userId' => $event->getParam('userId'), 'userGroupId' => $userGroupId], $this->entityManager, $this->translator);
        if ($discountCost['discountCost'] > 0) $orderAmount = $orderAmount - $discountCost['discountCost'];

        //获取积分计算
        $integral = IntegralCalculation::buyGoodsCartIntegral($cartGoodsArray, ['userGroupId' => $userGroupId, 'discountCost' => $discountCost['discountCost']]);

        //post 提交（就是提交订单的处理）
        $integralPrice = 0;
        $useIntegralNum= 0;
        $postArray = $event->getParam('postArray');
        if (!empty($postArray)) {
            $userInfo = $event->getParam('userInfo');
            $useIntegralNum = isset($postArray['useIntegralNum']) ? intval($postArray['useIntegralNum']) : 0;
            if ($userInfo->getIntegralType1Num() > 0 && $goodsIntegralBuy > 0 && $useIntegralNum > 0 && $useIntegralNum <= $goodsIntegralBuy && $useIntegralNum <= $userInfo->getIntegralType1Num()) {
                $integralPrice  = $useIntegralNum/Common::configValue('integral_type_1', 'integral')['integralCurrencyCon']/100;
                if ($orderAmount >= $integralPrice) $orderAmount = $orderAmount - $integralPrice;
            }
        }

        $array = [
            'orderAmount'       => $orderAmount,    //订单金额
            'cartAmount'        => $cartAmount,     //购物车金额
            'cartGoodsList'     => $cartGoodsArray, //购物车商品数组
            'allGoodsVirtual'   => $allGoodsVirtual,//是否全部为虚拟商品
            'haveGoodsVirtual'  => $haveGoodsVirtual,//全部商品中是否有虚拟商品
            'deliveryFee'       => $deliveryFee,    //配送费用
            'deliveryExist'     => $deliveryExist,  //是否需要配送
            'totalWeight'       => $totalWeight,    //商品重量
            'goodsIntegralBuy'  => $goodsIntegralBuy,//可积分购买的商品积分（非客户现有的消费积分）
            'integral'          => $integral,        //购物获取的积分

            'discountCost'      => $discountCost,   //优惠促销
            'useIntegralNum'    => $useIntegralNum, //用积分购买数
            'integralPrice'     => $integralPrice,  //积分对应的基础金额
        ];
        $event->setParams(array_merge($event->getParams(), ['lastArray' => $array]));

        return $array;
    }

    /**
     * 添加购物车前，对商品进行检测处理
     * @param Event $event
     * @return array
     */
    public function onAddCartCheckGoods(Event $event)
    {
        $goodsData = $event->getParam('goodsData');

        $userId = $event->getTarget()->shopPlugin()->getUserLoginData('user_id');
        //检查客户购物车内商品数量是否超过系统限制
        $userCartGoodsNum = $this->entityManager->getRepository(Cart::class)->count(['userId' => $userId, 'buyNow' => 0]);
        if($userCartGoodsNum >= Config::USER_CART_GOODS_MAX_NUM) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => $this->translator->translate('购物车内商品数量超过系统允许的最大数量，请清理后再次进行添加!')];
        }

        //检查添加的商品是否存在
        $goodsInfo = $this->entityManager->getRepository(Goods::class)->findOneBy(['goodsId' => $goodsData['goodsId'], 'goodsState' => 1]);
        if($goodsInfo == null) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => $this->translator->translate('该商品不存在或已经下架，无法添加购物车!')];
        }

        if(!empty($goodsData['specTagIdStr'])) {//传递了商品规格字符串，检查规格商品
            $specTagIdArray = array_filter(explode(',', $goodsData['specTagIdStr']));
            sort($specTagIdArray);
            $goodsInSpecGoods = $this->entityManager->getRepository(GoodsInSpecGoods::class)->findOneBy(['goodsId' => $goodsData['goodsId'], 'tagIdStr' => implode('', $specTagIdArray)]);
            if(!$goodsInSpecGoods) {
                $event->stopPropagation(true);
                return ['status' => 'true', 'inSpecGoods' => 'true', 'message' => $this->translator->translate('请选择商品规格后，再进行购物车添加!'), 'toUrl' => $event->getTarget()->url()->fromRoute('shop-goods', ['id' => $goodsData['goodsId']], ['force_canonical' => true])];
            }
        } else {//未传递商品规格字符串，检查是否有规格商品
            $goodsInSpecGoods = $this->entityManager->getRepository(GoodsInSpecGoods::class)->findOneBy(['goodsId' => $goodsData['goodsId']]);
            if($goodsInSpecGoods) {
                $event->stopPropagation(true);
                return ['status' => 'true', 'inSpecGoods' => 'true', 'message' => $this->translator->translate('请选择商品规格后，再进行购物车添加!'), 'toUrl' => $event->getTarget()->url()->fromRoute('shop-goods', ['id' => $goodsData['goodsId']], ['force_canonical' => true])];
            }
        }

        //购买限制
        $goodsStock = $this->entityManager->getRepository(GoodsStock::class)->findOneBy(['goodsId' => $goodsData['goodsId']]);
        if($goodsStock->getCartBuyMinNum() > 0 && $goodsStock->getCartBuyMinNum() > $goodsData['buyNum']) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => sprintf($this->translator->translate('该商品最少购买数量是 %s!'), $goodsStock->getCartBuyMinNum())];
        }
        if($goodsStock->getCartBuyMaxNum() > 0 && $goodsStock->getCartBuyMaxNum() < $goodsData['buyNum']) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => sprintf($this->translator->translate('该商品最多购买数量是 %s!'), $goodsStock->getCartBuyMaxNum())];
        }
        if($goodsStock->getPersonBuyMax() > 0) {//每人购买次数限制
            $orderGoodsNum = $this->entityManager->getRepository(OrderGoods::class)->count(['goodsId' => $goodsData['goodsId'], 'userId' => $userId]);
            if($orderGoodsNum >= $goodsStock->getPersonBuyMax()) {
                $event->stopPropagation(true);
                return ['status' => 'false', 'message' => sprintf($this->translator->translate('该商品最多购买 %s 次，您已经达到购买次数上限，不能再次购买!'), $goodsStock->getPersonBuyMax())];
            }
        }

        //库存检查
        if($goodsStock->getStockShowState() == 0) {
            if(isset($specTagIdArray) && !empty($specTagIdArray)) {//有规格商品
                if($goodsInSpecGoods->getSpecGoodsStock() < $goodsData['buyNum']) {
                    $event->stopPropagation(true);
                    return ['status' => 'false', 'message' => $this->translator->translate('该商品库存不足!')];
                }
            } else {//无规格商品
                if($goodsStock->getStockNum() < $goodsData['buyNum']) {
                    $event->stopPropagation(true);
                    return ['status' => 'false', 'message' => $this->translator->translate('该商品库存不足!')];
                }
            }
        }

        //检查是否有批发，获取批发记录id
        if($goodsInfo->getWholesaleState() == 1) {
            $wholesale = $this->entityManager->getRepository(GoodsInWholesale::class)->findGoodsInWholesale($goodsData['buyNum']);
            $goodsData['inWholesaleId'] = ($wholesale == null ? 0 : $wholesale->getInWholesaleId());
        } else $goodsData['inWholesaleId'] = 0;

        return $goodsData;
    }

    /**
     * 购物车商品修改购买数量时，对库存进行检查
     * @param Event $event
     * @return array
     */
    public function onChangeGoodsBuyNum(Event $event)
    {
        $data = $event->getParams();

        //购买限制
        if($data['cartGoods']['cartBuyMinNum'] > 0 && $data['cartGoods']['cartBuyMinNum'] > $data['buyNum']) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => sprintf($this->translator->translate('该商品最少购买数量是 %s!'), $data['cartGoods']['cartBuyMinNum'])];
        }
        if($data['cartGoods']['cartBuyMaxNum'] > 0 && $data['cartGoods']['cartBuyMaxNum'] < $data['buyNum']) {
            $event->stopPropagation(true);
            return ['status' => 'false', 'message' => sprintf($this->translator->translate('该商品最多购买数量是 %s!'), $data['cartGoods']['cartBuyMaxNum'])];
        }

        //商品没有开启库存显示时，不进行库存判断
        if($data['cartGoods']['stockShowState'] == 0) {
            if($data['cartGoods'][0]->getInSpecGoodsId() > 0) {
                if($data['cartGoods']['specGoodsStock'] < $data['buyNum']) {
                    $event->stopPropagation(true);
                    return ['status' => 'false', 'message' => $this->translator->translate('该商品库存不足!')];
                }
            } else {
                if($data['cartGoods']['stockNum'] < $data['buyNum']) {
                    $event->stopPropagation(true);
                    return ['status' => 'false', 'message' => $this->translator->translate('该商品库存不足!')];
                }
            }
        }

        //检查是否有批发，获取批发记录id
        if($data['cartGoods']['wholesaleState'] == 1) {
            $wholesale = $this->entityManager->getRepository(GoodsInWholesale::class)->findGoodsInWholesale($data['buyNum']);
            $data['inWholesaleId'] = ($wholesale == null ? 0 : $wholesale->getInWholesaleId());
        } else $data['inWholesaleId'] = 0;

        return $data;
    }

    /**
     * 结账，购物的商品库存减少（如果商品设置有货，则不减少），销量修改
     * @param Event $event
     */
    public function onShopGoodsChangeStock(Event $event)
    {
        $orderInfo = $event->getParam('orderInfo');
        foreach ($orderInfo->getOrderGoods() as $goodsValue) {
            $goodsStock = $this->entityManager->getRepository(GoodsStock::class)->findOneBy(['goodsId' => $goodsValue->getGoodsId()]);
            if($goodsStock && $goodsStock->getStockShowState() == 0) {
                if($goodsValue->getInSpecGoodsId() > 0) {
                    $this->goodsInSpecGoodsManager->editInSpecGoodsStock($goodsValue->getBuyNum(), '-', $goodsValue->getInSpecGoodsId(), $goodsValue->getGoodsId());
                } else {
                    $this->goodsStockManager->changeGoodsStockNum($goodsValue->getBuyNum(), '-', $goodsValue->getGoodsId());
                }
            }
            //修改，增加
            $this->goodsSalesRecordManager->changeGoodsSalesNum($goodsValue->getBuyNum(), '+', $goodsValue->getGoodsId());
        }
    }

    /**
     * 添加订单优惠记录
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onOrderDiscountRecord(Event $event)
    {
        $orderInfo  = $event->getParam('orderInfo');
        $array      = $event->getParam('array');
        $defaultCurrency = $event->getParam('defaultCurrency');

        //优惠促销的记录添加
        if ($array['discountCost']['discountCost'] > 0) {
            $this->orderDiscountRecordManager->addOrderDiscountRecord(
                [
                    'discountCost'  => $array['discountCost']['discountCost'],
                    'discountType'  => $array['discountCost']['discountType'],
                    'discountInfo'  => $array['discountCost']['discountTitle'],
                    'orderId'       => $orderInfo->getOrderId(),
                    'userId'        => $orderInfo->getUserId(),
                    'id'            => $array['discountCost']['discountId']
                ], $defaultCurrency);
        }

        //优惠券优惠记录添加
        if (isset($array['orderCoupon']) && !empty($array['orderCoupon'])) {
            $this->orderDiscountRecordManager->addOrderDiscountRecord(
                [
                    'discountCost'  => $array['orderCoupon']['couponPrice'],
                    'discountType'  => 'coupon',
                    'discountInfo'  => $array['orderCoupon']['couponTitle'],
                    'orderId'       => $orderInfo->getOrderId(),
                    'userId'        => $orderInfo->getUserId(),
                    'id'            => $array['orderCoupon']['couponId']
                ], $defaultCurrency);
            $this->userCouponManager->editUserCoupon([
                'couponUseState'=> 2,
                'usedOrderId'   => $orderInfo->getOrderId(),
                'usedOrderSn'   => $orderInfo->getOrderSn(),
                'usedTime'      => time()
            ], $array['userCouponInfo']);
        }

        //积分购买的积分添加
        if ($array['integralPrice'] > 0) {
            $integralType1Num = $array['userInfo']->getIntegralType1Num() - $array['useIntegralNum'];
            $this->shopUserManager->updateUserUserIntegral(['integralType1Num' => $integralType1Num], $orderInfo->getUserId());
            //添加积分优惠记录
            $this->orderDiscountRecordManager->addOrderDiscountRecord(
                [
                    'discountCost'  => $array['integralPrice'],
                    'discountType'  => 'integral',
                    'discountInfo'  => $this->translator->translate('积分购买'),
                    'orderId'       => $orderInfo->getOrderId(),
                    'userId'        => $orderInfo->getUserId(),
                    'id'            => $array['useIntegralNum'] //积分数
                ], $defaultCurrency);
            //添加积分记录
            $this->integralLogManager->addIntegralLog([
                'userId'            => $orderInfo->getUserId(),
                'userName'          => $orderInfo->getUserName(),
                'integralLogInfo'   => $this->translator->translate('积分购物').'-'.$array['useIntegralNum'].' '.$this->translator->translate('订单编号').$orderInfo->getOrderSn(),
                'changeIntegralNum' => '-'.$array['useIntegralNum'],
                'integralNum'       => $integralType1Num,
                'integralTypeId'    => 1,
                'integralLogTime'   => time(),
                'adminId'           => 0
            ]);

        }
    }

    /**
     * 结账时，判断是否有积分、优惠券等获取
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onUserGetConfirm(Event $event)
    {
        $array      = $event->getParam('array');
        $orderInfo  = $event->getParam('orderInfo');
        //积分获取
        if (isset($array['integral'])) {
            $integral = $array['integral'];
            if($integral['integralType1Num'] > 0 || $integral['integralType2Num'] > 0) {
                $this->userIntegralConfirmManager->addUserIntegralConfirm([
                    'integralType1Num'  => $integral['integralType1Num'],
                    'integralType2Num'  => $integral['integralType2Num'],
                    'userId'            => $orderInfo->getUserId(),
                    'id'                => $orderInfo->getOrderId(),
                    'confirmType'       => 'order',
                    'confirmState'      => 0,
                    'addTime'           => time()
                ]);
            }
        }

        //优惠券获取
        if (isset($array['addUserCoupon'])) {
            $addOrderCoupon = $array['addUserCoupon'];
            if (!empty($addOrderCoupon)) foreach ($addOrderCoupon as $couponValue) {
                $this->userCouponManager->addUserCoupon([
                    'couponUseState' => 0,
                    'userId'        => $orderInfo->getUserId(),
                    'userName'      => $orderInfo->getUserName(),
                    'getTime'       => time(),
                    'couponId'      => $couponValue['couponId'],
                    'couponTitle'   => $couponValue['couponTitle'],
                    'couponInfo'    => $couponValue['couponInfo'],
                    'couponUseStartTime'=> $couponValue['couponStartTime'],
                    'couponUseEndTime'  => $couponValue['couponEndTime'],
                    'getOrderId'    => $orderInfo->getOrderId(),
                    'getOrderSn'    => $orderInfo->getOrderSn()
                ]);
            }
        }
    }

    /**
     * 后台支付完成，操作
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onBackstageOrderPayFinish(Event $event)
    {
        $orderInfo  = $event->getParam('orderInfo');
        //到店自提，则进行提货码生成保存处理
        if ($orderInfo->getDeliveryType() == 'selfFetch') {
            $this->orderSelfLocationManager->addOrderSelfLocationTakeCode($orderInfo->getOrderId());
        }
        //如果有虚拟商品进行发货处理
        $this->sendVirtualGoods($event, $orderInfo);
    }

    /**
     *  跳转获取付款完成时，操作
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onReturnPayFinishOperation(Event $event)
    {
        $orderInfo  = $event->getParam('orderInfo');
        $payConfig  = Common::getPaymentConfig($orderInfo->getPaymentCode());
        if ($payConfig['noticeMode'] == 'returnNotice') {
            //到店自提，则进行提货码生成保存处理
            if ($orderInfo->getDeliveryType() == 'selfFetch') {
                $this->orderSelfLocationManager->addOrderSelfLocationTakeCode($orderInfo->getOrderId());
            }

            //如果有虚拟商品进行发货处理
            $this->sendVirtualGoods($event, $orderInfo);
        }
    }

    /**
     * 通知获取付款完成时，操作
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onNotifyPayFinishOperation(Event $event)
    {
        $orderInfo  = $event->getParam('orderInfo');
        $payConfig  = Common::getPaymentConfig($orderInfo->getPaymentCode());
        if ($payConfig['noticeMode'] == 'asyncNotice') {
            //到店自提，则进行提货码生成保存处理
            if ($orderInfo->getDeliveryType() == 'selfFetch') {
                $this->orderSelfLocationManager->addOrderSelfLocationTakeCode($orderInfo->getOrderId());
            }

            $this->sendVirtualGoods($event, $orderInfo);
        }
    }

    /**
     * 后台支付完成，进行虚拟商品发货处理
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onSendVirtualGoods(Event $event)
    {
        $orderInfo  = $event->getParam('orderInfo');
        $this->sendVirtualGoods($event, $orderInfo);
    }

    /**
     * 余额充值成功，客户余额进行更新
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onUserReturnBalanceChange(Event $event)
    {
        $rechargeInfo   = $event->getParam('rechargeInfo');
        $payConfig      = $event->getParam('payConfig');
        if ($payConfig['noticeMode'] == 'returnNotice') {
            $this->updateUserBalance($rechargeInfo);
        }
    }

    /**
     * 余额充值成功，客户余额进行更新
     * @param Event $event
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function onUserBalanceChange(Event $event)
    {
        $rechargeInfo   = $event->getParam('rechargeInfo');
        $payConfig      = Common::getPaymentConfig($rechargeInfo->getPayCode());
        if ($payConfig['noticeMode'] == 'asyncNotice') {
            $this->updateUserBalance($rechargeInfo);
        }
    }

    /**
     * 修改会员余额信息
     * @param UserRecharge $rechargeInfo
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    private function updateUserBalance(UserRecharge $rechargeInfo)
    {
        $userInfo       = $this->writeEntityManager->getRepository(User::class)->findOneBy(['userId' => $rechargeInfo->getUserId()]);
        if($rechargeInfo->getBaseRechargeNum() > 0 && $userInfo) {
            $userMoney = $userInfo->getUserMoney() + $rechargeInfo->getBaseRechargeNum();
            $this->balanceLogManager->addBalanceLog([
                'userId'    => $rechargeInfo->getUserId(),
                'userName'  => $rechargeInfo->getUserName(),
                'balanceChangeType' => 2,
                'balanceChangeNum'  => $rechargeInfo->getBaseRechargeNum(),
                'balanceChangedAmount' => $userMoney,
                'balanceChangeTime' => time(),
                'balanceChangeInfo' => $this->translator->translate('余额充值')
            ]);
            $this->userManager->updateUserMoney($userMoney, $userInfo);
        }
    }

    /**
     * 发送虚拟商品
     * @param $event
     * @param $orderInfo
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    private function sendVirtualGoods($event, $orderInfo)
    {
        $virtualGoodsList = $this->writeEntityManager->getRepository(OrderGoods::class)->findBy(['orderId' => $orderInfo->getOrderId(), 'userId' => $orderInfo->getUserId(), 'goodsType' => 2, 'goodsStatus' => 0]);
        if ($virtualGoodsList) {
            $virtualGoodsStockFew = [];//虚拟商品库存不足时，存储内容的数组
            foreach ($virtualGoodsList as $orderVirtualGoods) {
                $vGoodsNum2 = $this->entityManager->getRepository(GoodsVirtual::class)->count(['goodsId' => $orderVirtualGoods->getGoodsId(), 'virtualGoodsState' => 2, 'orderId' => $orderVirtualGoods->getOrderId()]);
                if ($vGoodsNum2 >= $orderVirtualGoods->getBuyNum()) continue;
                if ($vGoodsNum2 > 0) $sendVirtualNum = $orderVirtualGoods->getBuyNum() - $vGoodsNum2;
                else $sendVirtualNum = $orderVirtualGoods->getBuyNum();

                for ($i = 0; $i < $sendVirtualNum; $i++) {
                    $goodsVirtualInfo = $this->writeEntityManager->getRepository(GoodsVirtual::class)->findOneBy(['goodsId' => $orderVirtualGoods->getGoodsId(), 'virtualGoodsState' => 1]);
                    if ($goodsVirtualInfo && ($goodsVirtualInfo->getVirtualGoodsEndTime() == 0 || ($goodsVirtualInfo->getVirtualGoodsEndTime() > 0 && $goodsVirtualInfo->getVirtualGoodsEndTime() >= time()))) {

                        $updateVirtualGoods = [
                            'orderSn'           => $orderInfo->getOrderSn(),
                            'virtualGoodsState' => 2,
                            'orderId'           => $orderInfo->getOrderId(),
                            'userId'            => $orderInfo->getUserId(),
                            'userName'          => $orderInfo->getUserName()
                        ];
                        if ($goodsVirtualInfo->getVirtualGoodsAccountType() != 1 || $goodsVirtualInfo->getVirtualGoodsPasswordType() != 1) {
                            if ($goodsVirtualInfo->getVirtualGoodsAccountType() == 2) {
                                mt_srand((double) microtime() * 1000000);
                                $updateVirtualGoods['virtualGoodsAccount'] = 'U' . date('Ymd') . str_pad(mt_rand(1, 999999), 6, '0', STR_PAD_LEFT);
                            } elseif (in_array($goodsVirtualInfo->getVirtualGoodsAccountType(), [1, 3])) $updateVirtualGoods['virtualGoodsAccount'] = $goodsVirtualInfo->getVirtualGoodsAccount();

                            if ($goodsVirtualInfo->getVirtualGoodsPasswordType() == 2) {
                                $chars = range('a', 'z');
                                $updateVirtualGoods['virtualGoodsPassword'] = $chars[rand(0, 25)] . $chars[rand(0, 25)] . str_replace('.', '',microtime(true));
                            } elseif (in_array($goodsVirtualInfo->getVirtualGoodsPasswordType(), [1, 3])) $updateVirtualGoods['virtualGoodsPassword'] = $goodsVirtualInfo->getVirtualGoodsPassword();

                            $updateVirtualGoods['virtualGoodsAccountType'] = $goodsVirtualInfo->getVirtualGoodsAccountType();
                            $updateVirtualGoods['virtualGoodsPasswordType']= $goodsVirtualInfo->getVirtualGoodsPasswordType();
                            if ($goodsVirtualInfo->getVirtualGoodsEndTime() > 0) $updateVirtualGoods['virtualGoodsEndTime'] = $goodsVirtualInfo->getVirtualGoodsEndTime();

                            $this->goodsVirtualManager->addVirtualGoods($updateVirtualGoods, $goodsVirtualInfo->getGoodsId());
                        } else {
                            if ($i == 0) {
                                $virtualGoodsNum = $this->entityManager->getRepository(GoodsVirtual::class)->count(['goodsId' => $orderVirtualGoods->getGoodsId(), 'virtualGoodsState' => 1]);
                                if ($virtualGoodsNum < $sendVirtualNum) {//当第一次执行，发现虚拟可用的虚拟商品数量，不足以发货时，跳出处理
                                    $virtualGoodsStockFew[] = $orderVirtualGoods->getGoodsId();
                                    break;//跳出for循环，继续执行foreach循环
                                }
                            }
                            $this->goodsVirtualManager->editVirtualGoods($updateVirtualGoods, $goodsVirtualInfo);
                        }
                    } else {
                        $virtualGoodsStockFew[] = $orderVirtualGoods->getGoodsId();
                        break;//跳出for循环，继续执行foreach循环
                    }
                }
                //对正常发货的虚拟商品进行单独发货时间处理
                if (empty($virtualGoodsStockFew) || ($virtualGoodsStockFew && !in_array($orderVirtualGoods->getGoodsId(), $virtualGoodsStockFew))) {
                    $this->orderGoodsManager->editOrderGoods(['goodsStatus' => $event->getTarget()->salesPlugin()->getOrderStatusCode('GOODS_SHIPPED'), 'expressTime' => time()], $orderVirtualGoods);
                }
            }

            //如果订单中没有实物商品，则修改订单发货状态
            $orderGoodsInfo = $this->entityManager->getRepository(OrderGoods::class)->findOneBy(['orderId' => $orderInfo->getOrderId(), 'userId' => $orderInfo->getUserId(), 'goodsType' => 1]);
            if ($orderGoodsInfo == null) {
                if (empty($virtualGoodsStockFew)) $this->orderManager->editOrder(['orderStatus' => $event->getTarget()->salesPlugin()->getOrderStatusCode('GOODS_SHIPPED'), 'deliveryMode' => 1, 'expressTime' => time()], $orderInfo);
            }
        }
    }
}