<?php
/**
 * 易优CMS
 * ============================================================================
 * 版权所有 2016-2028 海南赞赞网络科技有限公司，并保留所有权利。
 * 网站地址: http://www.eyoucms.com
 * ----------------------------------------------------------------------------
 * 如果商业用途务必到官方购买正版授权, 以免引起不必要的法律纠纷.
 * ============================================================================
 * Author: 小虎哥 <1105415366@qq.com>
 * Date: 2018-4-3
 */

namespace app\plugins\model;

use think\Db;
use think\Page;
use think\Cache;

/**
 * 积分商品模型
 */

load_trait('controller/Jump');
class PointsGoods extends PointsShopBase
{
    use \traits\controller\Jump;

    private $times = 0;
    private $param = [];
    private $users = [];
    private $users_id = 0;

    // 构造函数
    public function __construct($param = [], $users = [])
    {
        // 统一接收参数处理
        $this->times = getTime();
        $this->param = !empty($param) ? $param : [];
        $this->users = !empty($users) ? $users : [];
        $this->users_id = !empty($this->users['users_id']) ? intval($this->users['users_id']) : 0;
        // 系统商品表
        $this->archives_db = Db::name('archives');
        // 积分商品表
        $this->points_goods_db = Db::name('weapp_points_goods');
        // 系统商品规格价格表
        $this->product_spec_value_db = Db::name('product_spec_value');
        // 积分商品规格价格表
        $this->points_goods_spec_db = Db::name('weapp_points_goods_spec');
    }

    // 查询积分商品ID
    public function getPointsShopGoodsID($aid = 0)
    {
        $where = [
            'goods_save' => 1,
            'goods_status' => 1,
            'aid' => intval($aid),
        ];
        $goodsID = $this->points_goods_db->where($where)->getField('goods_id');
        return !empty($goodsID) ? intval($goodsID) : false;
    }

    // 获取积分商城商品列表
    public function getPointsGoodsList()
    {
        // 积分商品查询
        $where = [
            'b.aid' => ['>', 0],
            'a.goods_save' => 1,
            'a.goods_status' => 1
        ];
        $field = 'a.*, b.title, b.litpic, b.users_price, b.sales_num, b.virtual_sales, b.sales_all, b.prom_type';
        $pagesize = config('paginate.list_rows') ? config('paginate.list_rows') : 15;
        if ('h5' == $this->param['terminal']) {
            // 分页查询
            $count = $this->points_goods_db->alias('a')->where($where)->join('__ARCHIVES__ b', 'a.aid = b.aid', 'LEFT')->count('goods_id');
            $Page = new Page($count, $pagesize);
            // 积分商品查询
            $limit = $Page->firstRow.','.$Page->listRows;
            $field = 'a.*, b.title, b.litpic, b.prom_type';
            $result['data'] = $this->points_goods_db->alias('a')->field($field)->join('__ARCHIVES__ b', 'a.aid = b.aid', 'LEFT')->where($where)->limit($limit)->order('add_time desc, goods_id desc')->select();
            $result['pageStr'] = $Page->show();
        } else {
            $result = $this->points_goods_db->alias('a')->field($field)->join('__ARCHIVES__ b', 'a.aid = b.aid', 'LEFT')->where($where)->paginate($pagesize, false, ['query' => request()->param()]);
            !empty($result) && $result = $result->toArray();
        }

        // 积分商品规格查询
        $where = [
            'goods_id' => ['IN', get_arr_column($result['data'], 'goods_id')],
        ];
        $pointsGoodsSpec = $this->points_goods_spec_db->where($where)->order('spec_points asc')->select();
        $pointsGoodsSpec = !empty($pointsGoodsSpec) ? group_same_key($pointsGoodsSpec, 'goods_id') : [];

        // 处理积分商品数据
        foreach ($result['data'] as $key => $value) {
            $value['litpic'] = handle_subdir_pic($value['litpic'], 'img', true);
            // 积分商品是多规格则执行
            if (!empty($value['goods_spec']) && !empty($pointsGoodsSpec[$value['goods_id']])) {
                $goodsSpecValue = $pointsGoodsSpec[$value['goods_id']];
                $currentPrice = current($goodsSpecValue);
                $endPrice = end($goodsSpecValue);
                $value['goods_price'] = $currentPrice['spec_price'];
                $value['goods_points'] = $currentPrice['spec_points'];
                $value['goods_stock'] = array_sum(get_arr_column($goodsSpecValue, 'spec_stock'));
            }
            $value['arcurl'] = url('plugins/PointsShop/goods_details', ['aid'=>$value['aid'], 'goods_id'=>$value['goods_id']]);
            $result['data'][$key] = $value;
        }

        // 返回数据
        return $result;
    }

