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

import cn.hutool.core.map.MapUtil;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.app.dto.AppTypeDto;
import com.pcloud.appcenter.app.entity.AppType;
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.*;
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.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.skill.entity.PcloudResourceItem;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.enums.AppTypeEnum;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
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.enums.MoneyReceiveTypeEnum;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;
import io.swagger.models.auth.In;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.pcloud.readercenter.rmall.service.RmallBookMoneyRecordService;
import com.pcloud.readercenter.rmall.entity.RmallBookMoneyRecord;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
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;


    @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) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("wechatUserId", wechatUserId);
        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(e -> e.getServeId()).collect(Collectors.toList());
        if (ListUtils.isEmpty(serveIds)) {
            return;
        }

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

        //存储已经删除群的群分类; 精选文章类型并且跳转链接包含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())) {
                //填充作品信息
                fillProduct4Collect(productDtoMap, productDtoMapFuture, serveCollect);
            } else if (Objects.equals(AppletRecordTypeEnum.APP.value, serveCollect.getServeType())) {
                //填充应用信息
                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 AppletTaskDTO insert(ServeCollect serveCollect) {
        paramCheck(serveCollect);
        fillParam(serveCollect);
        AppletTaskDTO appletTaskDTO = new AppletTaskDTO();
        serveCollectDao.insert(serveCollect);
        Integer taskCount = readerConsr.getTaskCount(serveCollect.getWechatUserId(), MoneyReceiveTypeEnum.COLLECTION.key);
        Integer subtractTaskCount = RmallContants.COLLECTION_MONEY_TIMES - 1;
        Integer isFinish = 0;
        if  (null != taskCount &&  subtractTaskCount.equals(taskCount)) {
            isFinish = 1;
        }
        appletTaskDTO.setIsFinishTask(isFinish);
        RMALL_SIGN_IN.execute(()->{
            //收藏埋点
            if (null == serveCollect.getIsDelete() || YesOrNoNumEnum.NO.getValue().equals(serveCollect.getIsDelete())){
                RmallBookMoneyRecord rmallBookMoneyRecord = new RmallBookMoneyRecord();
                rmallBookMoneyRecord.setWechatUserId(serveCollect.getWechatUserId());
                rmallBookMoneyRecord.setRecordType(MoneyReceiveTypeEnum.COLLECTION.key);
                rmallBookMoneyRecordService.insert(rmallBookMoneyRecord);
            }
        });
        return appletTaskDTO;
    }

    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) {
        return serveCollectDao.getTypeNameAndCountByWechatId(wechatUserId);
    }

    @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);
        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();
    }

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

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