<?php

namespace DAO;


use Our\ApiConst;
use Our\Common;
use Our\CommonExtension;

class GoodsModel extends \DAO\AbstractModel {

    public $errorCode;

    /**
     * 表名
     *
     * @var string
     */
    protected $_tableName = 'han_goods';

    private $cartGoodsField = 'goods_id,goods_storage,store_id,goods_commonid,goods_name,goods_image,goods_spec,snapshot_id';

    public $goodsDetailField='goods_id as goodsId,goods_commonid as goodsCommonid,goods_commonid as goodsCommonId,goods_name as goodsName,store_id as storeId';

    /**
     * 主键
     *
     * @var string
     */
    protected $_primaryKey = 'goods_id';
    public function init(){
    }

    /**
     * 更新商品表商品库存
     * @param $goodsId 商品ID
     * @param $num 库存数量
     * @param $op 1增加 2设置
     * @return mixed
     */
    public function updateStorage($goodsId, $num, $op) {
        $this->setDb();
        $whereSql = 'goods_id='.$goodsId;
        if($op==1){ //调整库存
            $updateSql = 'goods_storage = goods_storage'.($num<0 ? '-'.(-$num) : '+'.$num);
        } else {    //调整库存预警为不需要预警
            $updateSql = 'goods_storage_alarm =0';
        }
        $updateSql=$updateSql.",goods_edittime=".TIMESTAMP;
        $updateAllSql = "UPDATE {$this->_tableName} set {$updateSql} where {$whereSql}";
        return $this->db->update($this->_tableName)->query($updateAllSql);
    }

    /**
     *
     * 分页获取商品列表
     * @param $where
     * @param $field
     * @param $pageIndex
     * @param $pageSize
     * @param array $order
     * @return array|mixed
     */
    public function getListPage($where, $field, $pageIndex, $pageSize, $order = array('goods_id' => 'asc'))
    {
        $this->setDb($this->dbName);
        if($datas = $this->lists($where, $order, $field, $pageIndex, $pageSize)) {
            foreach ($datas['list'] as $key=>$val) {
                $datas['list'][$key]['goodsAttr'] = $this->getFormatGoodsAttr($val['goodsAttr']);
            }
        }
        return $datas ? $datas : array();
    }

    public function getList($where,$field){
        $this->setDb();
        if(is_array($where)){
            $where=$this->db->getSqlWhereByArray($where);
        }
        $res= $this->db->select($field)->from($this->_tableName)->where($where)->order('goods_storage','desc')->fetchAll();
        return $res;

    }
    public function getListGroup($where,$field,$groupField){
        $this->setDb($this->dbName);
        if(is_array($where)){
            $where=$this->db->getSqlWhereByArray($where);
        }
        return $this->db->select($field)->from($this->_tableName)->where($where)->group($groupField)->fetchAll();
    }
//    public function getOneById($id){
//        $this->setDb();
//        return $this->db->select('goods_id,goods_commonid,goods_price,goods_marketprice,goods_image,goods_storage,goods_spec')->from($this->_tableName)->where(array('goods_id'=>$id))->fetchOne();
//    }

    public function find($where,$field = \Our\NameConst::allField){
        $this->setDb($this->dbName);
        $result = $this->db->select($field)->from($this->_tableName)->where($where)->fetchOne();
        return $result;
    }

    /**
     * 获取在线商品列表
     * @param $where
     * @param string $field
     * @return mixed
     */
    public function getOnlineList($where,$field = \Our\NameConst::allField){
        $whereSql = ' goods_state ='.\Our\ApiConst::onlineGoodsState.' and goods_verify='.\Our\ApiConst::onlineGoodsVerify.' and is_del='.\Our\ApiConst::onlineGoodsDel;
        if($where){
            $whereSql .= ' and '.$where;
        }
        return $this->getList($whereSql,$field);
    }