    // 获取积分商城商品详情
    public function getPointsGoodsDetails()
    {
        // 积分商品查询
        $where = [
            'a.goods_save' => 1,
            'a.goods_status' => 1,
            'b.arcrank' => ['EGT', 0],
            'a.aid' => intval($this->param['aid']),
            'a.goods_id' => intval($this->param['goods_id']),
        ];
        $field = 'a.*, b.channel, b.title, b.litpic, b.users_price, b.sales_num, b.virtual_sales, b.sales_all, b.arcrank, b.prom_type, b.attrlist_id';
        $pointsGoods = $this->points_goods_db->alias('a')->field($field)->join('__ARCHIVES__ b', 'a.aid = b.aid', 'LEFT')->where($where)->find();
        if (empty($pointsGoods)) $this->error('商品不存在或已下架');
        $pointsGoods['spec_id'] = 0;
        $pointsGoods['litpic'] = $this->getDefaultPic($pointsGoods['litpic']);

        // 查询系统商品详情
        $where = [
            'aid' => intval($this->param['aid']),
        ];
        $goodsContent = Db::name('product_content')->field('content, content_ey_m')->where($where)->find();
        $pointsGoods['content'] = !empty($goodsContent['content_ey_m']) ? htmlspecialchars_decode($goodsContent['content_ey_m']) : htmlspecialchars_decode($goodsContent['content']);
        $pointsGoods['content'] = $this->handleGoodsContentPic($pointsGoods['content'], true);

        // 查询系统商品参数
        $pointsGoods['attr_list'] = $this->getSystemGoodsAttr($pointsGoods['aid'], $pointsGoods['attrlist_id']);

        // 查询系统商品自定义字段
        $pointsGoods['customField'] = $this->getSystemCustomField($pointsGoods['aid'], $pointsGoods['channel']);

        // 商品规格查询处理
        $allGoodsSpec = $allGoodsSpecValue = $defaultGoodsSpec = [];
        if (1 === intval($pointsGoods['goods_spec'])) {
            $where = [
                'aid'  => intval($this->param['aid']),
                'spec_is_select' => 1,
            ];
            $order = 'spec_value_id asc, spec_id asc';
            $field = '*, false checked';
            $productSpecData = Db::name('product_spec_data')->field($field)->where($where)->order($order)->select();
            foreach ($productSpecData as $key => $value) {
                $productSpecData[$key]['spec_image'] = !empty($value['spec_image']) ? get_default_pic($value['spec_image'], true) : '';
            }
            if (!empty($productSpecData)) {
                $productSpecData = group_same_key($productSpecData, 'spec_mark_id');
                foreach ($productSpecData as $key => $value) {
                    $allGoodsSpec[] = [
                        'spec_value_id' => $value[0]['spec_value_id'],
                        'spec_mark_id'  => $value[0]['spec_mark_id'],
                        'spec_name'     => $value[0]['spec_name'],
                        'findGoodsSpec' => $value,
                    ];
                }

                unset($where['spec_is_select']);
                $allGoodsSpecValue = $this->points_goods_spec_db->where($where)->order('spec_points asc, spec_price asc')->select();
                foreach ($allGoodsSpecValue as $key => $value) {
                    $value['spec_points'] = intval($value['spec_points']);
                    $value['spec_price'] = unifyPriceHandle($value['spec_price']);
                    $allGoodsSpecValue[$key] = $value;
                }
                if (!empty($allGoodsSpecValue)) {
                    // 默认选中的规格值，取价格最低者
                    $defaultGoodsSpec['spec_id'] = intval($allGoodsSpecValue[0]['spec_id']);
                    $defaultGoodsSpec['spec_keys'] = explode('_', $allGoodsSpecValue[0]['spec_keys']);
                    $defaultGoodsSpec['goods_price'] = unifyPriceHandle($allGoodsSpecValue[0]['spec_price']);
                    $defaultGoodsSpec['goods_points'] = intval($allGoodsSpecValue[0]['spec_points']);
                    $defaultGoodsSpec['goods_stock'] = intval($allGoodsSpecValue[0]['spec_stock']);
                }

                if (!empty($defaultGoodsSpec)) {
                    foreach ($allGoodsSpec as $key => $value) {
                        foreach ($value['findGoodsSpec'] as $key_1 => $value_1) {
                            if (in_array($value_1['spec_value_id'], $defaultGoodsSpec['spec_keys'])) {
                                $allGoodsSpec[$key]['findGoodsSpec'][$key_1]['checked'] = true;
                            }
                        }
                    }
                }
            }
        } else {
            // 默认选中的规格值，取价格最低者
            $defaultGoodsSpec['spec_id'] = 0;
            $defaultGoodsSpec['spec_keys'] = '';
            $defaultGoodsSpec['goods_price'] = unifyPriceHandle($pointsGoods['goods_price']);
            $defaultGoodsSpec['goods_points'] = intval($pointsGoods['goods_points']);
            $defaultGoodsSpec['goods_stock'] = intval($pointsGoods['goods_stock']);
        }

        // 返回数据
        $result = [
            'pointsGoods' => $pointsGoods,
            'allGoodsSpec' => $allGoodsSpec,
            'allGoodsSpecValue' => $allGoodsSpecValue,
            'defaultGoodsSpec' => $defaultGoodsSpec,
            'imageList' => $this->getGoodsImgImageList($pointsGoods['litpic'], $this->param['aid'], $this->param['terminal']),
        ];
        return $result;
    }

