package com.pcloud.book.giftcoupon.biz.impl;

import com.google.common.collect.Lists;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.assist.dto.AssistTempletDTO;
import com.pcloud.book.applet.biz.AppletThirdResourcesBiz;
import com.pcloud.book.applet.dao.AppletLinkClickDao;
import com.pcloud.book.applet.dao.AppletThirdResourcesDao;
import com.pcloud.book.applet.dao.AppletUserBookcaseDao;
import com.pcloud.book.applet.dto.PvuvDTO;
import com.pcloud.book.applet.entity.AppletThirdResources;
import com.pcloud.book.applet.enums.DataRecordTypeEnum;
import com.pcloud.book.applet.enums.DataTypeEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookLabelBiz;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.app.AssistTempletConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.label.LabelConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.giftcoupon.biz.GiftCouponPackageBiz;
import com.pcloud.book.giftcoupon.check.GiftParamCheck;
import com.pcloud.book.giftcoupon.dao.GiftCategoryDao;
import com.pcloud.book.giftcoupon.dao.GiftCouponPackageDao;
import com.pcloud.book.giftcoupon.dao.GiftReceiveDao;
import com.pcloud.book.giftcoupon.dto.BatchReceiveDTO;
import com.pcloud.book.giftcoupon.dto.BatchUpdateDTO;
import com.pcloud.book.giftcoupon.dto.GiftCategoryDTO;
import com.pcloud.book.giftcoupon.dto.GiftPackageDTO;
import com.pcloud.book.giftcoupon.dto.GiftReceiveDTO;
import com.pcloud.book.giftcoupon.dto.ServeInfoDTO;
import com.pcloud.book.giftcoupon.entity.GiftCategory;
import com.pcloud.book.giftcoupon.entity.GiftCouponPackage;
import com.pcloud.book.giftcoupon.entity.GiftReceive;
import com.pcloud.book.giftcoupon.enums.CouponTypeEnum;
import com.pcloud.book.giftcoupon.enums.CouponUseTypeEnum;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.rightsSetting.biz.RightsSettingBiz;
import com.pcloud.book.rightsSetting.dao.RightsNowItemDao;
import com.pcloud.book.rightsSetting.entity.BaseTempletClassify;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.readercenter.rmall.entity.RmallBookMoneyRecord;
import com.pcloud.readercenter.rmall.enums.MoneyReceiveTypeEnum;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.pcloud.book.util.common.ThreadPoolUtils.RMALL_SIGN_IN;

@Component("giftCouponPackageBiz")
public class GiftCouponPackageBizImpl implements GiftCouponPackageBiz {

    @Autowired
    private GiftCouponPackageDao giftCouponPackageDao;
    @Autowired
    private GiftReceiveDao giftReceiveDao;
    @Autowired
    private GiftParamCheck giftParamCheck;
    @Autowired
    private AppletLinkClickDao appletLinkClickDao;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private AppletThirdResourcesBiz appletThirdResourcesBiz;
    @Autowired
    private RightsNowItemDao rightsNowItemDao;
    @Autowired
    private GiftCategoryDao giftCategoryDao;
    @Autowired
    private LabelConsr labelConsr;
    @Autowired
    private BookLabelBiz bookLabelBiz;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;
    @Autowired
    private AppletUserBookcaseDao appletUserBookcaseDao;
    @Autowired
    private AppletThirdResourcesDao appletThirdResourcesDao;
    @Autowired
    private ReaderConsr readerConsr;



    //将券库最大容量
    private final Integer COUPON_MAX_ALL_RECEIVE=10;
    private final Integer COUPON_MAX_SHOW_SIZE=4;


