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

namespace Shop\View;

use Admin\Data\Common;
use Admin\Data\Config;
use Cms\Entity\CmsClass;
use Cms\Entity\SingleCms;
use Doctrine\ORM\EntityManager;
use Extend\Entity\Navigation;
use Goods\Entity\GoodsClass;
use Goods\Entity\GoodsInClass;
use Laminas\Config\Factory;
use Laminas\Math\Rand;
use Laminas\Mvc\I18n\Translator;
use Laminas\Session\Container;
use Laminas\View\Helper\AbstractHelper;
use PHPQRCode\QRcode;
use Sales\Entity\Order;
use User\Entity\Cart;
use User\Entity\UserGoodsFavorites;

class ShopHelper extends AbstractHelper
{
    private $translator;
    private $request;
    private $sessionUser;
    private $dbshopSession;
    private $routeMatch;
    private $entityManager;
    private $csrfValue = '';

    public function __construct(
        Translator  $translator,
        $request,
        $routeMatch,
        EntityManager   $entityManager
    )
    {
        $this->translator   = $translator;
        $this->request      = $request;
        $this->routeMatch   = $routeMatch;
        $this->entityManager= $entityManager;

        if($this->sessionUser == null) $this->sessionUser = new Container('dbshopUser');
        if($this->dbshopSession == null) $this->dbshopSession = new Container('dbshopSession');
    }

    /**
     * 检测会员是否登录
     * @return bool
     */
    public function checkUserLoginStatus()
    {
        return $this->sessionUser->offsetExists('user_id');
    }

    /**
     * 获取会员登录信息
     * @param $key
     * @return mixed|null
     */
    public function getUserLoginData($key)
    {
        return $this->sessionUser->offsetGet($key);
    }

    /**
     * 获取shop通用的 session 信息
     * @param $key
     * @return mixed|string|null
     */
    public function getDbshopSessionData($key)
    {
        return $this->dbshopSession->offsetExists($key) ? $this->dbshopSession->offsetGet($key) : '';
    }

    /**
     * 购物车商品数量
     * @return int
     */
    public function getShopCartGoodsNum()
    {
        return $this->entityManager->getRepository(Cart::class)->count(['buyNow' => 0, 'userId' => $this->sessionUser->offsetGet('user_id')]);
    }

    /**
     * 商品详情的上一页
     * @param $url
     * @return mixed|null
     */
    public function goodsPreviousPage($url)
    {
        $previousPage = $this->request->getServer()->get('HTTP_REFERER');
        if (!empty($previousPage) && stripos($previousPage, 'shop-goods') === false) $this->dbshopSession->offsetSet('goodsPreviousPage', $previousPage);

        return $this->dbshopSession->offsetExists('goodsPreviousPage') ? $this->dbshopSession->offsetGet('goodsPreviousPage') : $url;
    }

    /**
     * 获取导航信息
     * @param $type 1 顶部，2 中部，3 底部
     * @return array|object[]
     */
    public function shopNavigationMenu($type)
    {
        return $this->entityManager->getRepository(Navigation::class)->findBy(['navigationPlace' => $type], ['navigationSort' => 'ASC']);
    }

    /**
     * 获取手机验证码时间间隔
     * @return int
     */
    public function getPhoneCaptchaSecond()
    {
        return Config::PHONE_CAPTCHA_EXPIRED_SECOND;
    }

    /**
     * 订单状态
     * @param $orderStatus
     * @return mixed
     */
    public function getOrderStatus($orderStatus)
    {
        return Common::orderStatus($this->translator)[$orderStatus];
    }

    /**
     * 余额提现状态
     * @param $state
     * @return mixed
     */
    public function getWithdrawState($state)
    {
        return Common::withdrawState($this->translator)[$state];
    }

    /**
     * 订单状态编码
     * @param $statusStr
     * @return mixed
     */
    public function getOrderStatusCode($statusStr)
    {
        return Common::orderStatusCode($statusStr);
    }

