<?php
namespace Business\Coupon;
use Our\DbNameConst;

/**
 * User: liuyuzhen
 * Date: 2018/6/7
 * Time: 9:14
 * Description:
 */
class CouponServiceModel extends \Business\AbstractModel{

    public function getMyCoupons($where,$memberId){
        $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance();
        $validResult = $memberCouponDao->getValidMemberCoupon($where,$memberId);
        if($validResult==false){
            \Error\ErrorModel::throwException($memberCouponDao->errorCode);
        }
        if($where['couponState'] == \Our\ApiConst::couponUnused){
            $whereSql = ' coupon_state ='.$where['couponState'].' and member_id ='.$memberId.' and out_time > '.time();
        }else{
            $whereSql = ' coupon_state ='.$where['couponState'].' and member_id ='.$memberId;
        }
        $memberCouponArray = $memberCouponDao->getMemberCouponsByMemberId($whereSql,$memberId);
        if($memberCouponArray){
            $couponDao = \DAO\Coupon\CouponModel::getInstance();
            $couponIds = array_column($memberCouponArray,'coupon_id');
            if($couponIds){
                $coupons = $couponDao->getListByCouponIds($couponIds,$memberId);
                $storeDao = \DAO\StoreModel::getInstance();
                if($coupons){
                    foreach($coupons as $temp){
                        $couponList[$temp['id']] = $temp;
                    }
                    $returnCoupons = array();
                    foreach($memberCouponArray as $memberCoupon){
                        $coupon = $couponList[$memberCoupon['coupon_id']];

                        $temp = array();
                        $temp['type'] = $coupon['coupon_type'];
                        $temp['couponId'] = $coupon['id'];
                        $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['storeId'] = $coupon['store_id'];
                        if($temp['storeId']){
                            $storeInfo = $storeDao->get($temp['storeId'],false);//\Our\RedisHelper::cachedFunction(\Redis\Db6\StoreRedisModel::getInstance(),array(&$storeDao, 'getInfoById'),array($temp['storeId'],'store_name'),\Our\ApiConst::oneHour);
                            if(!$storeInfo){
                                continue;
                            }
                            $temp['storeName'] = $storeInfo['store_name'];
                        }else{
                            $temp['storeName'] = \Our\DescribeConst::wholePlatform;
                        }
                        $temp['startTime'] = $memberCoupon['add_time'];
                        $temp['endTime'] = $memberCoupon['out_time'];
                        $returnCoupons[] = $temp;
                    }
                }
            }

        }

        if(isset($returnCoupons)&&count($returnCoupons)>\Our\ApiConst::zero){
            return array('totalCount' => count($returnCoupons),'coupons' => $returnCoupons);
        }else{
            return array('totalCount'=>\Our\ApiConst::zero);
        }

    }