    @Transactional(rollbackFor = Exception.class)
    @ParamLog(value = "新增专享礼包", isAfterReturn = false)
    @Override
    public void createGiftPackage(GiftCouponPackage giftCouponPackage) {
        giftParamCheck.checkGiftAddParam(giftCouponPackage);
        if (null == giftCouponPackage.getAgentId()){
            giftCouponPackage.setAgentId(0L);
        }
        if (urlNumberExist(giftCouponPackage)){
            throw new BookBizException(BookBizException.ERROR,"链接编号重复");
        }
        if(StringUtil.isBlank(giftCouponPackage.getCoverPic())){
            giftCouponPackage.setCoverPic(BookConstant.DEFAULT_COVER_PIC);
        }
        giftCouponPackageDao.insert(giftCouponPackage);
        if(!ListUtils.isEmpty(giftCouponPackage.getGiftCategoryList())){
            giftCouponPackage.getGiftCategoryList().forEach(e->{
                e.setGiftPackageId(giftCouponPackage.getId());
            });
            giftCategoryDao.batchCreate(giftCouponPackage.getGiftCategoryList());
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog(value = "修改专享礼包", isAfterReturn = false)
    @Override
    public void updateGiftPackage(GiftCouponPackage giftCouponPackage) {
        giftParamCheck.checkGiftAddParam(giftCouponPackage);
        if (null == giftCouponPackage.getId()){
            throw new BookBizException(BookBizException.ERROR,"id为空");
        }
        GiftCouponPackage couponPackage = giftCouponPackageDao.getById(giftCouponPackage.getId());
        giftCouponPackage.setAgentId(couponPackage.getAgentId());
        if (urlNumberExist(giftCouponPackage)){
            throw new BookBizException(BookBizException.ERROR,"链接编号重复");
        }
        if(StringUtil.isBlank(giftCouponPackage.getCoverPic())){
            giftCouponPackage.setCoverPic(BookConstant.DEFAULT_COVER_PIC);
        }
        giftCategoryDao.deleteByPackageId(giftCouponPackage.getId());
        if(!ListUtils.isEmpty(giftCouponPackage.getGiftCategoryList())){
            giftCouponPackage.getGiftCategoryList().forEach(e->{
                e.setGiftPackageId(giftCouponPackage.getId());
            });
            giftCategoryDao.batchCreate(giftCouponPackage.getGiftCategoryList());
        }
        giftCouponPackageDao.update(giftCouponPackage);
    }

    @Override
    public GiftPackageDTO getGiftPackage(Long id) {
        GiftPackageDTO giftPackageDTO=giftCouponPackageDao.getByPackageId(id);
        if(null==giftPackageDTO){
            return giftPackageDTO;
        }
        giftPackageDTO.setDesc(StringUtils.isEmpty(giftPackageDTO.getResourceDesc()) ? new ArrayList<>() : Arrays.stream(giftPackageDTO.getResourceDesc().split(",")).collect(Collectors.toList()));
        List<GiftPackageDTO> giftPackageDTOS = Arrays.asList(giftPackageDTO);
        //设置分类
        fillCategory(giftPackageDTOS);
        //设置应用作品信息
        fillAppProductInfo(giftPackageDTOS);
        //设置课程券第三方链接
        giftPackageDTO.setAppletThirdResources(null==giftPackageDTO.getThirdResourceId() ? null : appletThirdResourcesDao.getByResourcesId(giftPackageDTO.getThirdResourceId()));
        return giftPackageDTO;
    }

    private void fillAppProductInfo( List<GiftPackageDTO> giftPackageDTOS ) {
        List<Long> productIds = giftPackageDTOS.stream().filter(a->null!=a.getServeId() && AppAndProductTypeEnum.PRODUCT.value.equals(a.getServeType())).map(a->a.getServeId()).distinct().collect(Collectors.toList());
        List<Long> appIds = giftPackageDTOS.stream().filter(a->null!=a.getServeId() && AppAndProductTypeEnum.APP.value.equals(a.getServeType())).map(a->a.getServeId()).distinct().collect(Collectors.toList());
        Map<Long, ProductDto> productDtoMap =!ListUtils.isEmpty(productIds) ? productConsr.getProBasesByIds(productIds) : new HashMap<>();
        Map<Long, AppDto> appDtoMap =!ListUtils.isEmpty(appIds) ? appConsr.mapByIds4AuditPass(appIds) : new HashMap<>();
        ServeInfoDTO serveInfoDTO;
        AccountSettingDto accountSettingDto;
        List<GiftPackageDTO> list_remove = new ArrayList<>();
        for (GiftPackageDTO item : giftPackageDTOS) {
            serveInfoDTO=new ServeInfoDTO();
            serveInfoDTO.setServeType(item.getServeType());
            serveInfoDTO.setServeId(item.getServeId());
            if (AppAndProductTypeEnum.PRODUCT.value.equals(item.getServeType())) {
                ProductDto productDto = productDtoMap.get(item.getServeId());

                if (productDto != null) {
                    serveInfoDTO.setServeName(productDto.getProductName());
                    serveInfoDTO.setServePic(productDto.getCoverImg());
                    if (productDto.getProductTypeDto() != null) {
                        serveInfoDTO.setServeTypeCode(productDto.getProductTypeDto().getTypeCode());
                        serveInfoDTO.setServeTypeName(productDto.getProductTypeDto().getTypeName());
                    }
                    //获取channelId,/C1404/product/display/10234028?adviserId=1001587&proType=MEMBER&source_type=QRCODE
                    Long channelId = null;
                    String url = item.getLinkUrl();
                    if (url.contains("/C") && !url.startsWith("https")) {
                        url = url.substring(url.indexOf("/C") + 2);
                        url = url.substring(0, url.indexOf("/"));
                        if (!StringUtil.isEmpty(url)) {
                            channelId = Long.valueOf(url);
                        }
                    }
                    if (null != channelId) {
                        accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
                        if (null == accountSettingDto){
                            throw new BookBizException(BookBizException.PARAM_IS_NULL, "运营平台未配置公众号");
                        }
                        String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, item.getLinkUrl());
                        serveInfoDTO.setResultUrl(resultLinkUrl);
                    } else {
                        serveInfoDTO.setResultUrl(item.getLinkUrl());
                    }
                    if (!StringUtil.isEmpty(productDto.getSkipUrl())){
                        serveInfoDTO.setHasThirdLink(true);
                    } else {
                        serveInfoDTO.setHasThirdLink(false);
                    }
                }
            }
            if (AppAndProductTypeEnum.APP.value.equals(item.getServeType())) {
                AppDto appDto = appDtoMap.get(item.getServeId());
                if (appDto != null) {
                    if (!StringUtil.isEmpty(appDto.getTurnUrl()) && appDto.getTurnUrl().contains("qrcode.5rs.me") && "ARTICLE".equals(appDto.getTypeCode())){
                        list_remove.add(item);
                    }
                    serveInfoDTO.setServeName(appDto.getTitle());
                    serveInfoDTO.setServePic(appDto.getSquareImg());
                    serveInfoDTO.setServeTypeCode(appDto.getTypeCode());
                    serveInfoDTO.setServeTypeName(appDto.getTypeName());
                    accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                    if (null == accountSettingDto){
                        throw new BookBizException(BookBizException.PARAM_IS_NULL, "运营平台未配置公众号");
                    }
                    String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, item.getLinkUrl());
                    serveInfoDTO.setResultUrl(resultLinkUrl);
                    if (!StringUtil.isEmpty(appDto.getTurnUrl())){
                        serveInfoDTO.setHasThirdLink(true);
                    } else {
                        serveInfoDTO.setHasThirdLink(false);
                    }
                } else {
                    list_remove.add(item); //把要移除的统一放在一个集合
                }
            }
            item.setServeInfoDTO(serveInfoDTO);
        }
    }

