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

import com.pcloud.analysisengine.browse.dto.BrowseCacheRecordDto;
import com.pcloud.book.advertising.biz.AdvertisingBrandDataBiz;
import com.pcloud.book.advertising.check.BrandDataCheck;
import com.pcloud.book.advertising.dao.AdvertisingBrandBookDao;
import com.pcloud.book.advertising.dao.AdvertisingBrandDataDao;
import com.pcloud.book.advertising.dto.AddAdvertisingBrandBooksDTO;
import com.pcloud.book.advertising.dto.BookListForAdvertisingDTO;
import com.pcloud.book.advertising.dto.BrandDataAddDTO;
import com.pcloud.book.advertising.dto.BrandDataDTO4Channel;
import com.pcloud.book.advertising.dto.BrandDataParamDTO;
import com.pcloud.book.advertising.entity.AdvertisingBrandBook;
import com.pcloud.book.advertising.entity.AdvertisingBrandData;
import com.pcloud.book.advertising.enums.BrandDataAddTypeEnum;
import com.pcloud.book.advertising.enums.BrandDataFromTypeEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.consumer.analysisengine.BrowseRecordConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.group.dao.AppClickRecordDao;
import com.pcloud.book.group.dao.BookGroupCipherUserDao;
import com.pcloud.book.group.dto.BookGroupIdAndCountDTO;
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.wechatgroup.group.dto.GroupUserCountDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @描述：品牌方数据修改
 * @作者：zhuyajie
 * @创建时间：11:58 2020/4/16
 * @版本：1.0
 */
@Component("advertisingBrandDataBiz")
public class AdvertisingBrandDataBizImpl implements AdvertisingBrandDataBiz {

    @Autowired
    private AdvertisingBrandDataDao advertisingBrandDataDao;
    @Autowired
    private BrandDataCheck brandDataCheck;
    @Autowired
    private AdvertisingBrandBookDao advertisingBrandBookDao;
    @Autowired
    private BookAdviserDao bookAdviserDao;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private BrowseRecordConsr browseRecordConsr;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private AppClickRecordDao appClickRecordDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ParamLog("添加品牌方数据")
    public void addBrandData(BrandDataParamDTO brandDataParamDTO) {
        //参数校验
        brandDataCheck.checkAddData(brandDataParamDTO);
        //是否已存在
        AdvertisingBrandData brandData = new AdvertisingBrandData();
        BeanUtils.copyProperties(brandDataParamDTO,brandData);
        List<AdvertisingBrandData> dataList = advertisingBrandDataDao.queryAll(brandData);
        if (!ListUtils.isEmpty(dataList)){
            for (AdvertisingBrandData data:dataList){
                advertisingBrandDataDao.deleteById(data.getId());
            }
        }
        List<AdvertisingBrandData> brandDataList = new ArrayList<>();
        for (BrandDataAddDTO dataAddDTO: brandDataParamDTO.getDataAddDTOS()){
            AdvertisingBrandData advertisingBrandData = new AdvertisingBrandData();
            BeanUtils.copyProperties(brandDataParamDTO,advertisingBrandData);
            advertisingBrandData.setAddCount(dataAddDTO.getAddCount());
            advertisingBrandData.setAddType(dataAddDTO.getAddType());
            brandDataList.add(advertisingBrandData);
        }
        advertisingBrandDataDao.insert(brandDataList);
    }