    public function getOnlineOne($goodsId,$field= \Our\NameConst::allField){
        $where['goods_state'] = \Our\ApiConst::onlineGoodsState;
        $where['goods_verify'] = \Our\ApiConst::onlineGoodsVerify;
        $where['is_del'] = \Our\ApiConst::onlineGoodsDel;
        $where['goods_id']  = $goodsId;
        $goods = \Our\RedisHelper::cachedFunction(\Redis\Db4\GoodsRedisModel::getInstance(),array(&$this, 'find'),array($where,$field),\Our\ApiConst::oneHour,array($goodsId));
        return $goods;
    }

    public function validAddCartGoods($where,$storageFlag = false){
        $goods = $this->getOnlineOne($where['goodsId'],$this->cartGoodsField);
        if(!$goods){
            $this->errorCode = \Error\CodeConfigModel::offlineGoodsOrNotExist;
            return false;
        }
        if($goods['goods_storage']<$where['goodsNum']&&$storageFlag){
            $this->errorCode = \Error\CodeConfigModel::noStorageForCart;
            return false;
        }
        return $goods;
    }

    public function validAddCartGoodsList($goodsIds,$storageFlag = false){
        $whereSql = \Our\Common::format(' goods_id in ({0})',implode(',',$goodsIds));
        $goodsList = $this->getOnlineList($whereSql,$this->cartGoodsField);
        if(!($goodsList&&count($goodsIds)==count($goodsList))){
            $this->errorCode = \Error\CodeConfigModel::offlineGoodsListOrNotExist;
            return false;
        }
        foreach($goodsList as $goods){
            if($goods['goods_storage']<\Our\ApiConst::one&&$storageFlag){
                $this->errorCode = \Error\CodeConfigModel::goodsListNoStorage;
                return false;
            }
        }
        return $goodsList;
    }



    public function validEditCartGoods($where,$cart,$storageFlag = true){
        $goods = $this->getOnlineOne($where['goodsId']);
        if($goods['goods_commonid'] != $cart['goods_commonid']){
            $this->errorCode = \Error\CodeConfigModel::wrongGoodsForEditGoods;
            return false;
        }
        if(!$goods){
            $this->errorCode = \Error\CodeConfigModel::offlineGoodsOrNotExist;
            return false;
        }
        if($goods['goods_storage']<$where['goodsNum']&&$storageFlag){
            $this->errorCode = \Error\CodeConfigModel::noStorageForCart;
            return false;
        }
        return $goods;
    }

    /**
     * 获取商品是否在售,如果在售还返回对应库存信息
     * @param $goodsId
     */
    public function getOnlineStorageGoods($goodsId){
        $goodsRedis = \Redis\Db4\GoodsRedisModel::getInstance();
        $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsId;
        $onlineStorageGoods = $goodsRedis->tableHGAll($onlineStorageGoodsKey);
        if($onlineStorageGoods){
            return $onlineStorageGoods;
        }else{
            $where['goods_state'] = \Our\ApiConst::onlineGoodsState;
            $where['goods_verify'] = \Our\ApiConst::onlineGoodsVerify;
            $where['is_del'] = \Our\ApiConst::onlineGoodsDel;
            $where['goods_id']  = $goodsId;
            $goods = $this->find($where,'goods_storage');
            if($goods){
                $data = array('onlineFlag'=>\Our\ApiConst::one,'goodsStorage'=>$goods['goods_storage']);
            }else{
                $data = array('onlineFlag'=>\Our\ApiConst::zero,'goodsStorage'=>$goods['goods_storage']);
            }
            $goodsRedis->tableHMGet($onlineStorageGoodsKey,$data,\Our\ApiConst::tenDaySecond);
            return $data;
        }
    }

