<?php

namespace DAO;


use Error\CodeConfigModel;

class PBundlingModel extends \DAO\AbstractModel {



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

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

    }

//    public function getOtherListByStoreId($store_id,$group_id){
//        $this->setDb();
//        if(!$store_id || !$group_id){
//            return false;
//        }
//        $field = '';
//        $where = array();
//        $groupList=$this->db->select($field)->from($this->_tableName)->where($where)->order('gmt_create','DESC')->fetchOne();
//    }

    /**
     * @param $field
     * @param $where
     * @param array $limit
     * @param int $isDel 是否包含已删除数据(0:不包含,1包含)
     * @return mixed
     */
    public function getList($field,$where,$limit = [],$isDel = \Our\ApiConst::zero){
        $this->setDb($this->dbName);
        if(is_array($where)){
            $where = $this->db->getSqlWhereByArray($where);
        }
        $this->db->select($field)->from($this->_tableName)->where($where);
        if($isDel==\Our\ApiConst::zero){
            $this->db->where('is_del=0')->where("bl_quota_starttime <= ".time())->where('bl_quota_endtime >= '.time())->where('bl_state=1');
        }
        if($limit){
            $this->db->limit($limit[0],$limit[1]);
        }
        $result =  $this->db->fetchAll();
        return $result;
    }
    public function getImgPath($image){
        if($image){
            return \Our\Common::getStaticFile($image,\Our\ImageConst::storeLabel,'ossHost');
        }
    }

    public function getDetail($where,$field,$limit=false){
        $this->setDb($this->dbName);
        return $this->db->select($field)->from($this->_tableName)->join('han_p_bundling_goods',"han_p_bundling_goods.bl_id = han_p_bundling.bl_id",'inner')->where($where)->where("bl_quota_starttime <= ".time())->where('bl_quota_endtime >= '.time())->where('bl_state=1')->where('is_del=0')->limit($limit[0],$limit[1])->fetchAll();
    }
    public function getCount($where){
        $this->setDb($this->dbName);
        return $this->db->from($this->_tableName)->where($where)->where("bl_quota_starttime <= ".time())->where('bl_quota_endtime >= '.time())->where('bl_state=1')->where('is_del=0')->fetchNum();
    }


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

    public function findById($blId,$field = \Our\NameConst::allField){
        $where['bl_id'] = $blId;
        $data = $this->find($where,$field);
        return $data;
    }

    public function getBlGoodsStorage($blId){
        $pBundlingRedis = \Redis\Db4\PBundlingRedisModel::getInstance();
        $storage =  $pBundlingRedis->tableHGet(\Our\NameConst::onlineStorageBlGoodsPrefix,$blId);
        if($storage === false){
            $field = 'bl_storage';
            $pBundling  = $this->findById($blId,$field);
            if($pBundling){
                $storage = $pBundling['bl_storage'];
                $bundingGoodsWhere['bl_id'] = $blId;
                $bundlingGoodsList = \DAO\PBundlingGoodsModel::getInstance()->getList($this->pBundingGoodsField,$bundingGoodsWhere);
                $pBundlingRedis->tableHSet(\Our\NameConst::onlineStorageBlGoodsPrefix,$blId,$pBundling['bl_storage'],\Our\ApiConst::oneDaySecond);
            }else{
                $storage = \Our\ApiConst::zero;
            }
        }
        return $storage;
    }


    public function opBlGoodsStorage($blId,$num ,$op = \Our\ApiConst::minus){
        if(!($blId&&$num>0)){
            return false;
        }
        $storeage = $this->getBlGoodsStorage($blId);
        if($storeage>=$num&&$op == \Our\ApiConst::minus){
            $storeage -= $num;
        }else if($op == \Our\ApiConst::plus){
            $storeage += $num;
        }else if($op == \Our\ApiConst::set){
            $storeage = $num;
        }else{
            return false;
        }
        $pBundlingRedis = \Redis\Db4\PBundlingRedisModel::getInstance();
        $result = $pBundlingRedis->tableHSet(\Our\NameConst::onlineStorageBlGoodsPrefix,$blId,$storeage,\Our\ApiConst::oneDaySecond);
        $this->deletePBundlingByBlId($blId);
        return $result;
    }

    public function updateBlStorage($dataList,$op = \Our\ApiConst::minus){
        $datas = array_values($dataList);
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        $error = 0;
        $baseSql = "UPDATE {$this->_tableName} set bl_storage = case bl_id ";
        $updateAllSql = $baseSql;
        $dataIds = array();
        for ($i = 0; $i < count($datas); $i++) {
            $updateSql = \Our\Common::format(" WHEN {0} THEN bl_storage{2}{1} ", $datas[$i]['blId'], $datas[$i]['blStorage'],\Our\ArrayConst::ops[$op]);
            $dataIds[] = $datas[$i]['blId'];
            $updateAllSql .= $updateSql;
            if ($i % 1000 == 0 && $i != 0) {
                $updateAllSql .= \Our\Common::format('END where bl_id in ({0})',implode(',',$dataIds));
                $one = $this->db->update($this->_tableName)->query($updateAllSql);
                if (!$one) {
                    $error++;
                }
                $updateAllSql = $baseSql;
                $dataIds = array();
            }
        }
        if ($updateAllSql != $baseSql) {
            $updateAllSql .= \Our\Common::format('END where bl_id in ({0})',implode(',',$dataIds));
            $one = $this->db->update($this->_tableName)->query($updateAllSql);

            if (!$one) {
                $error++;
            }
        }
        if ($error > 0) {
            return false;
        }
        return true;
    }



    public function  getPBundlingCacheByBlId($blId){
        $pBundlingDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        $result = $pBundlingDao->getByKeys('gid_'.$blId);
        if($result){
            return $result['result'];
        }
        return false;
    }

    /**
     * 更新组合销售缓存
     * @param $blId
     * @param $blStorage
     * @param int $op
     * @return bool
     * @throws \Error\OurExceptionModel
     * @throws \Exception
     */
    public function updatePBundlingStorageCacheByBlId($blId,$blStorage,$op=\Our\ApiConst::minus){
        $isLock = \Lock\RedisLock::getInstance()->getLock(\Our\NameConst::pBundlingStorageRedisPrefix.$blId);
        if(!$isLock){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::serverBusy);
        }
        $pBundlingRedisDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        $result = $pBundlingRedisDao->getByKeys('gid_'.$blId);
        if(!$result){
            \Lock\RedisLock::getInstance()->releaseLock(\Our\NameConst::pBundlingStorageRedisPrefix.$blId);
            return false;
        }
        $pBundling = $result['result'];
        \Our\Log::getInstance()->write(json_encode($pBundling),'/data/log/apptest');
        $key = $result['key'];
        if($op == \Our\ApiConst::minus){
            $pBundling['bl_storage'] = $pBundling['bl_storage']-$blStorage;
            if($pBundling['bl_storage']-$blStorage<\Our\ApiConst::zero){
                \Lock\RedisLock::getInstance()->releaseLock(\Our\NameConst::pBundlingStorageRedisPrefix.$blId);
                \Error\ErrorModel::throwException(\Our\CodeConfigModel::pBundlingNoStorageForOrder);
            }
            $pBundling['bl_origin_storage'] = $pBundling['bl_origin_storage']-$blStorage;
        }else if($op == \Our\ApiConst::plus){
            $pBundling['bl_storage'] = $pBundling['bl_storage']+$blStorage;
            $pBundling['bl_origin_storage'] = $pBundling['bl_origin_storage']+$blStorage;
        }
        \Our\Log::getInstance()->write(json_encode($pBundling),'/data/log/apptest');
        \Lock\RedisLock::getInstance()->releaseLock(\Our\NameConst::pBundlingStorageRedisPrefix.$blId);
        \Our\Log::getInstance()->write($key,'/data/log/apptest');
        return $pBundlingRedisDao->setNoPrefix($key,serialize($pBundling),\Our\ApiConst::oneDaySecond);
    }


    /**
     * 更新需要更新缓存的链表
     * @param $pBundling
     */
    public function addChangedPBundlingStorage($pBundling){
        $pBundlingRedisDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        $pBundlingRedisDao->tableLPush(\Our\NameConst::changedPBundlingStoragePrefix,$pBundling);
    }

    /**
     * 获取需要更新缓存的链表数据
     */
    public function getChangedPbundlingStorage(){
        $pBundlingRedisDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        return $pBundlingRedisDao->tableLPop(\Our\NameConst::changedPBundlingStoragePrefix);
    }


    public function updateStorageByRedisList(){
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        for($i=0;$i<2000;$i++){
            $pbundlingStr = $this->getChangedPbundlingStorage();
            if(!$pbundlingStr){
                break;
            }
            $pbundling = unserialize($pbundlingStr);
            if($pbundling['op'] != \Our\ApiConst::set){
                $sql = \Our\Common::format("UPDATE {$this->_tableName} set bl_storage = bl_storage {2} {0} where bl_id = {1} ",$pbundling['bl_storage'],$pbundling['bl_id'],\Our\ArrayConst::ops[$pbundling['op']]);
            }else{
                $sql = \Our\Common::format("UPDATE {$this->_tableName} set bl_storage = {0} where bl_id = {1} ",$pbundling['bl_storage'],$pbundling['bl_id']);
            }
            $one = $this->db->update($this->_tableName)->query($sql);
            if($one===false){
                \Our\Log::getInstance()->write($sql.' 执行失败');
            }
        }
        return true;
    }


    public function deletePBundlingByBlId($blId){
        $pBundlingDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        $pBundlingDao->tableDelAll($pBundlingDao->tableKeys('gid_'.$blId));
    }

    public function deletePBundlingByGoodsCommonId($goodsCommonId){
        $pBundlingDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        return $pBundlingDao->tableDelAll($pBundlingDao->tableKeys('*'.\Our\NameConst::blGoods.$goodsCommonId));
    }

    /**
     * 根据GoodsCommonIds反向更新组合销售数据
     * @param $goodsCommonId
     */
    public function updatePBundlingByGoodsCommonId($goodsCommonId){
        $goodsRedis = \Redis\Db4\GoodsRedisModel::getInstance();
        $onlineStorageGoodsKey = \Our\NameConst::onlineStorageGoodsPrefix.$goodsCommonId;
        $onlineStorageGoods = $goodsRedis->tableHGAll($onlineStorageGoodsKey);

        $pBundlingRedisDao = \Redis\Db4\PBundlingRedisModel::getInstance();
        $keys = $pBundlingRedisDao->tableKeys('*'.\Our\NameConst::blGoods.$goodsCommonId);
        foreach($keys as $blIdKey){
            $pBundling = $pBundlingRedisDao->getNoPrefix($blIdKey);
            if(\Our\Common::isSerialized($pBundling)){
                $pBundling = unserialize($pBundling);
            }
            $goodsList = $pBundling['goodsList'];
            if($goodsList){
                $newGoods = array();
                foreach($goodsList as $goods){
                    if($goods['goodsCommonId']==$goodsCommonId){
                        $goods['goodsStorage'] = unserialize($onlineStorageGoods[$goods['goods_id']])['goodsStorage'];
                        if(intval($goods['goodsStorage']/$goods['num'])<$pBundling['bl_storage']){
                            $pBundling['bl_storage'] = intval($goods['goodsStorage']/$goods['num']);
                        }
                    }
                    $newGoods[] = $goods;
                }
                $pBundling['goodsList'] = $newGoods;
            }
            $pBundlingRedisDao->setNoPrefix($blIdKey,serialize($pBundling),\Our\ApiConst::oneDaySecond);
        }
        return true;
    }

    public function delPBundlingListByStoreIdAndBlIds($storeId=false,$blId=false){
        if($blId){
            \Our\RedisHelper::delCachedFunction(\Redis\Db4\PBundlingRedisModel::getInstance(),array(&$this, 'getList'),array(),array('*'.$blId.'*'));
        }
        if($storeId){
            \Our\RedisHelper::delCachedFunction(\Redis\Db4\PBundlingRedisModel::getInstance(),array(&$this, 'getList'),array(),array($storeId));
            $cartRedis = \Redis\Db7\CartRedisModel::getInstance();
            $memberCartKey = \Our\NameConst::memberStoreCartsPrefix.'*_'.$storeId;
            $cartRedis->tableDelAll($cartRedis->tableKeys($memberCartKey));
        }
    }

    /**
     * 类实例
     *
     * @var \DAO\UserModel
     */
    private static $_instance = null;

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

        return self::$_instance;
    }


}