    /**
     * 积分类型
     * @param $typeId
     * @return mixed
     */
    public function userIntegralType($typeId)
    {
        $integralType = Common::integralType($this->translator);

        return $integralType[$typeId];
    }

    /**
     * 订单支付类型名称
     * @param $typeCode
     * @return mixed
     */
    public function getPaymentTypeName($typeCode)
    {
        return Common::paymentTypeName($typeCode, $this->translator);
    }

    /**
     * 订单配送类型名称
     * @param $typeCode
     * @return mixed
     */
    public function getDeliveryTypeName($typeCode)
    {
        return Common::deliveryTypeName($typeCode, $this->translator);
    }

    /**
     * 订单配送轨迹状态
     * @return mixed|string[]|null
     */
    public function getDeliveryTrackState()
    {
        return Common::configValue('deliveryApiState', 'delivery');
    }

    /**
     * 加入订单后的价格无需转换，已经对应固定货币的价格信息（包括但不限于 订单、充值等）
     * @param $number
     * @param $symbol
     * @return string
     */
    public function orderCurrency($number, $symbol)
    {
        return $symbol . $number;
    }

    /**
     * 可兑换商品的消费积分数
     * @param $goodsPrice
     * @return float|int
     */
    public function getGoodsIntegral($goodsPrice)
    {
        if($this->checkUserLoginStatus() == null && Common::configValue('goods', 'config')['login_goods_price_show'] == 1) return $this->translator->translate('登录可见');

        return $goodsPrice * Common::configValue('integral_type_1', 'integral')['integralCurrencyCon'] * 100;
    }

    /**
     * 获取客户购物车数量
     * @return int
     */
    public function getUserCartCount()
    {
        if(!$this->sessionUser->offsetExists('user_id')) return 0;

        return $this->entityManager->getRepository(Cart::class)->count(['userId' => $this->sessionUser->offsetGet('user_id'), 'buyNow' =>0]);
    }

    /**
     * 获取商品收藏状态
     * @param $goodsId
     * @return bool|object|null
     */
    public function getGoodsFavoritesStatus($goodsId)
    {
        if(!$this->sessionUser->offsetExists('user_id')) return false;
        return $this->entityManager->getRepository(UserGoodsFavorites::class)->findOneBy(['goodsId' => $goodsId, 'userId' => $this->sessionUser->offsetGet('user_id')]);
    }

    /**
     * 客户设置
     * @param $name
     * @param $configFile
     * @return mixed|string[]|null
     */
    public function customer($name, $configFile)
    {
        return Common::configValue($name, $configFile);
    }

    /**
     * 获取商城系统中的配置信息
     * @param $name
     * @param string $type
     * @param string $configFile
     * @return mixed
     */
    public function shop($name, $type = 'base', $configFile = 'config')
    {
        return Common::configValue($type, $configFile)[$name];
    }

    /**
     * 获取商城的热门关键词
     * @return array
     */
    public function shopHotKeywords()
    {
        return array_filter(explode('|', Common::configValue('base', 'config')['shop_hot_keywords']));
    }

    /**
     * 前台货币
     * @return array|\Laminas\Config\Config|mixed
     */
    public function shopCurrency()
    {
        $currencyArray = Common::readConfigFile('currency');
        if($this->dbshopSession->offsetGet('currencyCode')) {
            $currencyArray['default'] = Common::configValue($this->dbshopSession->offsetGet('currencyCode'), 'currency');
        }

        return $currencyArray;
    }

    /**
     * 会员名称中间用星号代替
     * @param $userName
     * @return string
     */
    public function userNameHide($userName)
    {
        return Common::stringHide($userName);
    }

    /**
     * 有货显示
     * @param $stockShow
     * @return mixed
     */
    public function goodsStockShow($stockShow)
    {
        return Common::goodsStockShow($this->translator)[$stockShow];
    }

