<?php


namespace JinDouYun\Model\Market;


use JinDouYun\Dao\Market\DComBinLog;
use JinDouYun\Dao\Market\DComBinPackage;
use JinDouYun\Model\Goods\MGoods;
use JinDouYun\Model\MBaseModel;
use JinDouYun\Model\System\MBasicSetup;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Core\StatusCode;

/**
 * @copyright   Copyright (c) https://www.qianniaovip.com All rights reserved
 * Description:
 * Class MComBinPackage
 * @package JinDouYun\Model\Market
 */
class MComBinPackage extends MBaseModel
{
    /**
     * @var DComBinPackage
     */
    private $objDComBinPackage;

    /**
     * @var
     */
    private $onlineEnterpriseId;

    /**
     * @var
     */
    private $onlineUserId;

    /**
     * @var int 预售状态
     */
    private $preSale;

    /**
     * @var DComBinLog
     */
    private $objDComBinLog;

    /**
     * MComBinPackage constructor.
     * @param string $onlineEnterpriseId
     * @param string $onlineUserId
     * @throws \Exception
     */
    public function __construct($onlineEnterpriseId = '', $onlineUserId = '')
    {
        $this->onlineEnterpriseId = $onlineEnterpriseId;
        $this->onlineUserId = $onlineUserId;
        parent::__construct($onlineEnterpriseId, $onlineUserId);
        $this->objDComBinPackage = new DComBinPackage();
        $this->objDComBinLog = new DComBinLog();
        $this->objDComBinPackage->setTable('qianniao_combin_package_' . $this->onlineEnterpriseId);
        $this->objDComBinLog->setTable('qianniao_combin_user_log_'.$this->onlineEnterpriseId);
        self::getPreSale();
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2020/12/25
     * Time: 11:50 上午
     * @return ResultWrapper
     */
    public function getPreSale(): ResultWrapper
    {
        $objMBasicSetup = new MBasicSetup($this->onlineEnterpriseId);
        $setResult = $objMBasicSetup->getBasicField('preSale');
        $this->preSale = StatusCode::$delete;
        if (!$setResult->isSuccess()){
            return ResultWrapper::fail($setResult->getData(),$setResult->getErrorCode());
        }
        $set = (array)$setResult->getData();
        $this->preSale = getArrayItem($set,'preSale',StatusCode::$delete);
        if (empty($this->preSale)) $this->preSale = StatusCode::$delete;
        return ResultWrapper::success($set);
    }

    /**
     * Doc: (des="套餐添加")
     * User: XMing
     * Date: 2021/1/21
     * Time: 3:28 下午
     * @param array $params
     * @return ResultWrapper
     */
    public function add(array $params): ResultWrapper
    {
        $insert = self::buildPackageData($params);
        $insert['createTime'] = time();
        $insert['updateTime'] = time();
        $result = $this->objDComBinPackage->insert($insert);
        if ($result === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success($result);
    }

    /**
     * Doc: (des="套餐列表")
     * User: XMing
     * Date: 2021/1/21
     * Time: 5:18 下午
     * @param array $selectParams
     * @return ResultWrapper
     */
    public function getAll(array $selectParams): ResultWrapper
    {
        $buildSql = self::buildSqlBySelectParams($selectParams);
        $lists = $this->objDComBinPackage->query($buildSql['sql']);
        if ($lists === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        $count = $this->objDComBinPackage->query($buildSql['countSql']);
        if ($lists === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }

        $formatListsResult = self::formatLists($lists);
        if (!$formatListsResult->isSuccess()) {
            return ResultWrapper::fail($formatListsResult->getData(), $formatListsResult->getErrorCode());
        }
        $formatLists = $formatListsResult->getData();
        $ret = [
            'data'  => $formatLists,
            'total' => isset($count[0]['total']) ? $count[0]['total'] : 0,
        ];
        return ResultWrapper::success($ret);
    }

    /**
     * Doc: (des="格式化数据")
     * User: XMing
     * Date: 2021/1/21
     * Time: 5:46 下午
     * @param array $lists
     * @return ResultWrapper
     */
    private function formatLists(array $lists): ResultWrapper
    {
        if (empty($lists)) {
            return ResultWrapper::success([]);
        }
        foreach ($lists as &$list) {
            unset($list['goodsData']);
            $list['allowInventory'] = bcsub($list['inventory'], $list['saleNum'], 2);
        }
        return ResultWrapper::success($lists);
    }

    /**
     * Doc: (des="构建sql")
     * User: XMing
     * Date: 2021/1/21
     * Time: 5:40 下午
     * @param array $selectParams
     * @return string[]
     */
    protected function buildSqlBySelectParams(array $selectParams): array
    {

        $tableName = $this->objDComBinPackage->get_Table();
        $fields = ' * ';
        $countFiled = ' COUNT(id) as total ';
        $time = time();
        $where = '';
        if (isset($selectParams['enableStatus']) && !empty($selectParams['enableStatus'])) {
            $where .= ' AND `enableStatus` = ' . $selectParams['enableStatus'];
        }

        if (isset($selectParams['keyword']) && !empty($selectParams['keyword'])) {
            $keyword = '"%' . $selectParams['keyword'] . '%"';
            $where .= ' AND `title` LIKE ' . $keyword;
        }
        // 1 未开始 2进行中 3已结束
        if (isset($selectParams['state']) && !empty($selectParams['state'])) {
            switch ($selectParams['state']) {
                case 1:
                    $where .= ' AND `startTime` > ' . $time . ' AND `isExpire` = ' . StatusCode::$standard;
                    break;
                case 2:
                    $where .= ' AND ( (`startTime` <= ' . $time . ' AND `endTime` >= ' . $time.') OR `isExpire` = '.StatusCode::$delete.') ';
                    break;
                case 3:
                    $where .= ' AND `endTime` < ' . $time . ' AND `isExpire` = ' . StatusCode::$standard;
                    break;
            }
        }

        if (isset($selectParams['shopId']) && !empty($selectParams['shopId'])){
            $where .= ' AND `shopId` = '.$selectParams['shopId'];
        }

        if (isset($selectParams['goodsId']) && !empty($selectParams['goodsId'])){
            $where .= ' AND FIND_IN_SET('.$selectParams['goodsId'].',`goodsIds`)';
        }

        $countSql = 'SELECT ' . $countFiled . ' FROM ' . $tableName . ' WHERE deleteStatus = ' . StatusCode::$standard . $where;
        $where .= ' ORDER BY createTime DESC ';
        if (isset($selectParams['limit']) && empty($selectParams['limit'])) {
            $where .= ' LIMIT ' . $selectParams['offset'] . ',' . $selectParams['limit'];
        }
        $sql = 'SELECT ' . $fields . ' FROM ' . $tableName . ' WHERE deleteStatus = ' . StatusCode::$standard . $where;

        return [
            'sql'      => $sql,
            'countSql' => $countSql
        ];
    }


    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/21
     * Time: 3:30 下午
     * @param array $params
     * @return array
     */
    public function buildPackageData(array $params): array
    {
        return [
            "title"        => getArrayItem($params, 'title', ''),
            //varchar(30) DEFAULT '' COMMENT '活动名称',
            "isExpire"     => getArrayItem($params, 'isExpire', StatusCode::$delete),
            //tinyint(3) DEFAULT '4' COMMENT '是否具有时间限制 默认5 4不限时间 5限制时间',
            "startTime"    => getArrayItem($params, 'startTime', 0),
            //int(10) NOT NULL DEFAULT '0' COMMENT '活动开始时间',
            "endTime"      => getArrayItem($params, 'endTime', 0),
            //int(10) NOT NULL DEFAULT '0' COMMENT '活动结束时间',
            "shopId"       => getArrayItem($params, 'shopId', 0),
            //int(10) NOT NULL DEFAULT '0' COMMENT '商铺id',
            "shopName"     => getArrayItem($params, 'shopName', ''),
            //varchar(30) DEFAULT NULL COMMENT '商铺名称',
            "goodsData"    => getArrayItem($params, 'goodsData', null),
            //json DEFAULT NULL COMMENT '活动商品数据',
            "price"        => getArrayItem($params, 'price', 0),
            //decimal(10,2) DEFAULT '0.00' COMMENT '套餐价格',
            "originPrice"  => getArrayItem($params, 'originPrice', 0),
            //decimal(10,2) DEFAULT '0.00' COMMENT '套餐价格',
            "inventory"    => getArrayItem($params, 'inventory', 0),
            //decimal(10,2) DEFAULT NULL COMMENT '套餐设置库存',
            "isLimit"      => getArrayItem($params, 'isLimit', StatusCode::$delete),
            //tinyint(3) DEFAULT '4' COMMENT '是否开启每人限购 默认4 4不开启 5开启',
            "limitNum"     => getArrayItem($params, 'limitNum', 0),
            //decimal(10,2) DEFAULT '0.00' COMMENT '每人限制购买数量',
            "expressType"  => getArrayItem($params, 'expressType', StatusCode::$delete),
            //tinyint(3) DEFAULT '4' COMMENT '运费设置 默认4 4默认跟随商品 5包邮',
            "enableStatus" => getArrayItem($params, 'enableStatus', StatusCode::$delete),
            //tinyint(3) DEFAULT '4' COMMENT '是否启用 默认4 4禁用 5启用',
            "materielNum"  => getArrayItem($params, 'materielNum', 0),

            "goodsIds"     => getArrayItem($params,'goodsIds',''),

        ];
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/21
     * Time: 6:41 下午
     * @param int $id
     * @return ResultWrapper
     * @throws \Exception
     */
    public function get(int $id): ResultWrapper
    {
        $package = $this->objDComBinPackage->get($id);
        if ($package === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        if (empty($package)) {
            return ResultWrapper::fail('未获取到指定信息', ErrorCode::$paramError);
        }
        $formatResult = self::formatPackage($package);
        if (!$formatResult->isSuccess()) {
            return ResultWrapper::fail($formatResult->getData(), $formatResult->getErrorCode());
        }
        return ResultWrapper::success($formatResult->getData());
    }

    /**
     * Doc: (des="格式化套餐详情")
     * User: XMing
     * Date: 2021/1/21
     * Time: 6:47 下午
     * @param array $data
     * @return ResultWrapper
     * @throws \Exception
     */
    private function formatPackage(array $data): ResultWrapper
    {
        if (empty($data)) {
            return ResultWrapper::success([]);
        }
        $data['allowInventory'] = bcsub($data['inventory'], $data['saleNum'], 2);
        $goodsData = json_decode(getArrayItem($data, 'goodsData', []),true);
        if (empty($goodsData)) {
            return ResultWrapper::fail('产品数据为空', ErrorCode::$paramError);
        }
        //获取商品详情
        $goodsIds = [];
        foreach ($goodsData as $datum){
            if (!in_array($datum['goodsId'],$goodsIds)){
                $goodsIds[] = $datum['goodsId'];
            }
        }
        unset($datum);

        $objMGoods = new MGoods($this->onlineEnterpriseId,false,$this->onlineUserId);
        $materielResult = $objMGoods->getGoodsByGoodsIds($goodsIds,$data['shopId']);
        if (!$materielResult->isSuccess()){
            return ResultWrapper::fail($materielResult->getData(),$materielResult->getErrorCode());
        }
        $goodsMaps = $materielResult->getData();
        foreach ($goodsData as &$datum){
            $datum['invalid'] = StatusCode::$standard;
            $datum['invalidMsg'] = '';
            if (!isset($goodsMaps[$datum['goodsId']])){
                $datum['invalid'] = StatusCode::$delete;
                $datum['invalidMsg'] = '商品已删除';
                continue;
            }
            $row = $goodsMaps[$datum['goodsId']];
            if ($row['enableStatus'] == StatusCode::$delete){
                $datum['invalid'] = StatusCode::$delete;
                $datum['invalidMsg'] = '商品已下架';
                continue;
            }
            $datum['title'] = getArrayItem($row,'title','');
            $datum['images'] = getArrayItem($row,'images',[]);
            $datum['code'] = createCode(StatusCode::$code['goodsBasic']['prefix'], $row['materielId'], StatusCode::$code['goodsBasic']['length']);
        }
        unset($datum);
        $data['goodsData'] = $goodsData;
        return ResultWrapper::success($data);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/21
     * Time: 6:41 下午
     * @param int $id
     * @return ResultWrapper
     */
    public function enable(int $id): ResultWrapper
    {
        $package = $this->objDComBinPackage->get($id);
        if ($package === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        if (empty($package)) {
            return ResultWrapper::fail('未获取到指定信息', ErrorCode::$paramError);
        }
        $update = [
            'enableStatus' => $package['enableStatus'] == StatusCode::$standard ? StatusCode::$delete : StatusCode::$standard,
            'updateTime'   => time(),
        ];
        $result = $this->objDComBinPackage->update($update, $id);
        if ($result === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/22
     * Time: 10:13 上午
     * @param array $data
     * @param int $id
     * @return ResultWrapper
     */
    public function edit(array $data, int $id): ResultWrapper
    {
        $update = self::buildPackageData($data);
        $update['updateTime'] = time();
        $result = $this->objDComBinPackage->update($update, $id);
        if ($result === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success(true);
    }


    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/22
     * Time: 10:30 上午
     * @param array $params
     * @return ResultWrapper
     * @throws \Exception
     */
    public function lists(array $params): ResultWrapper
    {
        $params['state'] = 2;
        $params['enableStatus'] = StatusCode::$standard;
        $buildSql = self::buildSqlBySelectParams($params);
        $lists = $this->objDComBinPackage->query($buildSql['sql']);
        if ($lists === false){
            return ResultWrapper::fail($this->objDComBinPackage->error(),ErrorCode::$dberror);
        }
        $count = $this->objDComBinPackage->query($buildSql['countSql']);
        if ($count === false){
            return ResultWrapper::fail($this->objDComBinPackage->error(),ErrorCode::$dberror);
        }
        $formatListsResult = self::formatListsApi($lists);
        if (!$formatListsResult->isSuccess()){
            return ResultWrapper::fail($formatListsResult->getData(),$formatListsResult->getErrorCode());
        }
        $ret = [
            'data'  => $formatListsResult->getData(),
            'total' => isset($count[0]['total']) ? $count[0]['total'] : 0,
        ];
        return ResultWrapper::success($ret);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/22
     * Time: 10:43 上午
     * @param array $lists
     * @return ResultWrapper
     * @throws \Exception
     */
    private function formatListsApi(array $lists): ResultWrapper
    {
        if (empty($lists)){
            return ResultWrapper::success([]);
        }

        $objMGoods = new MGoods($this->onlineEnterpriseId,false,$this->onlineUserId);
        foreach ($lists as  &$list){
            $list['allowInventory'] = bcsub($list['inventory'], $list['saleNum'], 2);
            $goodsData = json_decode($list['goodsData'],true);
            $goodsIds = [];
            foreach ($goodsData as $datum){
                if (!in_array($datum['goodsId'],$goodsIds)){
                    $goodsIds[] = $datum['goodsId'];
                }
            }
            unset($datum);
            $materielResult = $objMGoods->getGoodsByGoodsIds($goodsIds,$list['shopId']);
            if (!$materielResult->isSuccess()){
                return ResultWrapper::fail($materielResult->getData(),$materielResult->getErrorCode());
            }
            $goodsMaps = $materielResult->getData();

            foreach ($goodsData as &$datum){
                $datum['invalid'] = StatusCode::$standard;
                $datum['invalidMsg'] = '';
                if (!isset($goodsMaps[$datum['goodsId']])){
                    $datum['invalid'] = StatusCode::$delete;
                    $datum['invalidMsg'] = '商品已删除';
                    continue;
                }
                $row = $goodsMaps[$datum['goodsId']];
                if ($row['enableStatus'] == StatusCode::$delete){
                    $datum['invalid'] = StatusCode::$delete;
                    $datum['invalidMsg'] = '商品已下架';
                    continue;
                }
                $datum['title'] = getArrayItem($row,'title','');
                $datum['images'] = getArrayItem($row,'images',[]);
                $datum['code'] = createCode(StatusCode::$code['goodsBasic']['prefix'], $datum['materielId'], StatusCode::$code['goodsBasic']['length']);
            }
            unset($datum);
            $list['goodsData'] = $goodsData;
        }
        return ResultWrapper::success($lists);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2021/1/22
     * Time: 1:00 下午
     * @param int $id
     * @return ResultWrapper
     * @throws \Exception
     */
    public function details(int $id): ResultWrapper
    {
        $package = $this->objDComBinPackage->get($id);
        if ($package === false) {
            return ResultWrapper::fail($this->objDComBinPackage->error(), ErrorCode::$dberror);
        }
        if (empty($package)) {
            return ResultWrapper::fail('未获取到指定信息', ErrorCode::$paramError);
        }
        $formatDetailsResult = self::formatDetails($package);
        if (!$formatDetailsResult->isSuccess()){
            return ResultWrapper::fail($formatDetailsResult->getData(),$formatDetailsResult->getErrorCode());
        }
        $formatDetails = $formatDetailsResult->getData();
        return ResultWrapper::success($formatDetails);
    }

    /**
     * Doc: (des="组合套餐详情")
     * User: XMing
     * Date: 2021/1/22
     * Time: 2:35 下午
     * @param array $data
     * @return ResultWrapper
     * @throws \Exception
     */
    public function formatDetails(array $data): ResultWrapper
    {
        if (empty($data)){
            return ResultWrapper::success($data);
        }
        $goodsData = json_decode($data['goodsData'],true);
        if (empty($goodsData)){
            return ResultWrapper::fail('组合套餐配置异常',ErrorCode::$paramError);
        }
        $data['invalid'] = StatusCode::$standard;//活动有效状态
        $data['invalidMsg'] = '';//状态说明
        $data['allowInventory'] = floatval(bcsub($data['inventory'], $data['saleNum'], 2));
        if ($data['allowInventory'] < 0){
            $data['invalid'] = StatusCode::$delete;
            $data['invalidMsg'] = '抢光了～';
        }

        if ($data['enableStatus'] == StatusCode::$delete){
            $data['invalid'] = StatusCode::$delete;
            $data['invalidMsg'] = '下架了～';
        }

        $objMGoods = new MGoods($this->onlineEnterpriseId,true,$this->onlineUserId);
        foreach ($goodsData as &$list){
            $list['invalid'] = StatusCode::$standard;
            $list['invalidMsg'] = '';
            //获取商品的详情
            $goodsResult = $objMGoods->getApiGoodsInfo($list['goodsId']);
            if (!$goodsResult->isSuccess()){
                return ResultWrapper::fail($goodsResult->getData(),$goodsResult->getErrorCode());
            }
            $goods = $goodsResult->getData();
            if (empty($goods)){
                $data['invalid'] = StatusCode::$delete;
                $data['invalidMsg'] = '产品删除了～';
                $list['invalid'] = StatusCode::$delete;
                $list['invalidMsg'] = '商品已删除';
                continue;
            }
            unset($goods['skuData']);
            if ($goods['enableStatus'] == StatusCode::$delete){
                $data['invalid'] = StatusCode::$delete;
                $data['invalidMsg'] = '产品下架了～';
                $list['invalid'] = StatusCode::$delete;
                $list['invalidMsg'] = '商品已下架';
                continue;
            }

            if ($this->preSale == StatusCode::$delete){
                //需要校验库存
                if(floatval($goods['inventorTotal']) < 0){
                    $data['invalid'] = StatusCode::$delete;
                    $data['invalidMsg'] = '产品售馨了～';
                    $list['invalid'] = StatusCode::$delete;
                    $list['invalidMsg'] = '商品已售馨';
                    continue;
                }
            }
            $list = array_merge($list,$goods);
        }
        unset($list);
        $data['goodsData'] = $goodsData;
        return ResultWrapper::success($data);
    }

    /**
     * Doc: (des="增加套餐购买数量")
     * User: XMing
     * Date: 2021/1/22
     * Time: 9:47 下午
     * @param int $id
     * @param  array $params
     * @param array $orderMap
     * @return ResultWrapper
     */
    public function incPackNum(int $id,array $params,array $orderMap): ResultWrapper
    {
        if (!isset($params['userCenterId'])){
            return ResultWrapper::fail('userCenterId参数错误',ErrorCode::$paramError);
        }
        $userId = $params['userCenterId'];
        $package = $this->objDComBinPackage->get($id);
        if ($package === false){
            return ResultWrapper::fail($this->objDComBinPackage->error(),ErrorCode::$dberror);
        }
        if (empty($package)){
            return ResultWrapper::fail('套餐已下架',ErrorCode::$paramError);
        }
        if ($package['isLimit'] == StatusCode::$standard){
            //开启了每人限制
            $limitNum = $package['limitNum'];
            $logNum = $this->objDComBinLog->count(['userCenterId' => $userId,'comBinId' => $id]);
            if ($logNum === false){
                return ResultWrapper::fail($this->objDComBinLog->error(),ErrorCode::$dberror);
            }
            if ($logNum >= $limitNum){
                return ResultWrapper::fail('你已经购买过此套餐了',ErrorCode::$paramError);
            }
        }
        $inventory = $package['inventory'];
        $oldSaleNum = $package['saleNum'];
        $oldSubOrderNum = $package['subOrderNum'];
        $oldSubOrderPayMoney = $package['subOrderPayMoney'];
        if ($oldSaleNum >= $inventory){
            return ResultWrapper::fail('套餐抢光了',ErrorCode::$paramError);
        }
        $update = [
            'saleNum' => bcadd($oldSaleNum,1,2),
            'subOrderNum' => bcadd($oldSubOrderNum,1,2),
            'subOrderPayMoney' => bcadd($oldSubOrderPayMoney,$package['price'])
        ];
        $incResult = $this->objDComBinPackage->update($update,$id);
        if ($incResult === false){
            return ResultWrapper::fail($this->objDComBinPackage->error(),ErrorCode::$dberror);
        }
        $log = [];
        foreach ($orderMap as $no => $orderId){
            $log = [
                'sourceId' => $orderId,
                'sourceNo' => $no,
                'comBinId' => $id,
                'customerId' => $params['id'],
                'customerName' => $params['name'],
                'userCenterId' => $params['userCenterId'],
                'buyNum' => 1,
                'createTime' => time(),
                'updateTime' => time()
            ];
        }
        if (!empty($log)){
            $result = $this->objDComBinLog->insert($log);
            if ($result === false){
                return ResultWrapper::fail($this->objDComBinLog->error(),ErrorCode::$dberror);
            }
        }
        return ResultWrapper::success(true);
    }
}