    @Override
    public Map<String, Integer> getBrandData(AdvertisingBrandData advertisingBrandData) {
        List<AdvertisingBrandData> dataList = advertisingBrandDataDao.queryAll(advertisingBrandData);
        if (ListUtils.isEmpty(dataList)){
            return new HashMap<>();
        }
        Map<String, Integer> map = new HashMap<>();
        for (AdvertisingBrandData brandData:dataList){
            map.put(brandData.getAddType(),brandData.getAddCount());
        }
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新品牌方和书的关联关系")
    @Override
    public void addAdvertisingBrandBooks(AddAdvertisingBrandBooksDTO dto) {
        if (dto==null||dto.getAdvertisingBrandId()==null||ListUtils.isEmpty(dto.getBookIds())){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数错误！");
        }
        List<Long> bookIds=dto.getBookIds();
        List<Long> ids=bookIds.stream().distinct().collect(Collectors.toList());
        if (bookIds.size()!=ids.size()){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"一本书只能被一个品牌方标记！");
        }
        //看下之前是否被标记
        List<AdvertisingBrandBook> olds=advertisingBrandBookDao.getByBookIds(bookIds);
        if (!ListUtils.isEmpty(olds)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "一本书只能被一个品牌方标记！");
        }
        List<AdvertisingBrandBook> advertisingBrandBooks=new ArrayList<>();
        for (Long bookId:bookIds){
            AdvertisingBrandBook advertisingBrandBook=new AdvertisingBrandBook();
            advertisingBrandBook.setBookId(bookId);
            advertisingBrandBook.setAdvertisingBrandId(dto.getAdvertisingBrandId());
            advertisingBrandBooks.add(advertisingBrandBook);
        }
        //新增
        advertisingBrandBookDao.batchInsert(advertisingBrandBooks);
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("按书id批量删除品牌方和书的关联关系")
    @Override
    public void deleteAdvertisingBrandBooksByBookIds(List<Long> bookIds) {
        if (ListUtils.isEmpty(bookIds)){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        advertisingBrandBookDao.deleteByBookIds(bookIds);
    }

    @ParamLog("获取品牌方书刊列表")
    @Override
    public PageBeanNew<BookListForAdvertisingDTO> getBookListForAdvertising(Integer currentPage, Integer numPerPage, String keyword, Long advertisingBrandId, Boolean isPitch, Boolean is1v1) {
        if (currentPage==null||numPerPage==null||currentPage<0||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("keyword",keyword);
        map.put("advertisingBrandId",advertisingBrandId);
        map.put("isPitch",isPitch);
        map.put("is1v1",is1v1);
        PageBeanNew<BookListForAdvertisingDTO> pageNew = bookAdviserDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getBookListForAdvertising");
        fillOtherInfo(pageNew.getRecordList(),is1v1);
        fillAdd(pageNew.getRecordList(),is1v1);
        return pageNew;
    }

    private void fillAdd(List<BookListForAdvertisingDTO> list, Boolean is1v1) {
        List<Long> bookIds=list.stream().filter(s->s.getBookId()!=null).map(BookListForAdvertisingDTO::getBookId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(bookIds)){
            return;
        }
        List<AdvertisingBrandData> scan;
        List<AdvertisingBrandData> scanUser;
        List<AdvertisingBrandData> serveClick;
        Map<Long, Integer> friendsCountMap = new HashMap<>();
        if (is1v1 != null && is1v1) {
            List<AdvertisingBrandData> friendsCount = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.FRIENDS_COUNT.value);
            for (AdvertisingBrandData data : friendsCount) {
                friendsCountMap.put(data.getBookId(), data.getAddCount());
            }
            scan = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.GROUP_SCAN.value);
            scanUser = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.GROUP_SCAN_USER.value);
            serveClick = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.GROUP_SERVE_CLICK.value);
        } else {
            scan = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.SCAN.value);
            scanUser = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.SCAN_USER.value);
            serveClick = advertisingBrandDataDao.getBookAddByType(bookIds, BrandDataAddTypeEnum.SERVE_CLICK.value);
        }
        Map<Long,Integer> scanMap=new HashMap<>();
        Map<Long,Integer> scanUserMap=new HashMap<>();
        Map<Long,Integer> serveClickMap=new HashMap<>();
        for (AdvertisingBrandData data:scan){
            scanMap.put(data.getBookId(),data.getAddCount());
        }
        for (AdvertisingBrandData data:scanUser){
            scanUserMap.put(data.getBookId(),data.getAddCount());
        }
        for (AdvertisingBrandData data:serveClick){
            serveClickMap.put(data.getBookId(),data.getAddCount());
        }
        for (BookListForAdvertisingDTO dto:list){
            dto.setAddScanCount(scanMap.get(dto.getBookId()));
            dto.setAddScanPeople(scanUserMap.get(dto.getBookId()));
            dto.setAddServeBrowseCount(serveClickMap.get(dto.getBookId()));
            if (is1v1 != null && is1v1) {
                dto.setAddFriendCount(friendsCountMap.get(dto.getBookId()));
            }
        }
    }

    private void fillOtherInfo(List<BookListForAdvertisingDTO> list,Boolean is1v1) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        //填充二维码个数，扫码次数，扫码人数，服务点击次
        List<Long> channelIds = new ArrayList<>();
        List<Long> adviserIds = new ArrayList<>();
        List<Long> bookIds = new ArrayList<>();
        List<Long> bookGroupIds=new ArrayList<>();
        for (BookListForAdvertisingDTO dto : list) {
            if (!channelIds.contains(dto.getChannelId())){
                channelIds.add(dto.getChannelId());
            }
            if (!adviserIds.contains(dto.getAdviserId())){
                adviserIds.add(dto.getAdviserId());
            }
            if (!bookIds.contains(dto.getBookId())){
                bookIds.add(dto.getBookId());
            }
            if (is1v1 != null && is1v1 && !bookGroupIds.contains(dto.getBookGroupId())) {
                bookGroupIds.add(dto.getBookGroupId());
            }
        }
        Map<Long, GroupUserCountDTO> scanCountByGroup = wechatGroupConsr.getScanCountByGroup(bookGroupIds, null);
        Map<String, BrowseCacheRecordDto> bookScanAndUv = browseRecordConsr.getBookScanAndUv(adviserIds, channelIds, bookIds);
        Map<String, Long> bookServeBrowseCount = browseRecordConsr.getBookServeBrowseCount(adviserIds, channelIds, bookIds);
        Map<Long, Integer> addFriend = new HashMap<>();
        Map<Long, Integer> serveClickCountMap = new HashMap<>();
        if (is1v1 != null && is1v1 && !ListUtils.isEmpty(bookGroupIds)) {
            List<BookGroupIdAndCountDTO> addFriendByBookGroupIds = bookGroupCipherUserDao.getAddFriendByBookGroupIds(bookGroupIds);
            if (!ListUtils.isEmpty(addFriendByBookGroupIds)) {
                for (BookGroupIdAndCountDTO dto : addFriendByBookGroupIds) {
                    addFriend.put(dto.getBookGroupId(), dto.getCount());
                }
            }
            List<BookGroupIdAndCountDTO> serveClickCounts = appClickRecordDao.getClCoByBookGroupIds(bookGroupIds);
            for (BookGroupIdAndCountDTO se : serveClickCounts) {
                serveClickCountMap.put(se.getBookGroupId(), se.getCount());
            }
        }
        for (BookListForAdvertisingDTO dto : list) {
            if (is1v1 != null && is1v1) {
                Long bookGroupId=dto.getBookGroupId();
                if (addFriend.get(bookGroupId) != null) {
                    dto.setFriendCount(addFriend.get(bookGroupId));
                } else {
                    dto.setFriendCount(0);
                }
                //如果是1v1就取社群码的扫码量，扫码人数，服务点击量
                if (scanCountByGroup.get(bookGroupId) != null) {
                    dto.setScanPeople(scanCountByGroup.get(bookGroupId).getUserCount().longValue());
                    dto.setScanCount(scanCountByGroup.get(bookGroupId).getCount().longValue());
                }else {
                    dto.setScanPeople(0L);
                    dto.setScanCount(0L);
                }
                if (serveClickCountMap.get(bookGroupId)!=null){
                    dto.setServeBrowseCount(serveClickCountMap.get(bookGroupId).longValue());
                }else {
                    dto.setServeBrowseCount(0L);
                }
            }else {
                String key = dto.getBookId() + "-" + dto.getAdviserId() + "-" + dto.getChannelId();
                BrowseCacheRecordDto browseCacheRecordDto = bookScanAndUv.get(key);
                if (browseCacheRecordDto != null) {
                    dto.setScanPeople(browseCacheRecordDto.getBrowserCounts());
                    dto.setScanCount(browseCacheRecordDto.getScanCount());
                }
                dto.setServeBrowseCount(bookServeBrowseCount.get(key));
                Integer qrCount = qrcodeSceneConsr.getBookQRCountByMap(dto.getAdviserId(), dto.getChannelId(), dto.getBookId());
                dto.setQrcodeCount(qrCount);
            }
        }
    }

    @Override
    public Map<Long, BrandDataDTO4Channel> mapBrandQrServeAddData(BrandDataDTO4Channel brandDataDTO4Channel) {
        if (null==brandDataDTO4Channel || ListUtils.isEmpty(brandDataDTO4Channel.getServeIdList())
                || null == brandDataDTO4Channel.getSceneId() || null==brandDataDTO4Channel.getBookId()){
            return new HashMap<>();
        }
        if (!BrandDataFromTypeEnum.APP.value.equals(brandDataDTO4Channel.getFromType())&&!BrandDataFromTypeEnum.PRODUCT.value.equals(brandDataDTO4Channel.getFromType())){
            return new HashMap<>();
        }
        List<AdvertisingBrandData> dataList = advertisingBrandDataDao.getQrServeData4Channel(brandDataDTO4Channel);
        if (ListUtils.isEmpty(dataList)){
            return new HashMap<>();
        }
        Map<Long, BrandDataDTO4Channel> map = new HashMap<>();
        Map<Long,List<AdvertisingBrandData>> dataMap = dataList.stream().collect(Collectors.groupingBy(AdvertisingBrandData::getServeId));
        for (Map.Entry<Long,List<AdvertisingBrandData>> entry : dataMap.entrySet()){
            BrandDataDTO4Channel dto4Channel = new BrandDataDTO4Channel();
            for (AdvertisingBrandData brandData:entry.getValue()){
                if (BrandDataAddTypeEnum.READER.value.equals(brandData.getAddType())){
                    dto4Channel.setReaderNum(brandData.getAddCount());
                }else if (BrandDataAddTypeEnum.BROWSE.value.equals(brandData.getAddType())){
                    dto4Channel.setBrowseNum(brandData.getAddCount());
                }
            }
            map.put(entry.getKey(),dto4Channel);
        }
        return map;
    }

    @Override
    public Map<Long, BrandDataDTO4Channel> mapBrandQrAddData(BrandDataDTO4Channel brandDataDTO4Channel) {
        if (null==brandDataDTO4Channel || ListUtils.isEmpty(brandDataDTO4Channel.getSceneIdList())
                || null == brandDataDTO4Channel.getChannelId() || null==brandDataDTO4Channel.getBookId()
                || !BrandDataFromTypeEnum.QRCODE.value.equals(brandDataDTO4Channel.getFromType())){
            return new HashMap<>();
        }
        List<AdvertisingBrandData> dataList = advertisingBrandDataDao.getQrData4Channel(brandDataDTO4Channel);
        if (ListUtils.isEmpty(dataList)){
            return new HashMap<>();
        }
        Map<Long, BrandDataDTO4Channel> map = new HashMap<>();
        Map<Long,List<AdvertisingBrandData>> dataMap = dataList.stream().collect(Collectors.groupingBy(AdvertisingBrandData::getSceneId));
        for (Map.Entry<Long,List<AdvertisingBrandData>> entry : dataMap.entrySet()){
            BrandDataDTO4Channel dto4Channel = new BrandDataDTO4Channel();
            for (AdvertisingBrandData brandData:entry.getValue()){
                if (BrandDataAddTypeEnum.SCAN_USER.value.equals(brandData.getAddType())){
                    dto4Channel.setScanQrUserCount(brandData.getAddCount());
                }
            }
            map.put(entry.getKey(),dto4Channel);
        }
        return map;
    }

    @Override
    public List<Long> getAdvertisingBrandBooksIds(Long advertisingBrandId) {
        if (advertisingBrandId==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        return advertisingBrandBookDao.getBookIdsByAdvertisingBrandId(advertisingBrandId);
    }
}