    /**
     * 缺货显示
     * @param $outStockShow
     * @return mixed
     */
    public function goodsOutStockShow($outStockShow)
    {
        return Common::goodsOutStockShow($this->translator)[$outStockShow];
    }

    /**
     * 广告图片路径
     * @param $adFile
     * @return mixed
     */
    public function baseAdImagePath($adFile)
    {
        return substr($adFile,0, 4) == 'http' ? $adFile : $this->getView()->basePath($adFile);
    }

    /**
     * css文件路径
     * @param $cssFile
     * @return mixed
     */
    public function baseCssPath($cssFile)
    {
        return substr($cssFile,0, 4) == 'http' ? $cssFile : $this->getView()->basePath($cssFile);
    }

    /**
     * js文件路径
     * @param $jsFile
     * @return mixed
     */
    public function baseJsPath($jsFile)
    {
        return substr($jsFile,0, 4) == 'http' ? $jsFile : $this->getView()->basePath($jsFile);
    }

    /**
     * css 模板图片 路径
     * @param $imageFile
     * @return mixed
     */
    public function baseImagePath($imageFile)
    {
        return substr($imageFile,0, 4) == 'http' ? $imageFile : $this->getView()->basePath($imageFile);
    }

    /**
     * 会员头像路径
     * @param $avatarFile
     * @return mixed
     */
    public function userAvatarImagePath($avatarFile)
    {
        if(empty($avatarFile)) return $this->getView()->basePath(Common::configValue('default_user_avatar', 'customer')) . '?v=' . time();
        return substr($avatarFile,0, 4) == 'http' ? $avatarFile : $this->getView()->basePath($avatarFile);
    }

    /**
     * 商品图片路径
     * @param $goodsImageFile
     * @param bool $urlStatus
     * @return string
     */
    public function baseGoodsImagePath($goodsImageFile, $urlStatus = false)
    {
        //如为空，则返回默认图片
        if(empty($goodsImageFile)) return ($urlStatus ? $this->getView()->url('shop', [], ['force_canonical' => true]) . Common::configValue('goods_image_default', 'upload') : $this->getView()->basePath(Common::configValue('goods_image_default', 'upload'))) . '?v=' . time();

        return substr($goodsImageFile,0, 4) == 'http' ? $goodsImageFile : ($urlStatus ? $this->getView()->url('shop', [], ['force_canonical' => true]) . $goodsImageFile : $this->getView()->basePath($goodsImageFile));
    }

    /**
     * 商品分类图片路径
     * @param $classImageFile
     * @return mixed
     */
    public function baseGoodsClassImagePath($classImageFile)
    {
        //如为空，则返回默认图片
        if(empty($classImageFile)) return $this->getView()->basePath(Common::configValue('class_image_default', 'upload')) . '?v=' . time();

        return substr($classImageFile,0, 4) == 'http' ? $classImageFile : $this->getView()->basePath($classImageFile);
    }

    /**
     * 商品品牌图片路径
     * @param $brandImageFile
     * @return mixed
     */
    public function baseGoodsBrandImagePath($brandImageFile)
    {
        //如为空，则返回默认图片
        if(empty($brandImageFile)) return $this->getView()->basePath(Common::configValue('brand_logo_default', 'upload')) . '?v=' . time();

        return substr($brandImageFile,0, 4) == 'http' ? $brandImageFile : $this->getView()->basePath($brandImageFile);
    }

    /**
     * 附件或文件路径
     * @param $file
     * @return mixed
     */
    public function baseFilePath($file)
    {
        return substr($file,0, 4) == 'http' ? $file : $this->getView()->basePath($file);
    }