    @Override
    public void deleteGiftPackage(Long id) {
        //todo 删除应该有限制
        giftCouponPackageDao.deleteById(id);
        //1 删除即享权益
        rightsNowItemDao.deletePackageIds(Lists.newArrayList(id));
    }

    @Override
    public PageBeanNew<GiftPackageDTO> list4GiftPackage(String title, Integer state, Integer couponType,Integer currentPage, Integer numPerPage, Long agentId,Boolean onShelves) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("title", title);
        paramMap.put("state", state);
        paramMap.put("couponType", couponType);
        paramMap.put("agentId", agentId);
        paramMap.put("onShelves", onShelves);
        PageBeanNew<GiftPackageDTO> pageBeanNew=giftCouponPackageDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "list4GiftPackage");
        if (pageBeanNew == null || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        buildReceiveNum(pageBeanNew.getRecordList());
        //填充分类信息
        fillCategory(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    private void fillCategory(List<GiftPackageDTO> giftPackageDTOList) {
        if (ListUtils.isEmpty(giftPackageDTOList)) {
            return;
        }
        List<Long> packageIds = giftPackageDTOList.stream().map(a -> a.getId()).collect(Collectors.toList());
        List<Long> classifyIds=giftCategoryDao.getTemplateIds(packageIds);
        List<Long> labels=giftCategoryDao.getLabels(packageIds);
        List<GiftCategoryDTO> giftCategoryDTOList = giftCategoryDao.getByPackageIds(packageIds);
        Map<Long, List<GiftCategoryDTO>> map = ListUtils.isEmpty(giftCategoryDTOList) ? new HashMap<>() : giftCategoryDTOList.stream().collect(Collectors.groupingBy(a -> a.getGiftPackageId()));
        Map<Long, AssistTempletDTO> classifyMap = assistTempletConsr.mapByIds4Classify(classifyIds);
        Map<Long, String> labelMap = bookLabelBiz.getLabelMapByIds(labels);
        for (GiftPackageDTO giftPackageDTO : giftPackageDTOList) {
            if(MapUtils.isNotEmpty(map) && map.containsKey(giftPackageDTO.getId())){
                List<GiftCategoryDTO> giftCategoryDTOS = map.get(giftPackageDTO.getId());
                for (GiftCategoryDTO categoryDTO : giftCategoryDTOS) {
                    if(MapUtils.isNotEmpty(classifyMap) && classifyMap.containsKey(categoryDTO.getFirstClassify())){
                        categoryDTO.setFirstClassifyName(classifyMap.get(categoryDTO.getFirstClassify()).getTempletName());
                    }
                    if(MapUtils.isNotEmpty(classifyMap) && classifyMap.containsKey(categoryDTO.getSecondClassify())){
                        categoryDTO.setSecondClassifyName(classifyMap.get(categoryDTO.getSecondClassify()).getTempletName());
                    }
                    if(MapUtils.isNotEmpty(classifyMap) && classifyMap.containsKey(categoryDTO.getThirdClassify())){
                        categoryDTO.setThirdClassifyName(classifyMap.get(categoryDTO.getThirdClassify()).getTempletName());
                    }
                    if (MapUtils.isNotEmpty(labelMap) && labelMap.containsKey(categoryDTO.getSubjectLabelId())) {
                        categoryDTO.setSubjectLabelName(labelMap.get(categoryDTO.getSubjectLabelId()));
                    }
                    if (MapUtils.isNotEmpty(labelMap) && labelMap.containsKey(categoryDTO.getGradeLabelId())) {
                        categoryDTO.setGradeLabelName(labelMap.get(categoryDTO.getGradeLabelId()));
                    }
                }
                giftPackageDTO.setCategoryList(giftCategoryDTOS);
            }
        }
    }

    private void buildReceiveNum(List<GiftPackageDTO> recordList) {
        List<Long> giftIds = recordList.stream().filter(a -> null != a.getId()).map(a -> a.getId()).distinct().collect(Collectors.toList());
        List<GiftReceiveDTO> giftReceiveNumList = ListUtils.isEmpty(giftIds)?new ArrayList<>():giftReceiveDao.getGiftReceiveNumList(giftIds);
        Map<Long, Integer> receiveNumMap = new HashMap<>();
        if(!ListUtils.isEmpty(giftReceiveNumList)){
           receiveNumMap= giftReceiveNumList.stream().collect(Collectors.toMap(a -> a.getGiftPackageId(), a -> a.getReceiveNum(), (k1, k2) -> k2));
        }
        for (GiftPackageDTO giftPackageDTO : recordList) {
            giftPackageDTO.setReceiveNum(0);
            if(MapUtils.isNotEmpty(receiveNumMap) && receiveNumMap.containsKey(giftPackageDTO.getId())){
                giftPackageDTO.setReceiveNum(receiveNumMap.get(giftPackageDTO.getId()));
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog(value = "新增专享礼包", isAfterReturn = false)
    @Override
    public void createGiftReceive(GiftReceive giftReceive){
        giftParamCheck.checkGiftReceiveAddParam(giftReceive);
        GiftCouponPackage giftCouponPackage = giftCouponPackageDao.getById(giftReceive.getGiftPackageId());
        if(null==giftCouponPackage){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "当前奖券包不存在");
        }
        Integer giftReceiveCount = giftReceiveDao.getGiftReceiveCount(giftReceive.getWechatUserId(), giftReceive.getGiftPackageId());
        //库存减一
        if(giftCouponPackage.getStock()<1){
            throw new BookBizException(BookBizException.STOCK_IS_EMPTY, "今日库存已用完");
        }
        //超过单个奖券领取上限
        if(giftReceiveCount>=giftCouponPackage.getReceiveLimit()){
            throw new BookBizException(BookBizException.HAS_RECEIVED, "该类型的兑换券您已经领取过，请前往“我的券库”使用吧");
        }
        //超过券库总领取上限
        Integer giftAllReceiveCount =giftReceiveDao.getGiftAllReceiveCount(giftReceive.getWechatUserId());
        if(giftAllReceiveCount>=COUPON_MAX_ALL_RECEIVE){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "你的券库已达上限，请先去使用之后再领取吧！");
        }
        giftCouponPackageDao.reduceStock(giftReceive.getGiftPackageId());
        giftReceiveDao.insert(giftReceive);
    }

    @Override
    public PageBeanNew<GiftPackageDTO> list4MyGiftPackage(Integer state,Long wechatUserId,Integer currentPage, Integer numPerPage) {
        //state=1 已领取  state=2 已失效 state=3 已使用
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("wechatUserId", wechatUserId);
        paramMap.put("state", state);
        PageBeanNew<GiftPackageDTO> pageBeanNew=giftReceiveDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "list4MyGiftPackage");
        if (pageBeanNew == null || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        //设置应用作品信息
        fillAppProductInfo(pageBeanNew.getRecordList());
        pageBeanNew.getRecordList().forEach(e->{
            e.setDesc(StringUtils.isEmpty(e.getResourceDesc()) ? new ArrayList<>() : Arrays.stream(e.getResourceDesc().split(",")).collect(Collectors.toList()));
        });
        //设置课程券第三方链接
        setThirdResource(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    private void setThirdResource(List<GiftPackageDTO> list) {
        if(ListUtils.isEmpty(list)){
            return ;
        }
        List<Long> thirdResourceIds = list.stream().filter(a -> null != a.getThirdResourceId()).map(a -> a.getThirdResourceId()).distinct().collect(Collectors.toList());
        List<AppletThirdResources> appletsByIds =ListUtils.isEmpty(thirdResourceIds) ? new ArrayList<>() : appletThirdResourcesBiz.getAppletsByIds(thirdResourceIds);
        Map<Long, AppletThirdResources> map =ListUtils.isEmpty(appletsByIds) ? new HashMap<>() : appletsByIds.stream().collect(Collectors.toMap(a -> a.getId(), Function.identity(), (k1, k2) -> k2));
        list.forEach(e->{
            if(MapUtils.isNotEmpty(map) && map.containsKey(e.getThirdResourceId())){
                e.setAppletThirdResources(map.get(e.getThirdResourceId()));
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void useGiftCoupon(Long wechatUserId, Long receiveId) {
        GiftReceive giftReceive = giftReceiveDao.getById(receiveId);
        if(null==giftReceive){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "你还未领取该奖券包");
        }
        GiftCouponPackage giftCouponPackage = giftCouponPackageDao.getById(giftReceive.getGiftPackageId());
        if(null==giftCouponPackage){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "当前奖券包不存在");
        }
        //todo 可能有其他操作,如果点击不跳转页面，需要控制重复点击
        giftReceiveDao.useGiftCoupon(receiveId);
        //如果是书币券则更新书币记录及书币总量
        if (CouponTypeEnum.BOOK_COIN_COUPON.value.equals(giftCouponPackage.getCouponType()) && null != giftCouponPackage.getDenomination()) {
            RMALL_SIGN_IN.execute(()->{
                //书币兑换券
                RmallBookMoneyRecord rmallBookMoneyRecord = new RmallBookMoneyRecord();
                rmallBookMoneyRecord.setWechatUserId(wechatUserId);
                rmallBookMoneyRecord.setRecordType(MoneyReceiveTypeEnum.GIFT_COUPON.key);
                rmallBookMoneyRecord.setBookMoneyCount(giftCouponPackage.getDenomination() * 10);
                readerConsr.insertBookMoneyRecord(rmallBookMoneyRecord);
            });
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ParamLog(value = "礼券包一键领取", isAfterReturn = false)
    public void createGiftReceiveBatch(BatchReceiveDTO batchReceiveDTO, Long wechatUserId) {
        if (null==batchReceiveDTO || null==batchReceiveDTO.getRightsSettingId() || ListUtils.isEmpty(batchReceiveDTO.getGiftPackageIds())) {
            return;
        }
        Long rightsSettingId = batchReceiveDTO.getRightsSettingId();
        List<Long> giftPackageIds = batchReceiveDTO.getGiftPackageIds();
        List<Long> packageIdsBy = giftCouponPackageDao.getPackageIdsBy(giftPackageIds);
        if (ListUtils.isEmpty(packageIdsBy) || packageIdsBy.size() != giftPackageIds.size()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "有奖券包不存在，不能一键领取");
        }
        Integer noStockCount = giftCouponPackageDao.getNoStockCount(giftPackageIds);
        if (noStockCount > 0) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "有奖券包无库存，不能一键领取");
        }
        //超过券库总领取上限
        Integer giftAllReceiveCount =giftReceiveDao.getGiftAllReceiveCount(wechatUserId);
        if(giftAllReceiveCount>=COUPON_MAX_ALL_RECEIVE){
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "你的券库已达上限，请先去使用之后再领取吧！");
        }
        //判断是否有超过上限的
        List<GiftCouponPackage> overLimitCoupon = giftReceiveDao.getOverLimitCoupon(giftPackageIds, wechatUserId);
        if(!ListUtils.isEmpty(overLimitCoupon)){
            String titles = overLimitCoupon.stream().map(a -> a.getTitle()).collect(Collectors.joining(","));
            throw new BookBizException(BookBizException.PARAM_IS_NULL, titles+"兑换券您已经领取过，请前往”我的券库”使用吧");
        }
        //批量减库存
        giftCouponPackageDao.reduceStockBatch(giftPackageIds);
        //批量插入
        List<GiftReceive> list = new ArrayList<>();
        GiftReceive receive = null;
        for (Long giftPackageId : giftPackageIds) {
            receive = new GiftReceive();
            receive.setRightsSettingId(rightsSettingId);
            receive.setGiftPackageId(giftPackageId);
            receive.setWechatUserId(wechatUserId);
            list.add(receive);
        }
        giftReceiveDao.insert(list);
    }

    @Override
    public String getUrlNumberByUrl(String url, Long agentId) {
        if (StringUtil.isEmpty(url)){
            return "";
        }
        return giftCouponPackageDao.getUrlNumberByAddress(url, agentId);
    }

    @Override
    public PageBeanNew<GiftPackageDTO> listGiftPackage4Analysis(String title, Integer state, Integer couponType, Integer currentPage, Integer numPerPage, Integer linkOnly,Integer clickQty, Long agentId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("title", title);
        paramMap.put("state", state);
        paramMap.put("couponType", couponType);
        paramMap.put("linkOnly",linkOnly);
        paramMap.put("agentId", agentId);
        PageBeanNew<GiftPackageDTO> pageBeanNew=giftCouponPackageDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "listGiftPackage4Analysis");
        if (pageBeanNew == null || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        buildReceiveNum(pageBeanNew.getRecordList());
        fillUseAnalysis(pageBeanNew.getRecordList(),clickQty);
        return pageBeanNew;
    }

    /**
     * 填充使用分析
     * @author：zhuyajie
     * @date：2020/5/11 19:43
     *  * @param null
     */
    private void fillUseAnalysis(List<GiftPackageDTO> recordList,Integer clickQty) {
        if (ListUtils.isEmpty(recordList)){
            return;
        }
        if (null != clickQty && clickQty.intValue() >1){
            clickQty += 1;
        }
        List<Long> ids = recordList.stream().filter(s -> s != null).map(GiftPackageDTO::getId).distinct().collect(Collectors.toList());
        Map<Long, PvuvDTO> clickMap = appletLinkClickDao.mapPVUV(DataTypeEnum.gift_coupon.code, DataRecordTypeEnum.click.code, ids,clickQty);
        Map<Long, PvuvDTO> useMap = appletLinkClickDao.mapCouponUseCount(ids);
        for (GiftPackageDTO giftPackageDTO : recordList) {
            Long id = giftPackageDTO.getId();
            if (!MapUtils.isEmpty(clickMap) && clickMap.containsKey(id)) {
                PvuvDTO pvuvDTO = clickMap.get(id);
                giftPackageDTO.setClickPVUV(pvuvDTO.getPv() + "/" + pvuvDTO.getUv());
            } else {
                giftPackageDTO.setClickPVUV("0/0");
            }
            if (!MapUtils.isEmpty(useMap) && useMap.containsKey(id)) {
                PvuvDTO pvuvDTO = useMap.get(id);
                giftPackageDTO.setUseNum(pvuvDTO.getCount());
            } else {
                giftPackageDTO.setUseNum(0);
            }
        }
    }

    /**
     * 链接编号是否重复
     * @author：zhuyajie
     * @date：2020/5/11 18:50
     *  * @param null
     */
    public Boolean urlNumberExist(GiftCouponPackage giftCouponPackage) {
        Boolean exist = false;
        if (!CouponTypeEnum.COURSE_COUPON.value.equals(giftCouponPackage.getCouponType()) && !CouponUseTypeEnum.LINK.value.equals(giftCouponPackage.getUseType())) {//非外部链接
            return exist;
        }
        if (!StringUtil.isEmpty(giftCouponPackage.getExchangeAddress()) && !StringUtil.isEmpty(giftCouponPackage.getUrlNumber())) {
            exist = giftCouponPackageDao.urlNumberExist(giftCouponPackage.getExchangeAddress(), giftCouponPackage.getUrlNumber(), giftCouponPackage.getId(), giftCouponPackage.getAgentId());
        }
        return exist;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchUpdateGift(BatchUpdateDTO batchUpdateDTO) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("onShelves", batchUpdateDTO.getOnShelves());
        paramMap.put("packageIds",batchUpdateDTO.getPackageIds());
        //下架。解除和书的关系  立项权益里面要删除掉
        if(batchUpdateDTO.getOperateType()==1){
            giftCouponPackageDao.batchUpdateGift(paramMap);
            if(!batchUpdateDTO.getOnShelves()){
                rightsNowItemDao.deletePackageIds(batchUpdateDTO.getPackageIds());
            }
        }
        //设置分类
        if(batchUpdateDTO.getOperateType()==2){
            giftCategoryDao.deleteByPackageIds(batchUpdateDTO.getPackageIds());
            List<GiftCategory> list=new ArrayList<>();
            GiftCategory category;
            for (Long packageId : batchUpdateDTO.getPackageIds()) {
                for (BaseTempletClassify baseTempletClassify : batchUpdateDTO.getCategoryList()) {
                    if (Objects.nonNull(baseTempletClassify.getFirstClassify())){
                        rightsSettingBiz.setClassifyAndLabel(baseTempletClassify);
                        category=new GiftCategory();
                        BeanUtils.copyProperties(baseTempletClassify,category);
                        category.setGiftPackageId(packageId);
                        list.add(category);
                    }
                }
            }
            giftCategoryDao.batchCreate(list);
        }

    }

    @Override
    public List<GiftPackageDTO> listGiftPackage4Wechat(Long wechatUserId) {
        BaseTempletClassify baseTempletClassify = appletUserBookcaseDao.getLastReadBookInfo(wechatUserId);
        if (Objects.nonNull(baseTempletClassify) && Objects.nonNull(baseTempletClassify.getFirstClassify())) {
            rightsSettingBiz.setClassifyAndLabel(baseTempletClassify);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("firstClassify", null!=baseTempletClassify ? baseTempletClassify.getFirstClassify() : null);
        map.put("secondClassify", null!=baseTempletClassify ? baseTempletClassify.getSecondClassify() : null);
        map.put("thirdClassify", null!=baseTempletClassify ? baseTempletClassify.getThirdClassify() : null);
        map.put("gradeLabelId", null!=baseTempletClassify ? baseTempletClassify.getGradeLabelId() : null);
        map.put("subjectLabelId", null!=baseTempletClassify ? baseTempletClassify.getSubjectLabelId() : null);
        List<Long> resultIds = setSelectIds(map);
        if(ListUtils.isEmpty(resultIds)){
            return new ArrayList<>();
        }
        List<GiftPackageDTO> giftPackageDTOS = giftCouponPackageDao.getGiftByIds(resultIds);
        if(ListUtils.isEmpty(giftPackageDTOS)){
            return new ArrayList<>();
        }
        setHasReceived(wechatUserId, giftPackageDTOS);
        Map<Long, GiftPackageDTO> resultMap = giftPackageDTOS.stream().collect(Collectors.toMap(a -> a.getId(), Function.identity(), (k1, k2) -> k2));
        List<GiftPackageDTO> result=new ArrayList<>();
        for (Long resultId : resultIds) {
            if(MapUtils.isNotEmpty(resultMap) && resultMap.containsKey(resultId)){
                result.add(resultMap.get(resultId));
            }
        }
        return result;
    }

    @Override
    public GiftPackageDTO getCoupon4Sign() {
        GiftPackageDTO coupon4Sign = giftCouponPackageDao.getCoupon4Sign();
        if (null == coupon4Sign) {
            return new GiftPackageDTO();
        }
        coupon4Sign.setDesc(StringUtils.isEmpty(coupon4Sign.getResourceDesc()) ? new ArrayList<>() : Arrays.stream(coupon4Sign.getResourceDesc().split(",")).collect(Collectors.toList()));
        List<GiftPackageDTO> giftPackageDTOS = Arrays.asList(coupon4Sign);
        //设置分类
        fillCategory(giftPackageDTOS);
        //设置应用作品信息
        fillAppProductInfo(giftPackageDTOS);
        //设置课程券第三方链接
        coupon4Sign.setAppletThirdResources(null == coupon4Sign.getThirdResourceId() ? null : appletThirdResourcesDao.getByResourcesId(coupon4Sign.getThirdResourceId()));
        return coupon4Sign;
    }

    private List<Long> setSelectIds(Map<String, Object> map) {
        List<Long> list=giftCategoryDao.getByParams(map);
        Random index = new Random();
        List<Long> resultIds = new ArrayList<>();

        if(list.size()>=COUPON_MAX_SHOW_SIZE){
            List<Integer> indexList = new ArrayList<>();
            for(int i=0,j;i<COUPON_MAX_SHOW_SIZE;i++){
                //获取在 list.size 返回内的随机数
                j= index.nextInt(list.size());
                //判断是否重复
                if(!indexList.contains(j)){
                    //获取元素
                    indexList.add(j);
                    resultIds.add(list.get(j));
                }else{
                    i--;//如果重复再来一次
                }
            }
        }else{
            List<Integer> indexList = new ArrayList<>();
            if (!ListUtils.isEmpty(list)){
                resultIds.addAll(list);
            }
            List<Long> list1=giftCategoryDao.getOtherByParams(map);
            if(ListUtils.isEmpty(list1)){
                return resultIds;
            }
            if(list1.size()+resultIds.size()<=COUPON_MAX_SHOW_SIZE){
                resultIds.addAll(list1);
                return resultIds;
            }

            for(int i=0,j;i<COUPON_MAX_SHOW_SIZE-list.size();i++){
                //获取在 list.size 返回内的随机数
                j= index.nextInt(list1.size());
                //判断是否重复
                if(!indexList.contains(j)){
                    //获取元素
                    indexList.add(j);
                    resultIds.add(list1.get(j));
                }else{
                    i--;//如果重复再来一次
                }
            }
        }
        return resultIds;
    }

    private void setHasReceived(Long wechatUserId, List<GiftPackageDTO> list) {
        if(ListUtils.isEmpty(list)){
            return;
        }
        List<Long> packageIds = list.stream().map(a -> a.getId()).distinct().collect(Collectors.toList());
        List<Long> receivedIds= ListUtils.isEmpty(packageIds) ? new ArrayList<>() : giftReceiveDao.getReceivedIds(packageIds,wechatUserId);
        for (GiftPackageDTO giftPackageDTO : list) {
            giftPackageDTO.setHasReceived(false);
            if(!ListUtils.isEmpty(receivedIds) && receivedIds.contains(giftPackageDTO.getId())){
                giftPackageDTO.setHasReceived(true);
            }
            giftPackageDTO.setDesc(StringUtils.isEmpty(giftPackageDTO.getResourceDesc()) ? new ArrayList<>() : Arrays.stream(giftPackageDTO.getResourceDesc().split(",")).collect(Collectors.toList()));
        }
    }
}
