<?php

namespace DAO\Coupon;


use Our\ApiConst;
use Our\DbNameConst;
use Our\OrderConst;

class CouponModel extends \DAO\AbstractModel {


    /**
     * 表名
     *
     * @var string
     */
    protected $_tableName = 'han_coupon';
    /**
     * 主键
     *
     * @var string
     */
    protected $_primaryKey = 'id';

    protected $availStoreIndexField = 'id,type,FORMAT(cash_money/100,2) as cash_money,FORMAT(order_amount/100,2) as order_amount,discount,store_id,coupon_type,is_overlay,start_time,end_time,gift_coupon_id';
    protected $availCartStoreIndexField = 'id,type,FORMAT(cash_money/100,2) as cash_money,FORMAT(order_amount/100,2) as order_amount,discount,store_id,coupon_type,is_overlay,start_time,end_time,ids,gift_coupon_id,gift_goods_ids';

    public function init(){

    }
    public function getCount($where){
        $this->setDb($this->dbName);
        return $this->db->from($this->_tableName)->where($where)->fetchNum();
    }


    public function updateById($data,$couponId){
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        $result = $this->db->update($this->_tableName)->rows($data)->where(array('id'=>$couponId))->execute();
        if($result){
            $couponRedis=\Redis\Db13\CouponRedisModel::getInstance();
            $couponRedis->tableHMSet($couponId,$data);
        }
        return $result;

    }

    public function update($where,$data){
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        if(is_array($where)){
            $where = $this->db->getSqlWhereByArray($where);
        }
        $result = $this->db->update($this->_tableName)->rows($data)->where($where)->execute();
        if($result){
            $couponRedis=\Redis\Db13\CouponRedisModel::getInstance();
            $list = $this->getList($where);
            foreach($list as $tempCoupon){
                $couponRedis->tableHMSet($tempCoupon['id'],$tempCoupon);
            }
        }
        return $result;
    }

    public function updateTickNum($where){
        $this->setDb(\Our\DbNameConst::masterDBConnectName);
        if(is_array($where)){
            $where = $this->db->getSqlWhereByArray($where);
        }
        $result = $this->db->update($this->_tableName)->set('used_ticket_num', '-1', true)->where($where)->execute();
        if($result){
            $couponRedis=\Redis\Db13\CouponRedisModel::getInstance();
            $list = $this->getList($where);
            foreach($list as $tempCoupon){
                $couponRedis->tableHMSet($tempCoupon['id'],$tempCoupon);
            }
        }
        return $result;
    }





    /**
     * 获取单条数据
     * @param $where
     * @return array
     */
    public function find($where,$field='*'){
        $this->setDb($this->dbName);
        $data = $this->db->from($this->_tableName)->select($field)->where($where)->fetchOne();
        return $data;
    }

    public function findById($id,$field='*')
    {
        $couponRedis = \Redis\Db13\CouponRedisModel::getInstance();
        $coupon = $couponRedis->tableHGAll($id);
        if(!$coupon){
            $where['id'] = $id;
            $coupon = $this->find($where,$field);
            $couponRedis->tableHMSet($id,$coupon);
        }
        return $coupon;
    }

    public function getList($where,$field = '*'){
        $this->setDb($this->dbName);
        if(is_array($where)){
            $where = $this->db->getSqlWhereByArray($where);
        }
        $result = $this->db->select($field)->from($this->_tableName)->where($where)->fetchAll();
        return  $result ;
    }

    public function getOnlineCouponList($where,$field = \Our\NameConst::allField,$showFlag =true){
        $whereSql = ' start_time <'.time().' and end_time >='.time().' and is_del='.\Our\ApiConst::zero.' and is_available = '.\Our\ApiConst::one.' and ((is_limit_num =0 and used_ticket_num>0) or is_limit_num =1 ) ';
        if($showFlag){
            $whereSql .= ' and is_show ='.\Our\ApiConst::one ;
        }else{
            $whereSql .= ' and is_show ='.\Our\ApiConst::zero ;
        }
        if($where){
            $whereSql .= $where;
        }
        $result = $this->getList($whereSql,$field);
        return $result;
    }