    /**
     * 更新商品库存缓存以及更新销量
     * @param $goodsList 商品列表
     * @param int $op 删减标识符(1:增加,0:减少,2:直接设置)
     * @return bool
     */
    public function opOnlineStorageGoodsByGoodsCommonIds($goodsList,$op = \Our\ApiConst::minus,$updateSaleNumFalg = true){
        $goodsRedis = \Redis\Db4\GoodsRedisModel::getInstance();
        if($updateSaleNumFalg){
            $goodsCommonRedis = \Redis\Db4\GoodsCommonRedisModel::getInstance();
            $onlineGoodsCommonSaleNumKey = \Our\NameConst::onlineGoodsCommonSaleNumPrefix;
        }
        $goodsCommonList = $this->getOnlineStorageGoodsByGoodsCommonIds(array_keys($goodsList));
        foreach($goodsCommonList as $goodsCommonId=>$goodsCommonsTemp){
            $newGoodsList = array();
            $totalGoodsNum = \Our\ApiConst::zero;
            foreach($goodsCommonsTemp as $goodsId=>$temp){
                if($goodsList[$goodsCommonId][$goodsId]&&$goodsList[$goodsCommonId][$goodsId]['goodsNum']>\Our\ApiConst::zero){
                    if($op == \Our\ApiConst::minus&&$temp['goodsStorage']>=$goodsList[$goodsCommonId][$goodsId]['goodsNum']){
                        $temp['goodsStorage'] -= $goodsList[$goodsCommonId][$goodsId]['goodsNum'];
                    }else if($op == \Our\ApiConst::plus){
                        $temp['goodsStorage'] += $goodsList[$goodsCommonId][$goodsId]['goodsNum'];
                    }else if($op == \Our\ApiConst::set){
                        $temp['goodsStorage'] = $goodsList[$goodsCommonId][$goodsId]['goodsNum'];
                    }else{
                        return false;
                    }
                    $totalGoodsNum += $goodsList[$goodsCommonId][$goodsId]['goodsNum'];
                }
                $newGoodsList[$goodsId]= serialize($temp);
            }
            if($newGoodsList){
                $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsCommonId;
                $result = $goodsRedis->tableHMSet($onlineStorageGoodsKey,$newGoodsList,\Our\ApiConst::tenDaySecond);
                if(!$result){
                    return false;
                }

            }
            /**
             * 需要更新销量时 ,如果已经存在销量对应缓存,对销量对应缓存进行加减操作
             */
            if($updateSaleNumFalg&&$op!=\Our\ApiConst::set&&$totalGoodsNum>\Our\ApiConst::zero){
                $updateGoodsNum = $totalGoodsNum;
                if($op==\Our\ApiConst::plus){
                    $updateGoodsNum = -$updateGoodsNum;
                }

                if($goodsCommonRedis->tableHExists($onlineGoodsCommonSaleNumKey,$goodsCommonId)){
                    $oldSaleNum = $goodsCommonRedis->tableHGet($onlineGoodsCommonSaleNumKey,$goodsCommonId);
                    if($op==\Our\ApiConst::plus&&($oldSaleNum+$updateGoodsNum)<\Our\ApiConst::zero){
                        $updateGoodsNum = \Our\ApiConst::zero;
                        $goodsCommonRedis->tableHSet($onlineGoodsCommonSaleNumKey,$goodsCommonId,$updateGoodsNum);
                    }else{
                        $goodsCommonRedis->tableHIncrBy($onlineGoodsCommonSaleNumKey,$goodsCommonId,$updateGoodsNum);
                    }
                }
            }
            \DAO\PBundlingModel::getInstance()->deletePBundlingByGoodsCommonId($goodsCommonId);
        }
        return true;
    }



