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.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.AppletAppOrProductDTO;
import com.pcloud.book.applet.dto.AppletNewsDTO;
import com.pcloud.book.applet.dto.AppletRecordDTO;
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.base.exception.BookBizException;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
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.resourcecenter.product.dto.ProductDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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;

/**
 * (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;


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

    @Override
    @ParamLog("查询多条数据")
    public PageBeanNew getList(Long wechatUserId, Integer currentPage, Integer numPerPage) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("wechatUserId", wechatUserId);
        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 Long insert(ServeCollect serveCollect) {
        paramCheck(serveCollect);
        fillParam(serveCollect);
        serveCollectDao.insert(serveCollect);
        return serveCollect.getId();
    }

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

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