    // 系统商品和积分商品库存是否充足
    public function detectPointsGoodsStock()
    {
        // 基础判断
        if (empty($this->param['aid']) && empty($this->param['goods_id'])) $this->error('请选择购买商品');
        if (empty($this->param['goodsBuyNumber']) || 0 > intval($this->param['goodsBuyNumber'])) $this->error('请输入购买数量');

        // 系统商品多规格库存判断
        if (!empty($this->param['spec_keys'])) {
            $where  = [
                'aid' => $this->param['aid'],
                'spec_value_id' => $this->param['spec_keys']
            ];
            $specStock = $this->product_spec_value_db->where($where)->getField('spec_stock');
            if (empty($specStock)) $this->error('系统商品此规格已售罄');
            if (intval($specStock) < intval($this->param['goodsBuyNumber'])) $this->error('系统商品此规格最大库存' . $specStock);
        }
        // 系统商品单规格库存判断
        else {
            $where = [
                'aid' => $this->param['aid'],
            ];
            $stockCount = $this->archives_db->where($where)->getField('stock_count');
            if (empty($stockCount)) $this->error('系统商品已售罄');
            if (intval($stockCount) < intval($this->param['goodsBuyNumber'])) $this->error('系统商品最大库存' . $stockCount);
        }

        // 积分商品多规格库存判断
        if (!empty($this->param['spec_id']) && !empty($this->param['spec_keys'])) {
            $where  = [
                'aid'       => $this->param['aid'],
                'spec_id'   => $this->param['spec_id'],
                'goods_id'  => $this->param['goods_id'],
                'spec_keys' => $this->param['spec_keys']
            ];
            $specStock = $this->points_goods_spec_db->where($where)->getField('spec_stock');
            if (empty($specStock)) $this->error('积分商品此规格已售罄');
            if (intval($specStock) < intval($this->param['goodsBuyNumber'])) $this->error('积分商品此规格最大库存' . $specStock);
        }
        // 积分商品单规格库存判断
        else {
            $where = [
                'aid'      => $this->param['aid'],
                'goods_id' => $this->param['goods_id'],
            ];
            $goodsStock = $this->points_goods_db->where($where)->getField('goods_stock');
            if (empty($goodsStock)) $this->error('积分商品已售罄');
            if (intval($goodsStock) < intval($this->param['goodsBuyNumber'])) $this->error('积分商品最大库存' . $goodsStock);
        }
    }