    /**
     * 根据商品CommonId获取库存信息
     * @param $goodsCommonIds
     * @return mixed
     */
    public function getOnlineStorageGoodsByGoodsCommonIds($goodsCommonIds,$fromCart= false){
        $goodsRedis = \Redis\Db4\GoodsRedisModel::getInstance();
        $noRedisGoodsCommonIds= array();
        foreach($goodsCommonIds as $goodsCommonId){
            $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsCommonId;
            $onlineStorageGoods = $goodsRedis->tableHGAll($onlineStorageGoodsKey);
            if($onlineStorageGoods){
                foreach($onlineStorageGoods as $key=>&$value){
                    $value = unserialize($value);
                }
                $returnData[$goodsCommonId] = $onlineStorageGoods;
            }else{
                $noRedisGoodsCommonIds[]= $goodsCommonId;
            }
        }
        if($fromCart){
            $sql = \Our\Common::format(' goods_commonid in ({0})',implode(',',$goodsCommonIds));
            $field = 'goods_commonid,goods_id,goods_storage,goods_state,goods_verify,is_transport,transport_id,gc_id,gc_id_1,gc_id_2,gc_id_3,snapshot_id,goods_image,goods_freight,goods_free,delivery_template_id,is_del';
        }else if($noRedisGoodsCommonIds){
            $sql = \Our\Common::format(' goods_commonid in ({0})',implode(',',$noRedisGoodsCommonIds));
            $field = 'goods_commonid,goods_id,goods_storage,goods_state,goods_verify,is_del';
        }
        if($sql&&$field){
            $goodsArray = $this->getList($sql,$field);
            $goodsCommonList = array();
            $goodsList = array();
            if($goodsArray){
                foreach($goodsArray as $goods){
                    $goodsCommonList[$goods['goods_commonid']][] = $goods['goods_id'];
                    $goodsList[$goods['goods_id']] = $goods;
                }
            }
            if($noRedisGoodsCommonIds){
                foreach($noRedisGoodsCommonIds as $goodsCommonId){
                    if(isset($goodsCommonList[$goodsCommonId])){
                        $goodsCommon = array();
                        $goodsArr = array();
                        foreach($goodsCommonList[$goodsCommonId] as $goodsId){
                            $goods = $goodsList[$goodsId];
                            $data = array('goodsStorage'=>$goods['goods_storage']);
                            if($goods['goods_state']==\Our\ApiConst::onlineGoodsState&&$goods['goods_verify']==\Our\ApiConst::onlineGoodsVerify&&$goods['is_del']==\Our\ApiConst::zero){
                                $data['onlineFlag'] = \Our\ApiConst::one;
                            }else{
                                $data['onlineFlag'] = \Our\ApiConst::zero;
                            }
                            $goodsArr[$goodsId] = serialize($data);
                            $goodsCommon[$goodsId] = $data;
                        }
                        $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsCommonId;
                        $result = $goodsRedis->tableHMSet($onlineStorageGoodsKey,$goodsArr,\Our\ApiConst::tenDaySecond);
                        $returnData[$goodsCommonId] = $goodsCommon;
                    }
                }
            }
            if($fromCart){
                foreach($goodsList as $temp){
                    if(isset($returnData[$temp['goods_commonid']]['is_transport'])){
                        continue;
                    }
                    $returnData[$temp['goods_commonid']]['delivery_template_id'] = $temp['delivery_template_id'];
                    $returnData[$temp['goods_commonid']]['is_transport'] = $temp['is_transport'];
                    $returnData[$temp['goods_commonid']]['transport_id'] = $temp['transport_id'];
                    $returnData[$temp['goods_commonid']]['goods_freight'] = $temp['goods_freight'];
                    $returnData[$temp['goods_commonid']]['goods_free'] = $temp['goods_free'];
                    $returnData[$temp['goods_commonid']]['gcId'] = $temp['gc_id_1'];
                    $returnData[$temp['goods_commonid']]['gc_id'] = $temp['gc_id'];
                    $returnData[$temp['goods_commonid']]['gc_id_2'] = $temp['gc_id_2'];
                    $returnData[$temp['goods_commonid']]['gc_id_3'] = $temp['gc_id_3'];
                    $returnData[$temp['goods_commonid']]['snapshot_id'] = (isset($temp['snapshot_id'])&&$temp['snapshot_id']>\Our\ApiConst::zero)?$temp['snapshot_id']:\Our\ApiConst::zero;
                }
            }
        }
        return $returnData;
    }