    /**
     * 获取客服代码
     * @return string[]
     */
    public function getOnlineService()
    {
        $array = ['long' => '', 'online' => []];

        $onlineService = Common::readConfigFile('onlineService');
        if (empty($onlineService)) return $array;

        $controller = $this->getController();
        $action     = $this->getAction();

        $client = Common::isMobile() ? 'mobile' : 'pc';
        //珑客服
        if (
            isset($onlineService['onlineBody']['long']['range'])
            && !empty($onlineService['onlineBody']['long']['range'])
            && !empty($onlineService['onlineBody']['long']['content'])
            && in_array($controller.'-'.$action, $onlineService['onlineBody']['long']['range'])
            && (!empty($onlineService['longService']['client']) && in_array($client, $onlineService['longService']['client']))
        ) {
            $array['long'] = $onlineService['onlineBody']['long']['content'];
        }
        //在线客服
        if (
            isset($onlineService['onlineBody']['online'])
            && !empty($onlineService['onlineBody']['online'])
            && (!empty($onlineService['onlineServiceClient']) && in_array($client, $onlineService['onlineServiceClient']))
        ) foreach ($onlineService['onlineBody']['online'] as $onlineValue) {
            if (!empty($onlineValue['range']) && in_array($controller.'-'.$action, $onlineValue['range']) && !empty($onlineValue['content'])) {
                $array['online'][] = $onlineValue['content'];
            }
        }

        return $array;
    }

    /**
     * 获取Controller名称
     * @return bool|mixed
     */
    public function getController()
    {
        if($this->routeMatch == null) return false;

        $controller = $this->routeMatch->getParam('controller');
        $controller = explode('\\', $controller);
        return array_pop($controller);
    }

    /**
     * 获取Action名称
     * @return bool
     */
    public function getAction()
    {
        if($this->routeMatch == null) return false;

        return $this->routeMatch->getParam('action');
    }

    /**
     * 创建get操作的CSRF Token
     * @return mixed|string
     */
    public function getCsrfValue()
    {
        if(empty($this->csrfValue)) {
            $this->dbshopSession->offsetSet('shopQueryToken', md5(time() . Rand::getBytes(32) . 'shopQueryToken'));
            $this->csrfValue = $this->dbshopSession->offsetGet('shopQueryToken');
        }
        return $this->csrfValue;
    }

    /**
     * 返回分页url的Query字符串，去除page
     * @return bool|string
     */
    public function pagesQuery()
    {
        $queryStr = $this->request->getServer()->get('QUERY_STRING');
        if(!empty($queryStr)) {
            if(strpos($queryStr, 'page=') !== false) {
                $num = strpos($queryStr, '&');
                if($num) return substr($queryStr, $num);
                else return '';
            } else return '&'.$queryStr;
        }
        return $queryStr;
    }

    /**
     * 微信分享公众号信息
     * @param $shareUrl
     * @return array
     */
    public function getWxSignPackage($shareUrl)
    {
        return Common::getWxSignPackage($shareUrl);
    }

    /**
     * 通用有效时间计算
     * @param $startTime
     * @param $endTime
     * @return string
     */
    public function effectiveTime($startTime, $endTime)
    {
        $iStartTime  = $startTime > 0 ? $this->getView()->dateFormat($startTime, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, Config::SHOP_DATE_FORMAT) : '';
        $iEndTime    = $endTime > 0 ? $this->getView()->dateFormat($endTime, \IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, Config::SHOP_DATE_FORMAT) : '';
        if(empty($iStartTime) && empty($iEndTime)) {
            $startAndEndTime = $this->translator->translate('长期有效');
        } elseif (!empty($iEndTime) && time() > $endTime) {
            $startAndEndTime = '<span style="color: red;">'.$this->translator->translate('已经过期').'</span>';
        } else {
            $startAndEndTime = (empty($iStartTime) ? $this->translator->translate('无') : $iStartTime) . ' / ' . (empty($iEndTime) ? $this->translator->translate('无') : $iEndTime);
        }

        return $startAndEndTime;
    }

    /**
     * 获取指定数量的会员订单信息
     * @param int $num
     * @return mixed
     */
    public function shopOrderListNum($num = 10)
    {
        return $this->entityManager->getRepository(Order::class)->findBy(['userId' => $this->sessionUser->offsetGet('user_id')], ['orderId' => 'DESC'], $num);
    }