    public function getListByCouponIds($couponIds,$memberId){
        $where = ' id in ('.implode(',',$couponIds).')';
        $field = $this->availStoreIndexField ;
        $coupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(),array(&$this, 'getList'),array($where,$field),\Our\ApiConst::oneHour,array($memberId));
        return $coupons;
    }

    /*
    public function getMemberCouponList($memberId){

    }
    */

    /**
     * 获取店铺促销的所有优惠券(除无门槛优惠券外)
     * @param $storeId
     * @return mixed
     * @throws \Our\Exception
     */
    public function getStorePromotionCouponList($storeId){
        $field = $this->availStoreIndexField;
        $where = ' and store_id ='.$storeId.' and type<>1';
        $this->setDb($this->dbName);
        //$coupons = $this->getOnlineCouponList($where,$field);

        $coupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getOnlineCouponList'),array($where,$field),\Our\ApiConst::oneHour,array($storeId));
        //$coupons = $this->getOnlineCouponList($where,$field);

        if(!$coupons){
            return false;
        }
        $qmStoreClassDao = \DAO\QmStoreClassModel::getInstance();
        $storeClasses = $qmStoreClassDao->getStoreOnlineParentGoodsClasses($storeId);
        $storeClassIds = array();
        if($storeClasses){
            $storeClassIds = array_column($storeClasses,'gc_id');
        }
        $storeCouponGoodsClassDao = \DAO\GoodsClass\StoreCouponGoodsClassModel::getInstance();
        $result = array();
        foreach($coupons as $coupon){
            if(!($coupon['start_time']<=TIMESTAMP&&$coupon['end_time']>TIMESTAMP)){
                continue;
            }
            if($coupon['type']==\Our\ApiConst::goodsClassCoupon){ //指定品类优惠券,需要判断该优惠券对应分类店铺是否在经营
                if($storeClassIds){
                    $gcIds = $storeCouponGoodsClassDao->getGoodsClassIdsByCouponId($coupon['id']);
                    if(!$gcIds){
                        continue;
                    }
                    $gcIdList = array_intersect($storeClassIds,$gcIds);
                    if(!$gcIdList){
                        continue;
                    }
                }
            }
            $temp = array();
            $temp['couponId'] = $coupon['id'];
            $orderAmount = intval($coupon['order_amount']);
            $cashMoney = intval($coupon['cash_money']);
            if($coupon['coupon_type'] == \Our\ApiConst::fullMinusCouponType){//满额减免券
                if($orderAmount>0){
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullAvailAble,$orderAmount,$cashMoney);
                }else{
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullAvailAbleNoAmountLimit,$cashMoney);
                }
            }else if($coupon['coupon_type'] == \Our\ApiConst::discountCouponType){
                if($orderAmount>0){
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullDiscount,$orderAmount,$coupon['discount']);
                }else{
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullDiscountNoAmoutLimit,$coupon['discount']);
                }
            }else if($coupon['coupon_type'] == \Our\ApiConst::fullForCouponCouponType){
                $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullForCoupon,$orderAmount);
            }else if($coupon['coupon_type'] == \Our\ApiConst::fullForGiftCouponType){
                $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullForGift,$orderAmount);
            }
            $result[] = $temp;
        }
        return $result;
    }

    /**
     * 获取店铺优惠券列表
     * @param $storeId
     * @return array|bool
     * @throws \Our\Exception
     */
    public function getStoreCouponList($storeId){
        $field = $this->availStoreIndexField;
        $where = ' and store_id = '. $storeId ;
        $coupons = $this->getOnlineCouponList($where,$field);
        //$coupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getOnlineCouponList'),array($where,$field),\Our\ApiConst::oneHour);
        return $coupons;
    }

    public function getCartCouponTitles($where,$field = 'id,type,FORMAT(cash_money/100,2) as cash_money,FORMAT(order_amount/100,2) as order_amount,discount,store_id,coupon_type,is_overlay,start_time,end_time,ids,gift_coupon_id,gift_goods_ids'){
        $coupons = $this->getList($where,$field);
        if($coupons){
            $result = array();
            foreach($coupons as $coupon){
                $temp = array();
                $temp['coupon_type'] = $coupon['coupon_type'];
                $temp['type'] = $coupon['type'];
                $temp['couponId'] = $coupon['id'];
                $temp['store_id'] = $coupon['store_id'];
                $temp['order_amount'] = $coupon['order_amount'];
                $temp['discount'] = $coupon['discount'];
                $temp['cash_money'] = $coupon['cash_money'];
                $temp['ids'] = $coupon['ids'];
                $temp['gift_coupon_id'] = isset($coupon['gift_coupon_id'])?$coupon['gift_coupon_id']:\Our\ApiConst::zero;
                $temp['gift_goods_ids'] = isset($coupon['gift_goods_ids'])?$coupon['gift_goods_ids']:\Our\NameConst::emptyString;
                $orderAmount = intval($coupon['order_amount']);
                if($coupon['type'] == \Our\ApiConst::noLimitCoupon){//无门槛优惠券
                    $temp['title'] = $coupon['cash_money'].\Our\DescribeConst::noLimitGoodsCouponName;
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullMinusCouponType){//满额减免券
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponTitleFullAvailAble,$orderAmount,$coupon['cash_money']);
                }else if($coupon['coupon_type'] == \Our\ApiConst::discountCouponType){
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponFullDiscount,$orderAmount,$coupon['discount']);
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullForCouponCouponType){
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponFullForCoupon,$orderAmount);
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullForGiftCouponType){
                    $temp['title'] = \Our\Common::format(\Our\DescribeConst::couponFullForGift,$orderAmount);
                }
                $result[$coupon['id']] = $temp;
            }

            return $result;
        }
    }

    /**
     * 获取店铺首页优惠券列表
     * @param $storeId 店铺Id
     * @return array
     */
    public function getStoreIndexCouponList($storeId,$timeFlag= \Our\ApiConst::zero){
        $coupons = $this->getStoreCouponList($storeId);
        if($coupons){
            $result = array();
            foreach($coupons as $coupon){
                $temp = array();
                $temp['type'] = $coupon['coupon_type'];
                $temp['couponId'] = $coupon['id'];
                $temp['is_overlay'] = $coupon['is_overlay'];
                $orderAmount = intval($coupon['order_amount']);
                if($coupon['type'] == \Our\ApiConst::noLimitCoupon){//无门槛优惠券
                    $temp['type'] = \Our\ApiConst::noLimitCouponType;
                    $temp['title'] = $coupon['cash_money'];
                    $temp['subTitle'] = \Our\DescribeConst::noLimitCoupon;
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullMinusCouponType){//满额减免券
                    $temp['title'] = $coupon['cash_money'];
                    $temp['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullAvailable,$orderAmount);
                }else if($coupon['coupon_type'] == \Our\ApiConst::discountCouponType){
                    $temp['title'] = $coupon['discount'];
                    $temp['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullDiscount,$orderAmount,$coupon['discount']);
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullForCouponCouponType){
                    $temp['title'] = \Our\DescribeConst::specialCoupon;
                    $temp['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullForCoupon,$orderAmount);
                }else if($coupon['coupon_type'] == \Our\ApiConst::fullForGiftCouponType){
                    $temp['title'] = \Our\DescribeConst::giftCoupon;
                    $temp['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullForGift,$orderAmount);
                }
                $temp['title'] = $temp['title'].'';
                if($timeFlag){
                    $temp['startTime'] = $coupon['start_time'];
                    $temp['endTime'] = $coupon['end_time'];
                }
                $result[$coupon['id']] = $temp;
            }
            return $result;
        }
        return false;
    }

    /**
     * 获取店铺优惠券
     * @param $storeId 店铺Id
     * @param $memberId 会员ID
     * @return array|bool
     */
    public function getStoreCouponsById($storeId,$memberId){
        $couponDao = \DAO\Coupon\CouponModel::getInstance($this->dbName);
        $this->setDb($this->dbName);
        $couponList = $couponDao->getStoreIndexCouponList($storeId);
        if(!$couponList){
            return false;
        }
        $couponIds = array_column($couponList,'couponId');
        $memberCouponList = array();
        if($memberId){
            $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance();
            $memberCouponDao->setDb($this->dbName);
            $memberCoupons = $memberCouponDao->getListByMemberId($memberId,$couponIds);
            if($memberCoupons){
                foreach($memberCoupons as $memberCoupon){
                    $memberCouponList[$memberCoupon['coupon_id']][] = $memberCoupon;
                }
            }
        }
        foreach($couponList as &$coupon){
            if(!$memberCouponList){
                $coupon['isGet'] = \Our\ApiConst::zero;
            }
            $memberTempCoupons = $memberCouponList[$coupon['couponId']];
            if(!$memberTempCoupons){//没有领用记录,则未领取
                $coupon['isGet'] = \Our\ApiConst::zero;
            }else{
                if($coupon['is_overlay'] == \Our\ApiConst::zero){ //不允许领用多张
                    $coupon['isGet'] = \Our\ApiConst::one;
                }else if($coupon['is_overlay'] == \Our\ApiConst::one){//允许领用多张
                    $couponStates = array_column($memberTempCoupons,'coupon_state');
                    if(in_array(\Our\ApiConst::availCouponState,$couponStates)){
                        $coupon['isGet'] = \Our\ApiConst::one;
                    }else{
                        $coupon['isGet'] = \Our\ApiConst::zero;
                    }
                }
            }
            unset($coupon['is_overlay']);
        }
        return $couponList;
    }


    /**
     * 获取店铺指定品类或指定商品优惠券减免金额
     * @param $coupon
     * @param $gcTotalPriceArray
     * @return array|bool
     */
    public function  calcCouponMinusMoney($coupon,$gcTotalPriceArray,$goodsList){
        if(!($coupon&&$gcTotalPriceArray)){
            return false;
        }
        $totalPrice = \Our\ApiConst::zero;
        if($gcTotalPriceArray){
            foreach($gcTotalPriceArray as $key=>$gcTotalPrice){
                if(strpos($coupon['ids'],','.$key.',')!==false){
                    $totalPrice +=$gcTotalPrice['totalPrice'];
                }
            }
        }
        return $this->calcCouponMinusMoneyByOrderAmount($coupon,$totalPrice,$goodsList);
    }

    public function calcCouponMinusMoneyByOrderAmount($coupon,$totalPrice,$goodsList){
        if(!($coupon&&$totalPrice)){
            return false;
        }
        if($coupon['coupon_type'] ==\Our\ApiConst::fullMinusCouponType&&($totalPrice>\Our\ApiConst::zero&&$totalPrice>=$coupon['order_amount'])){ //指定品类满减券
            $reliefAmount = $coupon['cash_money'];
        }else if($coupon['coupon_type'] ==\Our\ApiConst::discountCouponType&&($totalPrice>=$coupon['order_amount']||$coupon['order_amount']==\Our\ApiConst::zero)){//指定品类折扣券,可能没有订单限制,或有订单金额限制
            $reliefAmount = round($totalPrice * (\Our\ApiConst::ten-$coupon['discount'])/\Our\ApiConst::ten,\Our\ApiConst::zero);
        }else if(($coupon['coupon_type']== \Our\ApiConst::fullForCouponCouponType)
            &&($totalPrice>\Our\ApiConst::zero&&$totalPrice>=$coupon['order_amount'])){
            $reliefAmount = \Our\ApiConst::zero;
        }else if($coupon['coupon_type']== \Our\ApiConst::fullForGiftCouponType){//满额赠礼品
            $reliefAmount = $this->calcGiftCouponReliefAmount($coupon,$goodsList);
            if($reliefAmount===false){
                return false;
            }
        }
        if(isset($reliefAmount)){
            return $reliefAmount;
        }
        return  false;
    }


    /**
     * 满额赠礼品券
     * @param $coupon
     * @param $goodsList
     */
    public function calcGiftCouponReliefAmount($coupon,$goodsList){
        $giftGoodsIds = $coupon['gift_goods_ids'];
        if(!$giftGoodsIds){
            return false;
        }
        if(!$goodsList){
            return false;
        }
        if(!($coupon['order_amount']&&$coupon['order_amount']>\Our\ApiConst::zero)){
            return false;
        }
        $giftGoodsAmount = \Our\ApiConst::zero;
        $storeCouponPrice = \Our\ApiConst::zero;
        $gcPrices = array();
        $goodsCommonPrices = array();
        foreach($goodsList as $goods){
            if($goods['type']== \Our\ApiConst::addGoodsToCart){

                $goodsNum = $goods['goodsNum'];
                if(strpos($giftGoodsIds,','.$goods['goodsCommonId'].',')!==false){
                    $giftGoodsAmount += $goods['goodsPrice'];
                    $goodsNum = $goodsNum-\Our\ApiConst::one;
                }
                if($goodsNum>\Our\ApiConst::zero){
                    if(isset($gcPrices[$goods['gcId']])){
                        $gcPrices[$goods['gcId']] += $goods['goodsPrice']*$goodsNum;
                    }else{
                        $gcPrices[$goods['gcId']] = $goods['goodsPrice']*$goodsNum;
                    }
                    if(isset($goodsCommonPrices[$goods['goodsCommonId']])){
                        $goodsCommonPrices[$goods['goodsCommonId']] += $goods['goodsPrice']*$goodsNum;
                    }else{
                        $goodsCommonPrices[$goods['goodsCommonId']] = $goods['goodsPrice']*$goodsNum;
                    }
                    $storeCouponPrice += $goods['goodsPrice']*$goodsNum;
                }
            }
        }
        if($giftGoodsAmount==\Our\ApiConst::zero){
            return false;
        }
        $totalPrice = \Our\ApiConst::zero;
        if($coupon['type'] == \Our\ApiConst::goodsClassCoupon){//指定品类券
            if(!$gcPrices) {
                return false;
            }
            foreach($gcPrices as $key=>$gcTotalPrice){
                if(strpos($coupon['ids'],','.$key.',')!==false){
                    $totalPrice +=$gcTotalPrice;
                }
            }
        }else if($coupon['type'] == \Our\ApiConst::goodsCoupon){//指定商品优惠券
            if(!$goodsCommonPrices) {
                return false;
            }
            foreach($goodsCommonPrices as $key=>$goodsCommonPrice){
                if(strpos($coupon['ids'],','.$key.',')!==false){
                    $totalPrice += $goodsCommonPrice;
                }
            }
        }else if($coupon['type'] == \Our\ApiConst::commonCoupon){//普通优惠券
            if($storeCouponPrice==\Our\ApiConst::zero){
                return false;
            }
            $totalPrice += $storeCouponPrice;
        }
        if($totalPrice==\Our\ApiConst::zero){
            return false;
        }

        if($totalPrice>=$coupon['order_amount']){
            $reliefAmount = $giftGoodsAmount;
            return $reliefAmount;
        }
        return false;

    }

    /**
     * 获取店铺优惠券时验证参数
     * @param $where
     * @throws \Error\OurExceptionModel
     * @throws \Exception
     */
    public function validStoreCouponParam($where){
        if(!$where['storeId']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyCouponStoreId);
        }
    }



    /**
     * 删除店铺优惠券缓存
     * @param $storeId 店铺ID
     * @param bool $couponId 指定优惠券ID
     * @throws \Our\Exception
     */
    public function deleteCouponCache($storeId,$couponId=false){
        $couponService = \Business\Coupon\CouponServiceModel::getInstance();
        $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance();
        if($couponId){
            \Our\RedisHelper::delCachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array(),array($couponId));
        }
        //\Our\RedisHelper::delCachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getStorePromotionCouponList'),array(),array($storeId));
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$couponService, 'getStoreCouponsById'),array(),array($storeId));
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getOnlineCouponList'),array(),array($storeId));
        return true;
    }


    public function getDb()
    {
        return $this->db;
    }


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

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

        return self::$_instance;
    }




}