    public function getListAndSetStorage($goodsCommonId,$field){
        $goodsList = $this->getList(array('goods_commonid'=>$goodsCommonId),$field);
        if($goodsList && is_array($goodsList)){
            $data = [];
            $goodsRedis = \Redis\Db4\GoodsRedisModel::getInstance();
            $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsCommonId;
            $onlineStorageGoods = $goodsRedis->tableHGAll($onlineStorageGoodsKey);
            if(empty($onlineStorageGoods)){
                foreach ($goodsList as $key => $goods){
                    $onlineFlag = \Our\ApiConst::zero;
                    if($goods['goods_state'] == \Our\ApiConst::onlineGoodsState && $goods['goods_verify'] == \Our\ApiConst::onlineGoodsVerify && $goods['is_del'] == \Our\ApiConst::onlineGoodsDel){
                        $onlineFlag = \Our\ApiConst::one;
                    }
                    unset($goodsList[$key]['goods_state']);
                    unset($goodsList[$key]['goods_verify']);
                    unset($goodsList[$key]['is_del']);
                    $data[$goods['goods_id']] = serialize(array('onlineFlag'=>$onlineFlag,'goodsStorage'=>$goods['goods_storage']));
                }
                $goodsRedis->tableHMSet($onlineStorageGoodsKey,$data,\Our\ApiConst::tenDaySecond);
            }else{
                foreach ($goodsList as $key => $goods){
                    unset($goodsList[$key]['goods_state']);
                    unset($goodsList[$key]['goods_verify']);
                    unset($goodsList[$key]['is_del']);
                }
            }

        }
        return $goodsList;
    }

    /**
     * 更新库存
     * @param $dataList
     * @param int $op
     * @return bool
     */
    public function updateGoodsStorage($dataList,$op=\Our\ApiConst::zero){
        $datas = array_values($dataList);
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        $error = 0;
        $baseSql = "UPDATE {$this->_tableName} set  ";

        $updateAllSql = $baseSql;
        $goodsSql = ' goods_storage = case goods_id ';
        $goodsEdittimeSql = ' goods_edittime = case goods_id ';
        $dataIds = array();
        for ($i = 0; $i < count($datas); $i++) {
            $goodsSql .= \Our\Common::format(" WHEN {0} THEN goods_storage{2}{1} ", $datas[$i]['goodsId'], $datas[$i]['goodsNum'],\Our\ArrayConst::ops[$op]);
            $goodsEdittimeSql .= \Our\Common::format("  WHEN {0} THEN {1}", $datas[$i]['goodsId'],TIMESTAMP);
            $dataIds[] = $datas[$i]['goodsId'];
            //$updateAllSql .= $updateSql;
            if ($i % 1000 == 0 && $i != 0) {

                $goodsSql = trim($goodsSql,',').' END';
                $goodsEdittimeSql = ','.trim($goodsEdittimeSql,',').' END';
                $updateAllSql .= $goodsSql;
                $updateAllSql .= $goodsEdittimeSql;
                $updateAllSql .= \Our\Common::format(' where goods_id in ({0})',implode(',',$dataIds));
                $one = $this->db->update($this->_tableName)->query($updateAllSql);
                if (!$one) {
                    $error++;
                }
                $updateAllSql = $baseSql;
                $goodsSql = 'goods_storage = case goods_id ';
                $goodsEdittimeSql = ' goods_edittime = case goods_id ';
                $dataIds = array();
            }
        }
        if ($goodsSql) {
            $goodsSql = trim($goodsSql,',').' END';
            $goodsEdittimeSql = trim($goodsEdittimeSql,',').' END';
            $updateAllSql .= $goodsSql;
            $updateAllSql .= ','.$goodsEdittimeSql;
            $updateAllSql .= \Our\Common::format(' where goods_id in ({0})',implode(',',$dataIds));
            $one = $this->db->update($this->_tableName)->query($updateAllSql);
            if (!$one) {
                $error++;
            }
        }
        if ($error > 0) {
            return false;
        }
        return true;
    }