    // 系统商品和积分商品状态是否上架
    public function detectPointsGoodsStatus()
    {
        // 基础判断
        if (empty($this->param['aid']) && empty($this->param['goods_id'])) $this->error('请选择购买商品');

        // 系统商品是否下架判断
        $where = [
            'arcrank' => ['EGT', 0],
            'aid' => $this->param['aid'],
        ];
        $count = $this->archives_db->where($where)->count();
        if (empty($count)) $this->error('系统商品已下架');

        // 积分商品是否下架判断
        $where = [
            'goods_status' => 1,
            'aid' => $this->param['aid'],
            'goods_id' => $this->param['goods_id'],
        ];
        $count = $this->points_goods_db->where($where)->count();
        if (empty($count)) $this->error('积分商品已下架');
    }

    // 积分商品立即购买处理
    public function nowBuyPointsGoods()
    {
        // 查询系统商品
        $where = [
            'arcrank' => ['>=', 0],
            'aid' => $this->param['aid']
        ];
        $count = Db::name('archives')->where($where)->count();
        // 系统商品存在
        if (!empty($count)) {
            // 拼装返回的URL
            $cacheData = [
                'spec_id' => 0,
                'spec_keys' => '',
                'aid' => intval($this->param['aid']),
                'users_id' => intval($this->users_id),
                'goods_id' => intval($this->param['goods_id']),
                'goodsBuyNumber' => intval($this->param['goodsBuyNumber']),
            ];
            // 存在规格则执行
            if (!empty($this->param['spec_id']) && !empty($this->param['spec_keys'])) {
                $cacheData['spec_id'] = intval($this->param['spec_id']);
                $cacheData['spec_keys'] = strval($this->param['spec_keys']);
            }
            // 先 json_encode 后 md5 加密信息
            $cacheKeys = md5(json_encode($cacheData));
            // 存入缓存，一天有效期
            Cache::set($cacheKeys, $cacheData, 86400);
            // 返回跳转链接
            if (1 == input('param.fenbao/d')) {
                $url = '?cacheKeys=' . $cacheKeys;
            } else {
                $url = '/pages/points_shop/pointsGoodsBuy?cacheKeys=' . $cacheKeys;
            }
            if ('h5' == $this->param['terminal']) $url = url('plugins/PointsShop/goods_buy_page', ['cacheKeys'=>$cacheKeys]);
            $this->success('数据正确', $url, ['url'=>$url]);
        } else {
            $this->error('商品不存在或已下架');
        }
    }

