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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.google.common.collect.Lists;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.app.dto.AppTypeDto;
import com.pcloud.book.applet.biz.AppletNewsBiz;
import com.pcloud.book.applet.biz.ServeCollectBiz;
import com.pcloud.book.applet.dao.ServeCollectDao;
import com.pcloud.book.applet.dto.AppletAppOrProductDTO;
import com.pcloud.book.applet.dto.AppletNewsDTO;
import com.pcloud.book.applet.dto.AppletTaskDTO;
import com.pcloud.book.applet.dto.CollectionTypeNameAndCountDTO;
import com.pcloud.book.applet.dto.ServeCollectDTO;
import com.pcloud.book.applet.entity.ServeCollect;
import com.pcloud.book.applet.enums.AppletRecordTypeEnum;
import com.pcloud.book.applet.enums.CollectionTypeEnum;
import com.pcloud.book.applet.vo.CollectionTypeNameCodeClassifyVO;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.channelcenter.qrcode.dto.GroupQrcodeVO;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.channelcenter.wechat.entity.AccountSetting;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.readercenter.common.enums.YesOrNoNumEnum;
import com.pcloud.readercenter.rmall.constants.RmallContants;
import com.pcloud.readercenter.rmall.entity.RmallBookMoneyRecord;
import com.pcloud.readercenter.rmall.enums.MoneyReceiveTypeEnum;
import com.pcloud.readercenter.rmall.service.RmallBookMoneyRecordService;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

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

/**
 * (ServeCollect)表服务实现类
 *
 * @author makejava
 * @since 2020-09-10 10:44:31
 */