    /**
     * 商品分类的breadcrumbs
     * @param $code
     * @param $templateCode
     * @param $classInfo
     * @return array
     */
    public function shopGoodsClassBreadcrumbs($code, $templateCode, $classInfo)
    {
        $classList = $this->entityManager->getRepository(GoodsClass::class)->shopClassBreadcrumbs($classInfo);
        return ['classId' => $classInfo->getClassId(), 'classList' => $classList];
    }

    /**
     * 文章分类的breadcrumbs
     * @param $code
     * @param $templateCode
     * @param $classId
     * @return array
     */
    public function shopCmsClassBreadcrumbs($code, $templateCode, $classId)
    {
        $classInfo = $this->entityManager->getRepository(CmsClass::class)->findOneBy(['cmsClassId' => $classId, 'cmsClassState' => 1]);
        if ($classInfo == null) return [];

        $array = [];
        if ($classInfo->getCmsClassTopId() > 0) {
            $classTopInfo = $this->entityManager->getRepository(CmsClass::class)->findOneBy(['cmsClassId' => $classInfo->getCmsClassTopId(), 'cmsClassState' => 1]);
            if ($classTopInfo) $array[] = ['id' => $classTopInfo->getCmsClassId(), 'title' => $classTopInfo->getCmsClassName()];
        }
        $array[] = ['id' => $classInfo->getCmsClassId(), 'title' => $classInfo->getCmsClassName()];

        return ['classId' => $classId, 'classList' => $array];
    }

    /**
     * 商品分类推荐商品列表
     * @param $code
     * @param $templateCode
     * @param $classId
     * @return array
     */
    public function shopClassRecommendGoods($code, $templateCode, $classId)
    {
        $recommendGoods = $this->entityManager->getRepository(GoodsInClass::class)->shopFindClassRecommendGoods($classId);
        return ['classId' => $classId, 'recommendGoods' => $recommendGoods];
    }

    /**
     * 前台单页文章调用（多个调用）
     * @param $singleTag
     * @param $templateCode
     * @return array
     */
    public function shopMoreSingleCms($singleTag, $templateCode)
    {
        $singleCmsArray = [];
        $singleCmsList  = $this->entityManager->getRepository(SingleCms::class)->findBy(['singleTag' => $singleTag, 'templateCode' => $templateCode], ['singleCmsSort' => 'ASC']);
        if($singleCmsList == null) return $singleCmsArray;

        foreach ($singleCmsList as $item) {
            $singleCmsArray[] = [
                'id'    => $item->getSingleCmsId(),
                'title' => $item->getSingleCmsTitle(),
                'body'  => $item->getSingleCmsBody()
            ];
        }

        return $singleCmsArray;
    }

    /**
     * 前台单页文章调用（单个调用）
     * @param $singleTag
     * @param $templateCode
     * @return array
     */
    public function shopSingleCms($singleTag, $templateCode)
    {
        $singleCmsInfo = $this->entityManager->getRepository(SingleCms::class)->findOneBy(['singleTag' => $singleTag, 'templateCode' => $templateCode]);
        if($singleCmsInfo == null) return [];

        return [
            'id'    => $singleCmsInfo->getSingleCmsId(),
            'title' => $singleCmsInfo->getSingleCmsTitle(),
            'body'  => $singleCmsInfo->getSingleCmsBody()
        ];
    }

    /**
     * 获取两级的商品分类
     * @return array
     */
    public function secGoodsClass()
    {
        //商品分类
        $goodsClass = $this->entityManager->getRepository(GoodsClass::class)->findBy(['classState' => 1], ['classTopId' => 'ASC', 'classSort' => 'ASC']);
        $classList  = Common::classOptions($goodsClass, 0, 'getClassTopId', 'getClassId', 2);

        $classArray     = [];
        $subClassArray  = [];
        if($classList) foreach ($classList as $classValue) {
            if($classValue->getClassTopId() == 0) $classArray[] = $classValue;
            else $subClassArray[$classValue->getClassTopId()][] = $classValue;
        }

        return ['classArray' => $classArray, 'subClassArray' => $subClassArray];
    }