    // 查询提交的积分商品数据
    public function getBuyPointsGoods()
    {
        // 积分商品购买缓存数据
        $cacheData = Cache::get($this->param['cacheKeys']);
        // 基础判断
        if (empty($cacheData) || empty($cacheData['aid']) || empty($cacheData['goods_id'])) {
            if ('h5' == $this->param['terminal']) {
                $this->error('购买链接失效，请重新下单', url('user/Shop/shop_centre'));
            } else {
                $this->success('请求失败', null, ['errorMsg' => '购买链接失效，请重新下单', 'jumpPage' => '/pages/points_shop/index', 'loadShow' => 0]);
            }
        }

        // 商品查询
        $where = [
            'a.goods_save' => 1,
            'a.aid' => intval($cacheData['aid']),
            'a.goods_id' => intval($cacheData['goods_id']),
        ];
        $field = 'a.*, b.channel, b.title, b.litpic, b.arcrank, b.prom_type, b.attrlist_id, b.logistics_type';
        $pointsGoods = $this->points_goods_db->alias('a')->field($field)->join('__ARCHIVES__ b', 'a.aid = b.aid', 'LEFT')->where($where)->find();
        if (empty($pointsGoods)) $this->error('商品已停售');
        if (isset($pointsGoods['goods_status']) && 2 === intval($pointsGoods['goods_status'])) $this->error('商品已下架');
        // 商品封面图处理
        $pointsGoods['litpic'] = $this->getDefaultPic($pointsGoods['litpic']);
        // 商品价格
        $pointsGoods['goods_price'] = !empty($pointsGoods['goods_price']) ? unifyPriceHandle($pointsGoods['goods_price']) : 0;
        // 积分商城商品详情页
        $pointsGoods['arcurl'] = url('plugins/PointsShop/goods_details', ['aid'=>$pointsGoods['aid'], 'goods_id'=>$pointsGoods['goods_id']]);

        // 商品规格查询处理
        $pointsGoods['goodsSpecID'] = 0;
        $pointsGoods['goodsSpecKeys'] = $pointsGoods['goodsSpecNames'] = '';
        if (1 === intval($pointsGoods['goods_spec']) && !empty($cacheData['spec_id']) && !empty($cacheData['spec_keys'])) {
            // 查询系统规格值名称
            $where = [
                'spec_is_select' => 1,
                'aid' => intval($cacheData['aid']),
                'spec_value_id' => ['IN', explode('_', $cacheData['spec_keys'])]
            ];
            $productSpecData = Db::name('product_spec_data')->where($where)->order('spec_value_id asc')->column('spec_value');
            $pointsGoods['goodsSpecID'] = intval($cacheData['spec_id']);
            $pointsGoods['goodsSpecKeys'] = strval($cacheData['spec_keys']);
            $pointsGoods['goodsSpecNames'] = !empty($productSpecData) ? $productSpecData : [];
            // $pointsGoods['goodsSpecNames'] = !empty($productSpecData) ? implode('; ', $productSpecData) : '';

            // 查询积分商品规格购买信息
            $where = [
                'aid' => intval($cacheData['aid']),
                'spec_keys' => $cacheData['spec_keys'],
                'spec_id' => intval($cacheData['spec_id']),
                'goods_id' => intval($cacheData['goods_id']),
            ];
            $pointsGoodsSpec = $this->points_goods_spec_db->where($where)->find();
            if (!empty($pointsGoodsSpec)) {
                $pointsGoods['goods_stock'] = intval($pointsGoodsSpec['spec_stock']);
                $pointsGoods['goods_points'] = intval($pointsGoodsSpec['spec_points']);
                $pointsGoods['goods_price'] = unifyPriceHandle($pointsGoodsSpec['spec_price']);
            }
        }

        // 商品购买总信息
        $pointsGoods['goodsBuyNumber'] = !empty($cacheData['goodsBuyNumber']) ? intval($cacheData['goodsBuyNumber']) : 1;
        $pointsGoods['goodsSinglePrice'] = unifyPriceHandle($pointsGoods['goods_price'] * $pointsGoods['goodsBuyNumber']);
        $pointsGoods['goodsSinglePoints'] = intval($pointsGoods['goods_points']) * intval($pointsGoods['goodsBuyNumber']);
        $pointsGoods['goodsTotalPrice'] = $pointsGoods['goodsSinglePrice'];
        $pointsGoods['goodsTotalPoints'] = intval($pointsGoods['goodsSinglePoints']);

        // 商品物流支持
        $pointsGoods['onlyVerify'] = $pointsGoods['onlyDelivery'] = $pointsGoods['allLogisticsType'] = false;
        // 仅到店核销
        if ('2' === $pointsGoods['logistics_type']) $pointsGoods['onlyVerify'] = true;
        // 仅物流配送
        if ('1' === $pointsGoods['logistics_type']) $pointsGoods['onlyDelivery'] = true;
        // 物流配送 和 到店核销 都支持
        if ('1,2' === $pointsGoods['logistics_type']) $pointsGoods['allLogisticsType'] = true;

        return $pointsGoods;
    }