    /**
     * 获取格式化的规格值
     * @param $goodsSpecStr
     * @return array
     */
    public function  getFormatGoodsAttr($goodsSpecStr){
        $goodsAttr = array();
        if(!empty($goodsSpecStr)){
            $goodsSpec = unserialize($goodsSpecStr);
            if($goodsSpec){
                if (is_array($goodsSpec) && count($goodsSpec) > 0) {
                    $goodsAttr = array();
                    foreach ($goodsSpec as $key => $value) {
                        $attr['attrName'] = (string)$key;
                        $attr['attrValue'] = $value;
                        $goodsAttr[] = $attr;
                    }
                }
            }
        }
        return $goodsAttr;
    }

    /**
     * 类实例
     */
    private static $_instance = null;

    /**
     * 获取类实例
     */
    public static function getInstance($dbName=\Our\DbNameConst::salveDBConnectName) {
        if (!(self::$_instance instanceof self)) {
            self::$_instance = new self($dbName);
        }

        return self::$_instance;
    }

    public function getGoodsGroup($goodsGroup){
        $orderGoodses=array();
        if(!empty($goodsGroup)){
            $goodsGroup=unserialize($goodsGroup);
            $goodsGroup=json_decode(json_encode($goodsGroup),true);
            foreach($goodsGroup as $orderGoods){
                if(isset($orderGoods['goodsSpec'])){
                    unset($orderGoods['goodsSpec']);
                }
                $orderGoods['goodsImage']=\Our\ImageUtil::getGoodsImgUrl($orderGoods['goodsImagePath'],\Our\ImageConst::goods);
                unset($orderGoods['goodsImagePath']);
                array_push($orderGoodses,$orderGoods);
            }
        }
        return $orderGoodses;
    }
    public function getOriginPriceByGoodsGroup($goodsGroup){
        $goodsOriginPrice=ApiConst::zero;
        foreach( $goodsGroup as $goodsG){

            $goodsOriginPrice+=    $goodsG['num']*$goodsG['goodsPrice'];
        }
        return $goodsOriginPrice;
    }
    //ccw
    public function convert($goodses,$extentField=false,$refundOrders=false){
        if($refundOrders){
            $newGoods=Array();
            foreach($goodses as $goods){
                if($refundOrders[$goods['recId']]){
                    array_push($newGoods,$goods);
                }
            }
            $goodses=$newGoods;
        }
        foreach($goodses as &$goods){
            if($goods['refundId']==ApiConst::zero){
                if((!empty($extentField) || empty($goods['refundStateName'])) ){
                    $goods['refundStateName']=$extentField;
                }
            }
            $goods['goodsImage']=\Our\ImageUtil::getGoodsImgUrl($goods['goodsImage'],\Our\ApiConst::goodsSmallSize);
            if($goods['goodsSpec']){
                $goods['goodsAttr'] = $this->getFormatGoodsAttr($goods['goodsSpec']);
            }else{
                $goods['goodsAttr']=array();
            }
            if(isset($goods['refundStateName'])){
                $goods['refundStateName']= $goods['refundStateName']? $goods['refundStateName']:'';
            }

            unset($goods['goodsSpec']);

            if(isset($goods['goodsGroup'])&&!empty($goods['goodsGroup'])){
                $goods['goodsGroup']=$this->getGoodsGroup($goods['goodsGroup']);
                $goodsOriginPrice=ApiConst::zero;
                foreach( $goods['goodsGroup'] as $goodsG){

                    $goodsOriginPrice+=    $goodsG['num']*$goodsG['goodsPrice'];
                }
                $goods['goodsOriginPrice']= $goodsOriginPrice;

//                $goods['goodsDiscountPrice']=array_sum($goods['goodsGroup'],'discountPrice');
//                $goods['goodsReduceAmount']=$goods['goodsPayPrice']-$goods['goodsDiscountPrice'];
            }else{
                $goods['goodsGroup']=array();
            }
        }

        return $goodses;
    }

    public function getAlertCountByStoreId($storeId){
        $where=Common::format(" store_id={0}",$storeId);
        $where.=" and goods_storage<goods_storage_alarm";
        $alertCount=$this->getCountByWhere($where);
        return $alertCount;

    }

}