    public function getCouponById($where,$memberId){
        $couponDao = \DAO\Coupon\CouponModel::getInstance();
        if(!$where['couponId']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyCouponId);
        }
        $coupon = $couponDao->findById($where['couponId']);
        $coupon['cash_money'] = $coupon['cash_money']?($coupon['cash_money']/\Our\ApiConst::hundred):\Our\ApiConst::zero;
        $coupon['order_amount'] = $coupon['order_amount']?($coupon['order_amount']/\Our\ApiConst::hundred):\Our\ApiConst::zero;
        if(!$coupon || $coupon['is_del'] == 1 || time() > $coupon['end_time'] || time() < $coupon['start_time']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::couponNotExist);
        }
        $orderAmount = intval($coupon['order_amount']);
        $result['type'] = intval($coupon['coupon_type']);
        $result['couponId'] = intval($coupon['id']);
        if($coupon['coupon_type'] == \Our\ApiConst::fullMinusCouponType){//满额减免券
            $result['title'] = $coupon['cash_money'];
            $result['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullAvailable,$orderAmount);
        }else if($coupon['coupon_type'] == \Our\ApiConst::discountCouponType){
            $result['title'] = $coupon['discount'];
            $result['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullDiscount,$orderAmount,$coupon['discount']);
        }else if($coupon['coupon_type'] == \Our\ApiConst::fullForCouponCouponType){
            $result['title'] = \Our\DescribeConst::specialCoupon;
            $result['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullForCoupon,$orderAmount);
        }else if($coupon['coupon_type'] == \Our\ApiConst::fullForGiftCouponType){
            $result['title'] = \Our\DescribeConst::giftCoupon;
            $result['subTitle'] = \Our\Common::format(\Our\DescribeConst::couponFullForGift,$orderAmount);
        }
        $result['useMemo'] = $coupon['use_memo'];
        $result['isGet'] = \Our\ApiConst::zero;
        $result['couponType'] = intval($coupon['type']);
        if($memberId){
            $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance();
            if($coupon['is_overlay']){//允许领用多张的优惠券是否存在已经领取的未使用有效优惠券
                $whereSql = ' coupon_state ='.\Our\ApiConst::couponUnused.' and member_id ='.$memberId.'  and out_time > '.time();
                $memberCoupons = $memberCouponDao->getList($whereSql);
            }else{//不允许领用多张的优惠券
                $memberCoupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array(array('coupon_id'=>$where['couponId'],'member_id'=>$memberId)),\Our\ApiConst::oneHour,array($where['couponId']));
            }
            if($memberCoupons&&count($memberCoupons)>0){
                $result['isGet'] = \Our\ApiConst::one;
            }
        }
        return $result;
    }

    /**
     * 领取优惠券
     * @param $where
     * @param $memberId
     */
    public function receiveCoupon($where,$memberId){
        $this->getValidReceiveCoupon($where,$memberId);
        $dbName = \Our\DbNameConst::masterDBConnectName;
        $couponDao = \DAO\Coupon\CouponModel::getInstance($dbName);
        $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance($dbName);
        $couponDao->setDb($dbName);
        $couponDao->db->doTransaction();
        $coupon = $couponDao->findById($where['couponId']);
        $addTime = time();
        $outTime = $addTime + $coupon['effective_days']*\Our\ApiConst::oneDaySecond;
        $newMemberCoupon = array(
            'coupon_id' => $where['couponId'],
            'coupon_state' => \Our\ApiConst::couponUnused,
            'add_time' => $addTime,
            'out_time' => $outTime,
            'member_id' => $memberId
        );
        $memberCouponResult = $memberCouponDao->insert($newMemberCoupon);
        if(!$memberCouponResult){
            $couponDao->db->doRollback();
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::receiveCouponFailed);
        }
        $coupon = $couponDao->findById($where['couponId']);
        if($coupon['is_limit_num']==\Our\ApiConst::zero){
            $couponResult = $couponDao->updateTickNum(array('id'=>$where['couponId']));
            if(!$couponResult){
                $couponDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::receiveCouponFailed);
            }
        }
        $couponDao->db->doCommit();
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array(),array($memberId));
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getStoreCouponsById'),array(),array($coupon['store_id']."_".$memberId));
        return true;
    }


    /**
     * 购物车多店下单涉及到赠券时使用
     * @param $coupons
     * @param $memberId
     * @param int $orderId
     * @return bool
     * @throws \Error\OurExceptionModel
     * @throws \Exception
     * @throws \Our\Exception
     */
    public function receiveCouponBatch($coupons,$memberId,$orderId=\Our\ApiConst::zero){
        $dbName = \Our\DbNameConst::masterDBConnectName;
        $couponDao = \DAO\Coupon\CouponModel::getInstance($dbName);
        $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance($dbName);
        $couponDao->setDb($dbName);
        $couponDao->db->doTransaction();
        $addTime = TIMESTAMP;
        $couponIds = array();
        foreach($coupons as $coupon){
            $outTime = $addTime + $coupon['effective_days']*\Our\ApiConst::oneDaySecond;
            $newMemberCoupon = array(
                'coupon_id' => $coupon['id'],
                'coupon_state' => \Our\ApiConst::couponUnused,
                'add_time' => $addTime,
                'out_time' => $outTime,
                'member_id' => $memberId,
                'gift_order_id'=>$orderId
            );
            if($coupon['is_limit_num']==\Our\ApiConst::zero){
                $couponIds[] = $coupon['id'];
            }
            $newMemberCoupons[] = $newMemberCoupon;
        }
        if($newMemberCoupons){
            $memberCouponResult = $memberCouponDao->insertBatch($newMemberCoupons);
            if(!$memberCouponResult){
                $couponDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::receiveGiftCouponFailed);
            }
        }
        if($couponIds){
            $couponResult = $couponDao->updateTickNum(array('id'=>array('in',$couponIds)));
            if(!$couponResult){
                $couponDao->db->doRollback();
                \Error\ErrorModel::throwException(\Error\CodeConfigModel::receiveGiftCouponUpdateCouponCountFailed);
            }
        }
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array(),array($memberId));
        $couponDao->db->doCommit();
        return true;
    }
    /**
     * 验证领取优惠券信息
     * @param $where
     * @param $memberId
     * @return bool
     */
    public function getValidReceiveCoupon($where,$memberId,$dbName= \Our\DbNameConst::masterDBConnectName){
        if(!$memberId){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyMemberCouponMemberId);
        }
        if(!$where['couponId']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyCouponId);
        }
        $couponDao = \DAO\Coupon\CouponModel::getInstance($dbName);
        $coupon = $couponDao->findById($where['couponId']);
        if($coupon['is_del']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::couponNotExist);
        }
        if(!($coupon['start_time']<time()&&$coupon['end_time']>=time()&&$coupon['is_available'])){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::couponOverdue);
        }
        if($coupon['is_limit_num']==\Our\ApiConst::zero&&$coupon['used_ticket_num']<=\Our\ApiConst::zero){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::couponNoUsedTicketNum);
        }
        $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance($dbName);
        if($coupon['is_overlay']){//允许领用多张的优惠券是否存在已经领取的未使用有效优惠券
            $whereSql = ' coupon_state ='.\Our\ApiConst::couponUnused.' and member_id ='.$memberId.' and coupon_id='.$coupon['id'].' and out_time > '.time();
            //$memberCoupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array($whereSql),\Our\ApiConst::oneHour,array($where['couponId']));
            $memberCoupons = $memberCouponDao->getList($whereSql);
        }else{//不允许领用多张的优惠券
            $memberCoupons = \Our\RedisHelper::cachedFunction(\Redis\Db13\MemberCouponRedisModel::getInstance(), array(&$memberCouponDao, 'getList'),array(array('coupon_id'=>$where['couponId'],'member_id'=>$memberId)),\Our\ApiConst::oneHour,array($memberId));
        }
        if($memberCoupons&&count($memberCoupons)>0){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::alreadyGetTheCoupon);
        }
        return true;
    }


    /**
     * 获取促销优惠券标题列表
     * @param $where
     * @throws \Error\OurExceptionModel
     * @throws \Exception
     */
    public function getStorePromotionCouponTitles($where){
        $this->validCouponStore($where);
        $couponDao = \DAO\Coupon\CouponModel::getInstance();
        $couponTitles = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$couponDao, 'getStorePromotionCouponList'),array($where['storeId']),\Our\ApiConst::oneHour,array($where['storeId']));
        return $couponTitles?$couponTitles:array();
    }

    /**
     * 获取店铺首页优惠券
     */
    public function getStoreCoupons($where,$memberId = null){
        $couponDao = \DAO\Coupon\CouponModel::getInstance();
        $couponDao->validStoreCouponParam($where);
        $couponList = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getStoreCouponsById'),array($where['storeId'],$memberId),\Our\ApiConst::oneHour,array($where['storeId']."_".$memberId));
        if($couponList){
            $couponList = array_values($couponList);
            $couponList =$this->sortCouponList($couponList);
        }else{
            $couponList = array();
        }
        return $couponList;
    }

    public function getGoodsCoupons($where,$memberId = null){
        $this->validCouponStore($where);
        $couponDao = \DAO\Coupon\CouponModel::getInstance();
        $couponDao->validStoreCouponParam($where);
        $couponList = \Our\RedisHelper::cachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getStoreCouponsById'),array($where['storeId'],$memberId,\Our\ApiConst::one),\Our\ApiConst::oneHour,array($where['storeId']."_".$memberId));
        if($couponList){
            $couponList = array_values($couponList);
            $couponList = $this->sortCouponList($couponList);
            if(count($couponList)>=\Our\ApiConst::defaultCouponTitleLength){
                $couponTitleArray= array_slice($couponList,0,\Our\ApiConst::defaultCouponTitleLength);
            }else{
                $couponTitleArray= $couponList;
            }
            $couponTitles = array();
            foreach($couponTitleArray as $coupon){
                if($coupon['type'] == \Our\ApiConst::noLimitCouponType){
                    $couponTitles[] = $coupon['title'].\Our\DescribeConst::noLimitGoodsCouponName;
                }else if($coupon['type'] == \Our\ApiConst::fullMinusCouponType){
                    $couponTitles[] = str_replace(\Our\DescribeConst::available,\Our\DescribeConst::minus.$coupon['title'],$coupon['subTitle']);
                }else{
                    $couponTitles[] = $coupon['subTitle'];
                }
            }
            return array('couponsTitle'=>$couponTitles,'coupons'=>$couponList);
        }else{
            return array('couponsTitle'=>array(),'coupons'=>array());
        }
    }

    public function validCouponStore($where){
        if(!$where['storeId']){
            \Error\ErrorModel::throwException(\Error\CodeConfigModel::emptyCouponStoreId);
        }
        return true;
    }
    /**
     * 获取店铺优惠券
     * @param $storeId 店铺Id
     * @param $memberId 会员ID
     * @return array|bool
     */
    public function getStoreCouponsById($storeId,$memberId,$timeFlag = \Our\ApiConst::zero){
        $couponDao = \DAO\Coupon\CouponModel::getInstance();
        $couponList = $couponDao->getStoreIndexCouponList($storeId,$timeFlag);
        if(!$couponList){
            return false;
        }
        $couponIds = array_column($couponList,'couponId');
        $memberCouponList = array();
        if($memberId){
            $memberCouponDao = \DAO\Coupon\MemberCouponModel::getInstance();
            $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;
            }
            if(isset($memberCouponList[$coupon['couponId']])){
                $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;
                        }
                    }
                }
            }else{
                $coupon['isGet'] = \Our\ApiConst::zero;
            }
            unset($coupon['is_overlay']);
        }
        return $couponList;
    }

    /**
     * 删除店铺优惠券缓存
     * @param $storeId 店铺ID
     * @param bool $couponId 指定优惠券ID
     * @throws \Our\Exception
     */
    public function deleteCouponCache($storeId,$couponId=false){
        $couponDao = \DAO\Coupon\CouponModel::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(&$couponDao, 'getStorePromotionCouponList'),array(),array($storeId));
        \Our\RedisHelper::delCachedFunction(\Redis\Db13\CouponRedisModel::getInstance(), array(&$this, 'getStoreCouponsById'),array(),array($storeId));
    }

    public function sortCouponList($couponList){
        foreach($couponList as $key => $coupon){
            $isGet[$key] = $coupon['isGet'];
        }
        array_multisort($isGet, SORT_ASC, $couponList);
        return $couponList;
    }

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

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

        return self::$_instance;
    }
}