    // 下单购买的商品(系统商品and积分商品)库存(减少or增加)处理
    public function updatePointsGoodsStock($pointsGoods = [], $action = 'reduce')
    {
        // 减少库存
        if ('reduce' == $action) {
            $pointsGoods = [$pointsGoods];
        }
        // 增加库存
        else if ('increase' == $action) {
            foreach ($pointsGoods as $key => $value) {
                $pointsGoods[$key] = json_decode($value, true);
            }
        }
        // 处理库存
        $update_1 = $update_2 = $update_3 = $update_4 = [];
        foreach ($pointsGoods as $key => $value) {
            // 系统商品总库存处理
            if ('reduce' == $action) {
                $update_1[] = [
                    'aid' => intval($value['aid']),
                    'stock_count' => Db::raw('stock_count-' . ($value['goodsBuyNumber'])),
                    'sales_num'   => Db::raw('sales_num+' . ($value['goodsBuyNumber'])),
                    // 'sales_all'   => Db::raw('sales_all+' . ($value['goodsBuyNumber'])),
                    'update_time' => $this->times,
                ];
            } else if ('increase' == $action) {
                $update_1[] = [
                    'aid' => intval($value['aid']),
                    'stock_count' => Db::raw('stock_count+' . ($value['goodsBuyNumber'])),
                    'sales_num'   => Db::raw('sales_num-' . ($value['goodsBuyNumber'])),
                    // 'sales_all'   => Db::raw('sales_all-' . ($value['goodsBuyNumber'])),
                    'update_time' => $this->times,
                ];
            }
            // 系统商品规格现有库存处理
            if (!empty($value['goodsSpecKeys'])) {
                $where  = [
                    'aid' => intval($value['aid']),
                    'spec_value_id' => strval($value['goodsSpecKeys'])
                ];
                $value_id = $this->product_spec_value_db->where($where)->getField('value_id');
                if ('reduce' == $action) {
                    $update_2[] = [
                        'value_id' => intval($value_id),
                        'spec_stock' => Db::raw('spec_stock-' . ($value['goodsBuyNumber'])),
                        'spec_sales_num' => Db::raw('spec_sales_num+' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                } else if ('increase' == $action) {
                    $update_2[] = [
                        'value_id' => intval($value_id),
                        'spec_stock' => Db::raw('spec_stock+' . ($value['goodsBuyNumber'])),
                        'spec_sales_num' => Db::raw('spec_sales_num-' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                }
            }

            // 积分商品规格现有库存处理
            if (!empty($value['goods_id']) && !empty($value['goodsSpecKeys'])) {
                $where  = [
                    'aid' => intval($value['aid']),
                    'goods_id' => intval($value['goods_id']),
                    'spec_keys' => strval($value['goodsSpecKeys'])
                ];
                $spec_id = $this->points_goods_spec_db->where($where)->getField('spec_id');
                if ('reduce' == $action) {
                    $update_3[] = [
                        'spec_id' => intval($spec_id),
                        'spec_stock' => Db::raw('spec_stock-' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                } else if ('increase' == $action) {
                    $update_3[] = [
                        'spec_id' => intval($spec_id),
                        'spec_stock' => Db::raw('spec_stock+' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                }
            }
            // 积分商品库存处理
            else {
                if ('reduce' == $action) {
                    $update_4[] = [
                        'goods_id' => intval($value['goods_id']),
                        'goods_stock' => Db::raw('goods_stock-' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                } else if ('increase' == $action) {
                    $update_4[] = [
                        'goods_id' => intval($value['goods_id']),
                        'goods_stock' => Db::raw('goods_stock+' . ($value['goodsBuyNumber'])),
                        'update_time' => $this->times,
                    ];
                }
            }
        }

        // 更新系统商品库存
        if (!empty($update_1)) {
            $archivesModel = new \app\user\model\Archives();
            $archivesModel->saveAll($update_1);
            $this->archives_db->where(['sales_num' => ['lt', 0]])->update(['sales_num' => 0, 'update_time' => $this->times]);
            // $this->archives_db->where(['sales_all' => ['lt', 0]])->update(['sales_all' => 0, 'update_time' => $this->times]);
        }

        // 更新系统商品规格现有库存
        if (!empty($update_2)) {
            $productSpecValueModel = new \app\user\model\ProductSpecValue();
            $productSpecValueModel->saveAll($update_2);
            $this->product_spec_value_db->where(['spec_sales_num' => ['lt', 0]])->update(['spec_sales_num' => 0, 'update_time' => $this->times]);
        }

        // 更新积分商品规格现有库存
        if (!empty($update_3)) {
            $pointsGoodsSpecModel = new \weapp\PointsShop\model\PointsGoodsSpec;
            $pointsGoodsSpecModel->saveAll($update_3);
        }

        // 更新积分商品库存
        if (!empty($update_4)) {
            $pointsGoodsModel = new \weapp\PointsShop\model\PointsGoods;
            $pointsGoodsModel->saveAll($update_4);
        }
    }
}