@Service("serveCollectBiz")
public class ServeCollectBizImpl implements ServeCollectBiz {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServeCollectBizImpl.class);

    @Autowired
    private ServeCollectDao serveCollectDao;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private AppletNewsBiz appletNewsBiz;
    @Autowired
    private RmallBookMoneyRecordService rmallBookMoneyRecordService;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private BookDao bookDao;
    @Value("${operate_official_id}")
    private Long operateOfficialId;


    @Override
    @ParamLog("通过ID查询单条数据")
    public ServeCollect getById(Long id) {
        return serveCollectDao.getById(id);
    }

    @Override
    @ParamLog("查询多条数据")
    public PageBeanNew getList(Long wechatUserId, Integer currentPage, Integer numPerPage, String typeCode,
                               Long officialAccountsId) {
        List<Long> wechatUserIds = readerConsr.getAllUnionUser(wechatUserId);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("wechatUserIds", wechatUserIds);
        paramMap.put("typeCode",typeCode);
        PageBeanNew pageBeanNew = serveCollectDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getList");
        List recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return pageBeanNew;
        }
        // 填充答案信息
        fillServes(recordList);
        return pageBeanNew;
    }

    private void fillServes(List<ServeCollect> recordList) {
        List<Long> serveIds = recordList.stream().map(ServeCollect::getServeId).collect(Collectors.toList());
        if (ListUtils.isEmpty(serveIds)) {
            return;
        }

        //根据不同的类型填充不同的数据
        List<Long> newsIds = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.NEWS.value.equals(serveCollect.getServeType())).
                map(ServeCollect::getServeId).distinct().collect(Collectors.toList());
        List<Long> productIds = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.PRODUCT.value.equals(serveCollect.getServeType())).
                map(ServeCollect::getServeId).distinct().collect(Collectors.toList());
        List<Long> appIds = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.APP.value.equals(serveCollect.getServeType())).
                map(ServeCollect::getServeId).distinct().collect(Collectors.toList());

        List<Long> bookIds = recordList.stream().filter(serveCollect ->
                AppletRecordTypeEnum.APP.value.equals(serveCollect.getServeType()) || AppletRecordTypeEnum.PRODUCT.value.equals(serveCollect.getServeType())
        ).map(ServeCollect::getBookId).distinct().collect(Collectors.toList());

        Map<Long, BookDto> bookDtoMap;
        CompletableFuture<Map<Long, BookDto>> bookDtoMapFuture = null;
        if (CollUtil.isNotEmpty(bookIds)) {
            bookDtoMapFuture = CompletableFuture.supplyAsync(() ->
                    Optional.ofNullable(bookDao.getMapByIds(bookIds)).orElse(new HashMap<>()), ThreadPoolUtils.FILL_APPLET_RECORD);
        }

        //资源map
        Map<Long, AppletNewsDTO> newsDtoMap = new HashMap<>();
        Future<Map<Long, AppletNewsDTO>> newsDtoMapFuture = null;
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Future<Map<Long, ProductDto>> productDtoMapFuture = null;
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        Future<Map<Long, AppDto>> appDtoMappFuture = null;
        if (!ListUtils.isEmpty(newsIds)) {
            newsDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> appletNewsBiz.getByIds4Record(newsIds));
        }
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> productConsr.getProBasesByIds(productIds));
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMappFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> appConsr.mapByIds4AuditPass(appIds));
        }

        bookDtoMap = Optional.ofNullable(bookDtoMapFuture).map(future -> {
            Map<Long, BookDto> map = null;
            try {
                map = future.get();
            } catch (InterruptedException | ExecutionException e) {
                LOGGER.warn("[AppletRecordBizImpl.fillAppletRecord] 异步获取图书信息失败", e);
            }
            return map;
        }).orElse(new HashMap<>());

        //存储已经删除群的群分类; 精选文章类型并且跳转链接包含qrcode.5rs.me
        Iterator<ServeCollect> iterator = recordList.iterator();
        while (iterator.hasNext()) {
            ServeCollect serveCollect = iterator.next();
            if (Objects.equals(AppletRecordTypeEnum.NEWS.value, serveCollect.getServeType()) && null != newsDtoMap) {
                //填充资讯信息
                filllAppletNews4Collect(newsDtoMap, newsDtoMapFuture, serveCollect);
            } else if (Objects.equals(AppletRecordTypeEnum.PRODUCT.value, serveCollect.getServeType())) {
                if ("ANSWER".equals(serveCollect.getServeTypeCode())) {
                    serveCollect.setBookName(Optional.ofNullable(bookDtoMap.get(serveCollect.getBookId())).map(BookDto::getBookName).orElse(""));
                    serveCollect.setCoverImg(Optional.ofNullable(bookDtoMap.get(serveCollect.getBookId())).map(BookDto::getCoverImg).orElse(""));
                }
                //填充作品信息
                fillProduct4Collect(productDtoMap, productDtoMapFuture, serveCollect);
            } else if (Objects.equals(AppletRecordTypeEnum.APP.value, serveCollect.getServeType())) {
                if ("ANSWER".equals(serveCollect.getServeTypeCode())) {
                    serveCollect.setBookName(Optional.ofNullable(bookDtoMap.get(serveCollect.getBookId())).map(BookDto::getBookName).orElse(""));
                    serveCollect.setCoverImg(Optional.ofNullable(bookDtoMap.get(serveCollect.getBookId())).map(BookDto::getCoverImg).orElse(""));
                }
                //填充应用信息
                fillApp4Collect(appDtoMap, appDtoMappFuture, serveCollect);
            }
        }
    }

    private void filllAppletNews4Collect(Map<Long, AppletNewsDTO> newsDtoMap, Future<Map<Long, AppletNewsDTO>> newsDtoMapFuture, ServeCollect serveCollect) {
        //填充资讯信息
        try {
            newsDtoMap = newsDtoMapFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("获取资讯错误: {}==", e);
        }
        if (MapUtil.isEmpty(newsDtoMap)) {
            return;
        }
        AppletNewsDTO appletNewsDTO = newsDtoMap.get(serveCollect.getServeId());
        if (null == appletNewsDTO || Objects.equals(YesOrNoNumEnum.YES.getValue(), appletNewsDTO.getIsDelete())) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        appletNewsDTO.setNewsType(appletNewsDTO.getType());
        appletNewsDTO.setNewsName(serveCollect.getServeName());
        serveCollect.setAppletNewsDTO(appletNewsDTO);
        serveCollect.setSourceDelete(appletNewsDTO.getShowState() ? YesOrNoNumEnum.NO.getValue() : YesOrNoNumEnum.YES.getValue());
    }

    private void fillApp4Collect(Map<Long, AppDto> appDtoMap, Future<Map<Long, AppDto>> appDtoMappFuture, ServeCollect serveCollect) {
        try {
            appDtoMap = appDtoMappFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("获取app错误: {}==", e);
        }
        if (MapUtil.isEmpty(appDtoMap)) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        AccountSettingDto accountSettingDto;
        AppDto appDto = appDtoMap.get(serveCollect.getServeId());
        AppletAppOrProductDTO appletAppOrProductDTO = new AppletAppOrProductDTO();
        if (appDto == null || appDto.getIsDelete()) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        if (!StringUtil.isEmpty(serveCollect.getLinkUrl()) && serveCollect.getLinkUrl().contains("qrcode.5rs.me") && "ARTICLE".equals(appDto.getTypeCode())) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        appletAppOrProductDTO.setServeName(appDto.getTitle());
        appletAppOrProductDTO.setServePic(appDto.getSquareImg());
        appletAppOrProductDTO.setServeTypeCode(appDto.getTypeCode());
        appletAppOrProductDTO.setServeTypeName(appDto.getTypeName());
        accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
        if (null == accountSettingDto) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, serveCollect.getLinkUrl());
        appletAppOrProductDTO.setResultUrl(resultLinkUrl);
        if (!StringUtil.isEmpty(appDto.getTurnUrl())){
            appletAppOrProductDTO.setHasThirdLink(true);
        } else {
            appletAppOrProductDTO.setHasThirdLink(false);
        }
        appletAppOrProductDTO.setServeType(AppAndProductTypeEnum.APP.value);
        appletAppOrProductDTO.setServeId(serveCollect.getServeId());
        serveCollect.setAppletAppOrProductDTO(appletAppOrProductDTO);
    }

    private void fillProduct4Collect(Map<Long, ProductDto> productDtoMap, Future<Map<Long, ProductDto>> productDtoMapFuture, ServeCollect serveCollect) {
        try {
            productDtoMap = productDtoMapFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("获取product错误: {}==", e);
        }
        if (MapUtil.isEmpty(productDtoMap)) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        AccountSettingDto accountSettingDto;
        ProductDto productDto = productDtoMap.get(serveCollect.getServeId());
        AppletAppOrProductDTO appletAppOrProductDTO = new AppletAppOrProductDTO();
        if (productDto == null || YesOrNoNumEnum.YES.getValue().equals(productDto.getIsDelete())) {
            serveCollect.setSourceDelete(YesOrNoNumEnum.YES.getValue());
            return;
        }
        appletAppOrProductDTO.setServeName(productDto.getProductName());
        appletAppOrProductDTO.setServePic(productDto.getCoverImg());
        if (productDto.getProductTypeDto() != null) {
            appletAppOrProductDTO.setServeTypeCode(productDto.getProductTypeDto().getTypeCode());
            appletAppOrProductDTO.setServeTypeName(productDto.getProductTypeDto().getTypeName());
        }
        //获取channelId,/C1404/product/display/10234028?adviserId=1001587&proType=MEMBER&source_type=QRCODE
        Long channelId = null;
        String url = serveCollect.getLinkUrl();
        if (!StringUtil.isEmpty(url) && 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 && StringUtil.isEmpty(serveCollect.getLinkUrl())) {
            accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            if (null != accountSettingDto) {
                String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, productDto.getTurnUrl());
                appletAppOrProductDTO.setResultUrl(resultLinkUrl);
            }
        } else {
            appletAppOrProductDTO.setResultUrl(serveCollect.getLinkUrl());
        }
        if (!StringUtil.isEmpty(productDto.getSkipUrl())){
            appletAppOrProductDTO.setHasThirdLink(true);
        } else {
            appletAppOrProductDTO.setHasThirdLink(false);
        }
        appletAppOrProductDTO.setServeType(AppAndProductTypeEnum.PRODUCT.value);
        appletAppOrProductDTO.setServeId(serveCollect.getServeId());
        serveCollect.setAppletAppOrProductDTO(appletAppOrProductDTO);
    }

    @Override
    @ParamLog("新增收藏")
    public String insert(ServeCollect serveCollect) {
        paramCheck(serveCollect);
        fillParam(serveCollect);
        List<Long> allUnionUserIds = readerConsr.getAllUnionUser(serveCollect.getWechatUserId());
        ServeCollect collected = serveCollectDao.getCollectByUser(allUnionUserIds, serveCollect.getServeId(), serveCollect.getServeType());
        if (null != collected) {
            if (YesOrNoNumEnum.YES.getValue().equals(collected.getIsDelete())) {
                //删除状态，则更新状态为收藏
                collected.setIsDelete(YesOrNoNumEnum.NO.getValue());
                serveCollectDao.update(collected);
            }
        } else {
            //不存在则新增
            if (StringUtil.isEmpty(serveCollect.getServeTypeName())) {
                fillTypeCodeAndTypeName(Lists.newArrayList(serveCollect));
            }
            serveCollectDao.insert(serveCollect);
        }
        AccountSetting appInfo = qrcodeSceneConsr.getAppInfo(operateOfficialId);
        return null != appInfo ? appInfo.getQrcodeUrl() : "https://oss.5rs.me/oss/uploadfe/jpg/5962646df4abeb5ece0b7037be4f3e6a.jpg";
    }

    private void fillParam(ServeCollect serveCollect) {
        if (null == serveCollect.getServeType()) {
            serveCollect.setServeType(CollectionTypeEnum.ANSWER.value);
        }
        if (null == serveCollect.getIsDelete()) {
            serveCollect.setIsDelete(YesOrNoEnums.NO.getValue());
        }
    }

    private void paramCheck(ServeCollect serveCollect) {
        if (null == serveCollect) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "serveCollect对象为空");
        }
        if (null == serveCollect.getWechatUserId()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "wechatUserId为空");
        }
        if (null == serveCollect.getServeId()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "应用id为空");
        }


    }

    @Override
    @ParamLog("修改")
    public void update(ServeCollect serveCollect) {
        if (serveCollect == null || !NumberUtil.isNumber(serveCollect.getId())) {
            throw BizException.PARAM_IS_NULL;
        }
        serveCollectDao.update(serveCollect);
    }

    @Override
    @ParamLog("删除")
    public void deleteById(Long id) {
        serveCollectDao.deleteById(id);
    }

    @Override
    public void cancelCollect(List<Long> ids) {
        serveCollectDao.cancelCollect(ids);
    }

    @Override
    public void deleteInvalidNews(List<Long> newsIds) {
        serveCollectDao.deleteInvalidNews(newsIds);
    }

    @Override
    public List<ServeCollect> getList4RightsSetting(List<ServeCollect> serveCollects) {
        return serveCollectDao.getList4RightsSetting(serveCollects);
    }

    @Override
    public List<ServeCollect> getList4RightsSettingByWechatUserId(Long wechatUserId) {
        return serveCollectDao.getList4RightsSettingByWechatUserId(wechatUserId);
    }

    @Override
    public List<CollectionTypeNameAndCountDTO> getTypeNameAndCountByWechatId(Long wechatUserId, Long officialAccountsId) {
        List<Long> wechatUserIds = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        return serveCollectDao.getTypeNameAndCountByWechatId(wechatUserIds);
    }

    @Override
    public PageBeanNew getListByTypeNameAndWechatUserId(String typeName, Long wechatUserId, Integer currentPage, Integer numPerPage) {
        Map<String, Object> param = new HashMap<>();
        param.put("typeName",typeName);
        param.put("wechatUserId",wechatUserId);
        PageBeanNew pageBeanNew = serveCollectDao.listPageNew(new PageParam(currentPage, numPerPage), param, "getListByTypeNameAndWechatUserId");
        return pageBeanNew;
    }

    @Override
    public ServeCollectDTO isCollected(Long wechatUserId, Long serverId) {
        if (null == wechatUserId || null == serverId){
            LOGGER.error("[ServeCollectBizImpl.isCollected]参数为空，wechatUserId:{} serverId:{}",wechatUserId,serverId);
            throw BizException.PARAM_IS_NULL;
        }
        ServeCollectDTO collected = serveCollectDao.isCollected(wechatUserId, serverId, AppletRecordTypeEnum.NEWS.value);
        if (null == collected){
            ServeCollectDTO serveCollectDTO = new ServeCollectDTO();
            serveCollectDTO.setIsCollected(0);
            return  serveCollectDTO;
        }
        collected.setIsCollected(1);
        return collected;
    }

    @Override
    public void processingData() {
        List<CollectionTypeNameCodeClassifyVO> typeNameCodeClassifyVOList = getDistinctTypeCode();
        if (ListUtils.isEmpty(typeNameCodeClassifyVOList)) {
            LOGGER.warn("[ServeCollectBizImpl.processingData] 获取typeCode失败：{}", typeNameCodeClassifyVOList);
            return;
        }
        //product与App
        solveTypeName(typeNameCodeClassifyVOList);
    }

     /**
     * 填充TypeName
     * @param typeNameCodeClassifyVOList
     */
    private void solveTypeName(List<CollectionTypeNameCodeClassifyVO> typeNameCodeClassifyVOList){
        if (ListUtils.isEmpty(typeNameCodeClassifyVOList)){
            return;
        }

        List<String> productTypeCodes = typeNameCodeClassifyVOList.stream().filter(collectionTypeNameCodeClassifyVO -> AppletRecordTypeEnum.PRODUCT.value.equals(collectionTypeNameCodeClassifyVO.getServeType())).
                map(collectionTypeNameCodeClassifyVO -> collectionTypeNameCodeClassifyVO.getServeTypeCode()).distinct().collect(Collectors.toList());
        List<String> AppTypeCodes = typeNameCodeClassifyVOList.stream().filter(collectionTypeNameCodeClassifyVO -> AppletRecordTypeEnum.APP.value.equals(collectionTypeNameCodeClassifyVO.getServeType())).
                map(collectionTypeNameCodeClassifyVO -> collectionTypeNameCodeClassifyVO.getServeTypeCode()).distinct().collect(Collectors.toList());
        //map资源
        Map<String, ProductTypeDto> productTypeDtoMap = new HashMap<>();
        Future<Map<String, ProductTypeDto>> productTypeDtoMapFuture = null;
        Map<String, AppTypeDto> appTypeDtoMap = new HashMap<>();
        Future<Map<String, AppTypeDto>> appTypeDtoMapFuture = null;

        productTypeDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> productConsr.getProType());
        appTypeDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() ->appConsr.listAllCode());
        //更新TypeName
        //product
        updateProductTypeName(productTypeDtoMap,productTypeDtoMapFuture,productTypeCodes);
        //App
        updateAppTypeName(appTypeDtoMap,appTypeDtoMapFuture,AppTypeCodes);
    }

    /**
     * 更新PRODUCT的TypeName
     * @param productTypeDtoMap
     * @param productTypeDtoMapFuture
     * @param productTypeCodes
     */
    private void updateProductTypeName(Map<String, ProductTypeDto> productTypeDtoMap,Future<Map<String, ProductTypeDto>> productTypeDtoMapFuture,List<String> productTypeCodes){
        try {
            productTypeDtoMap = productTypeDtoMapFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("获取商品TypeName错误: {}==", e);
        }
        if (MapUtil.isEmpty(productTypeDtoMap)) {
            return;
        }
        for (String productTypeCode : productTypeCodes) {
            Map<String,String> paramMap = new HashMap<>();
            String typeName = null;
            ProductTypeDto productTypeData = productTypeDtoMap.get(productTypeCode);
            if (null != productTypeData){
                typeName = productTypeData.getTypeName();
            }
            paramMap.put("serveTypeCode",productTypeCode);
            paramMap.put("serveTypeName",typeName);
            serveCollectDao.updateTypeName(paramMap);
            LOGGER.info("[ServeCollectBizImpl.processingData] 更新TypeName TypeCode:{}",productTypeCode);
        }
    }

    /**
     * 更新App的TypeName
     * @param appTypeDtoMap
     * @param appTypeDtoMapFuture
     * @param AppTypeCodes
     */
    private void updateAppTypeName(Map<String, AppTypeDto> appTypeDtoMap,Future<Map<String, AppTypeDto>> appTypeDtoMapFuture,List<String> AppTypeCodes){
        try {
            appTypeDtoMap = appTypeDtoMapFuture.get();
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("获取AppTypeName错误: {}==", e);
        }
        if (MapUtil.isEmpty(appTypeDtoMap)) {
            return;
        }
        for (String appTypeCode : AppTypeCodes) {
            Map<String,String> paramMap = new HashMap<>();
            String typeName = null;
            AppTypeDto appTypeData = appTypeDtoMap.get(appTypeCode);
            if (null != appTypeData){
                typeName = appTypeData.getTypeName();
            }
            paramMap.put("serveTypeCode",appTypeCode);
            paramMap.put("serveTypeName",typeName);
            serveCollectDao.updateTypeName(paramMap);
            LOGGER.info("[ServeCollectBizImpl.processingData] 更新TypeName TypeCode:{}",appTypeCode);
        }
    }

    /**
     * 获取所有TypeCode
     * @return
     */
    private List<CollectionTypeNameCodeClassifyVO> getDistinctTypeCode(){
        return serveCollectDao.getDistinctTypeCode();
    }

    /**
     * 填充数据:typeCode,typeName
     */
    public void processingData2TypeCode(){
        int currentPage = 0;
        while(true){
            PageBeanNew<ServeCollect> pageBeanNew = serveCollectDao.listPageNew(new PageParam(currentPage, 1000), null, "List2ProcessedData");
            if (CollUtil.isEmpty(pageBeanNew.getRecordList())){
                return;
            }
            fillTypeCodeAndTypeName(pageBeanNew.getRecordList());
            currentPage++;
            serveCollectDao.batchUpdate(pageBeanNew.getRecordList());
        }
    }

    @Override
    @ParamLog("取消收藏")
    public void cancel(ServeCollect serveCollect) {
        paramCheck(serveCollect);
        List<Long> allUnionUserIds = readerConsr.getAllUnionUser(serveCollect.getWechatUserId());
        List<ServeCollect> serveCollects = serveCollectDao.getCollectList(allUnionUserIds, serveCollect.getServeId(), serveCollect.getServeType(), null);
        if (ListUtils.isEmpty(serveCollects)) {
            return;
        }
        List<Long> ids = serveCollects.stream().map(e -> e.getId()).collect(Collectors.toList());
        serveCollectDao.cancelCollect(ids);
    }

    @Override
    public Boolean getCollectState(Long wechatUserId, Long serverId, Integer serveType) {
        List<Long> allUnionUserIds = readerConsr.getAllUnionUser(wechatUserId);
        List<ServeCollect> collectList = serveCollectDao.getCollectList(allUnionUserIds, serverId, serveType, YesOrNoNumEnum.NO.getValue());
        return ListUtils.isEmpty(collectList) ? Boolean.FALSE : Boolean.TRUE;
    }

    private void fillTypeCodeAndTypeName(List<ServeCollect> recordList){
        List<Long> newsIdList = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.NEWS.value.equals(serveCollect.getServeType())).
                map(serveCollect -> serveCollect.getServeId()).collect(Collectors.toList());
        List<Long> productsIdList = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.PRODUCT.value.equals(serveCollect.getServeType())).
                map(serveCollect -> serveCollect.getServeId()).collect(Collectors.toList());
        List<Long> appIdList = recordList.stream().filter(serveCollect -> AppletRecordTypeEnum.APP.value.equals(serveCollect.getServeType())).
                map(serveCollect -> serveCollect.getServeId()).collect(Collectors.toList());

        Map<Long, AppletNewsDTO> newsDtoMap = new HashMap<>();
        Future<Map<Long, AppletNewsDTO>> newsDtoMapFuture = null;
        Map<Long,ProductDto> productDtoMap = new HashMap<>();
        Future<Map<Long,ProductDto>> productDtoMapFuture = null;
        Map<Long,AppDto> appDtoMap = new HashMap<>();
        Future<Map<Long,AppDto>> appDtoMapFuture = null;

        if (!ListUtils.isEmpty(newsIdList)) {
            newsDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> appletNewsBiz.getByIds4Record(newsIdList));
        }
        if (!CollUtil.isEmpty(productsIdList)){
            productDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> productConsr.getProBasesByIds(productsIdList));
        }
        if (!CollUtil.isEmpty(appIdList)){
            appDtoMapFuture = ThreadPoolUtils.FILL_APPLET_RECORD.submit(() -> appConsr.mapByIds4AuditPass(appIdList));
        }
        Iterator<ServeCollect> iterator = recordList.iterator();
        while(iterator.hasNext()){
            ServeCollect serveCollect = iterator.next();
            if (Objects.equals(AppletRecordTypeEnum.NEWS.value, serveCollect.getServeType()) && null != newsDtoMap) {
                fillNewsTypeNameAndTypeCode(newsDtoMap, newsDtoMapFuture, serveCollect);
            }
            if (Objects.equals(AppletRecordTypeEnum.PRODUCT.value,serveCollect.getServeType())){
                fillProTypeNameAndTypeCode(productDtoMap,productDtoMapFuture,serveCollect);
            }
            if (Objects.equals(AppletRecordTypeEnum.APP.value,serveCollect.getServeType())){
                fillAppTypeNameAndTypeCode(appDtoMap,appDtoMapFuture,serveCollect);
            }
        }

    }

    /**
     * 填充product收藏的TypeName与TypeCode
     * @param productDtoMap
     * @param productDtoMapFuture
     * @param serveCollect
     */
    private void fillProTypeNameAndTypeCode(Map<Long,ProductDto> productDtoMap,Future<Map<Long,ProductDto>> productDtoMapFuture,ServeCollect serveCollect){
        try{
            productDtoMap =  productDtoMapFuture.get();
        }catch (InterruptedException | ExecutionException e){
            LOGGER.error("获取商品详情错误: {}==", e);
        }
        if (CollUtil.isEmpty(productDtoMap)){
            return;
        }
        if ( null != productDtoMap.get(serveCollect.getServeId())){
            serveCollect.setServeTypeCode(productDtoMap.get(serveCollect.getServeId()).getProductTypeCode());
            serveCollect.setServeTypeName(productDtoMap.get(serveCollect.getServeId()).getProductTypeName());
        }

    }

    /**
     * 填充App收藏的TypeName与TypeCode
     * @param appDtoMap
     * @param appDtoMapFuture
     * @param serveCollect
     */
    private  void fillAppTypeNameAndTypeCode(Map<Long,AppDto> appDtoMap,Future<Map<Long,AppDto>> appDtoMapFuture,ServeCollect serveCollect){
        try {
            appDtoMap = appDtoMapFuture.get();
        }catch (InterruptedException | ExecutionException e){
            LOGGER.error("获取App详情错误：{}==",e);
        }
        if (CollUtil.isEmpty(appDtoMap)){
            return;
        }
        if (null != appDtoMap.get(serveCollect.getServeId())){
            serveCollect.setServeTypeCode(appDtoMap.get(serveCollect.getServeId()).getTypeCode());
            serveCollect.setServeTypeName(appDtoMap.get(serveCollect.getServeId()).getTypeName());
        }
    }

    private  void fillNewsTypeNameAndTypeCode ( Map<Long, AppletNewsDTO> newsDtoMap,Future<Map<Long, AppletNewsDTO>> newsDtoMapFuture,ServeCollect serveCollect){
        try {
            newsDtoMap = newsDtoMapFuture.get();
        }catch (InterruptedException | ExecutionException e){
            LOGGER.error("获取App详情错误：{}==",e);
        }
        if (CollUtil.isEmpty(newsDtoMap)){
            return;
        }
        if (null != newsDtoMap.get(serveCollect.getServeId())){
            if (serveCollect.getServeTypeCode() == null){
                serveCollect.setServeTypeCode("NEWS");
            }
            if (null == serveCollect.getServeTypeName()){
                serveCollect.setServeTypeName(newsDtoMap.get(serveCollect.getServeId()).getSource());
            }
        }
    }

    @Override
    public List<Long> getAllCollect(Long wechatUserId,String typeCode,Long officialAccountsId) {
        List<Long> wechatUserIds = readerConsr.getRelateUserIdList(wechatUserId, officialAccountsId);
        return serveCollectDao.getAllCollect(wechatUserIds,typeCode);
    }

    @Override
    public List<ServeCollectDTO> getList4Collect(List<ServeCollectDTO> serveCollects) {
        return serveCollectDao.getList4Collect(serveCollects);
    }
}