    /**
     * 获取下级商品分类
     * @param $classTopId
     * @return array|GoodsClass[]|object[]
     */
    public function goodsSubClass($classTopId)
    {
        return $this->entityManager->getRepository(GoodsClass::class)->findBy(['classState' => 1, 'classTopId' => $classTopId], ['classSort' => 'ASC']);
    }

    /**
     * 获取指定位置的区域内容调用
     * @param $location
     * @param int $key
     * @param int $id
     * @return array
     */
    public function helperPartial($location, $key = 0, $id = 0)
    {
        $partial = [];
        $shopDefaultTemplate    = Common::getShopDefaultTemplate();
        $shopDefaultTemplateCode= str_replace('/', '-', $shopDefaultTemplate);
        $config = Factory::fromFile('module/Shop/view/'.$shopDefaultTemplate.'/shop/templatePartial.ini');
        if(isset($config[$location])) {
            if ($key > 0 && $id && isset($config[$location][$key])) {//指定获取带id的信息
                $partial['partialFile'] = $config[$location][$key]['partial'];
                if (isset($config[$location][$key]['functionArg'])) {
                    $partial['partialArg'] = $config[$location][$key]['functionArg'];
                    $partial['partialArg'][$config[$location][$key]['partialBody']] = $this->{$config[$location][$key]['functionName']}($config[$location][$key]['code'], $shopDefaultTemplateCode, $id);
                } else $partial['partialArg'] = [$config[$location][$key]['partialBody'] => $this->{$config[$location][$key]['functionName']}($config[$location][$key]['code'], $shopDefaultTemplateCode, $id)];
            } else {//通用调用
                foreach ($config[$location] as $key => $value) {
                    $partial[$key]['partialFile'] = $value['partial'];
                    if(isset($value['functionArg'])) {
                        $partial[$key]['partialArg'] = $value['functionArg'];
                        $partial[$key]['partialArg'][$value['partialBody']] = $this->{$value['functionName']}($value['code'], $shopDefaultTemplateCode);
                    } else $partial[$key]['partialArg'] = [$value['partialBody'] => $this->{$value['functionName']}($value['code'], $shopDefaultTemplateCode)];
                }
            }
        }

        return $partial;
    }

    /**
     * 生成二维码(商城，商品)
     * @param $text
     * @param $qrCodeType
     * @param $fileName
     * @param false $overwriteFile
     * @return string|string[]
     */
    public function helperCreateQrCodeFile($text, $qrCodeType, $fileName, $overwriteFile = false)
    {
        $filePathArray = [
            'shop' => Config::COMMON_IMAGE_PATH,
            'goods'=> Config::GOODS_QRCODE_IMAGE_PATH,
            ''
        ];
        if (!isset($filePathArray[$qrCodeType])) return '';

        //如果是商品的二维码，那么判断是否登录，登录则生成会员专用二维码
        if ($qrCodeType == 'goods' && $this->checkUserLoginStatus()) $invitationQrCodeFile = $filePathArray[$qrCodeType] . $this->sessionUser->offsetGet('user_id'). '_' . basename($fileName) . '.png';
        else $invitationQrCodeFile = $filePathArray[$qrCodeType] . basename($fileName) . '.png';

        if(!file_exists($invitationQrCodeFile)) QRcode::png($text, $invitationQrCodeFile, 0, 6, 1);
        else {
            if(!$overwriteFile) return str_replace(Config::PUBLIC_PATH, '', $invitationQrCodeFile).'?v='.time();
            else QRcode::png($text, $invitationQrCodeFile, 0, 6, 1);
        }
        return str_replace(Config::PUBLIC_PATH, '', $invitationQrCodeFile).'?v='.time();
    }
}