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

import cn.hutool.core.collection.CollUtil;
import com.pcloud.book.applet.dao.AppletBookClassifyDao;
import com.pcloud.book.applet.dto.AppletBookClassifyDTO;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.SearchBiz;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dao.HotBookDao;
import com.pcloud.book.book.dao.SearchRecordDao;
import com.pcloud.book.book.dao.SearchRecordDisDao;
import com.pcloud.book.book.dao.SearchRecordDisSaleDao;
import com.pcloud.book.book.dao.SearchRecordSaleDao;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.entity.HotBook;
import com.pcloud.book.book.entity.SearchRecord;
import com.pcloud.book.book.entity.SearchRecordDis;
import com.pcloud.book.book.vo.BookSearchTopVO;
import com.pcloud.book.book.vo.SearchBookVO;
import com.pcloud.book.consumer.common.ExportConsr;
import com.pcloud.book.consumer.message.MessageConsr;
import com.pcloud.book.consumer.reader.ReaderConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.AgentConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.channelcenter.wechat.service.AccountSettingService;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.readercenter.wechat.entity.WechatUser;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component("searchBiz")
public class SearchBizImpl implements SearchBiz {

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

    @Autowired
    private HotBookDao hotBookDao;
    @Autowired
    private SearchRecordDao searchRecordDao;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private SearchRecordDisDao searchRecordDisDao;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private AccountSettingService accountSettingService;
    @Autowired
    private SearchRecordSaleDao searchRecordSaleDao;
    @Autowired
    private SearchRecordDisSaleDao searchRecordDisSaleDao;
    @Autowired
    private AppletBookClassifyDao appletBookClassifyDao;

    @ParamLog("创建热门书")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createHotBook(HotBook hotBook) {
        if (hotBook==null|| hotBook.getBookId()==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"热门书不能为空！");
        }
        Integer maxSeqNum=hotBookDao.getMaxSeqNum();
        hotBook.setSeqNum(maxSeqNum+1);
        hotBookDao.insert(hotBook);
    }

    @ParamLog("刪除热门书")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteHotBook(Long id) {
        if (id==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"热门书id不能为空！");
        }
        hotBookDao.deleteById(id);
    }

    @ParamLog("获取热门书列表")
    @Override
    public PageBeanNew<HotBook> getHotBookList(Integer currentPage,Integer numPerPage) {
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        PageBeanNew<HotBook> pageNew = hotBookDao.listPageNew(new PageParam(currentPage, numPerPage), new HashMap<>(), "getHotBookList");
        List<HotBook> list=pageNew.getRecordList();
        //填充出版社信息
        fillHotBookAgent(list);
        fillClassify(list);
        return pageNew;
    }

    private void fillClassify(List<HotBook> list) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Long> templetIds = list.stream().filter(s -> s.getTempletId() != null).map(HotBook::getTempletId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(templetIds)) {
            return;
        }
        Map<Long, AppletBookClassifyDTO> classifyNameMap = appletBookClassifyDao.getClassifyNames(templetIds);
        if (MapUtils.isEmpty(classifyNameMap)) {
            return;
        }
        for (HotBook hotBook : list) {
            AppletBookClassifyDTO appletBookClassifyDTO = classifyNameMap.get(hotBook.getTempletId());
            if (appletBookClassifyDTO != null) {
                hotBook.setClassifyName(appletBookClassifyDTO.getClassifyName());
            }
        }
    }

    @ParamLog("填充书的出版社")
    private void fillHotBookAgent(List<HotBook> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        List<Long> adviserIds=list.stream().filter(s->s.getAdviserId()!=null).map(HotBook::getAdviserId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(adviserIds)){
            return;
        }
        Map<Long, AdviserBaseInfoDto> infoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        for (HotBook hotBook:list){
            AdviserBaseInfoDto infoDto = infoDtoMap.get(hotBook.getAdviserId());
            if (infoDto!=null){
                hotBook.setAgentId(infoDto.getAgentId());
                hotBook.setAgentName(infoDto.getAgentName());
            }
        }
    }

    @ParamLog("修改热门书排序值")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateHotBookSeqNum(HotBook hotBook) {
        if(hotBook==null||hotBook.getId()==null||hotBook.getSeqNum()==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        hotBookDao.updateSeqNum(hotBook.getId(),hotBook.getSeqNum());
    }

    @ParamLog("创建搜索记录H5")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void createSearchRecord4H5(SearchRecord searchRecord, Long officialAccountId) {
        if (searchRecord==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数为空！");
        }
        if (StringUtil.isEmpty(searchRecord.getContent())){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"内容不能为空！");
        }
        try {
            Long agentId = ResponseHandleUtil.parseResponse(accountSettingService.getAgentIdByAccountSettingId(officialAccountId), Long.class);
            searchRecord.setAgentId(agentId);
        } catch (Exception e) {
            LOGGER.info("[accountSettingService.getAgentIdByAccountSettingId] 获取 agentId 失败", e);
        }
        searchRecordDao.insert(searchRecord);
        createSearchRecordDis(searchRecord);
    }

    @ParamLog("获取热门搜索列表")
    @Override
    public PageBeanNew<SearchBookVO> getSearchList(String content, Integer currentPage, Integer numPerPage) {
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("content",content);
        PageBeanNew<SearchBookVO> pageNew = searchRecordDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getSearchList");
        fillSearchAgent(pageNew.getRecordList());
        return pageNew;
    }

    @ParamLog("导出热门搜索列表")
    @Override
    public void exportSearchList(String systemCode, Long partyId, String content) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                Integer count = getSearchList(content,0,1).getTotalCount();
                if (count > 10000) {
                    throw new BookBizException(BookBizException.ERROR, "数量超出限制，请添加筛选条件！");
                }
                List<SearchBookVO> list = new ArrayList<>();
                Integer cu = 500;
                Integer p = (count / cu) + 1;
                for (int i = 0; i < p; i++) {
                    PageBeanNew<SearchBookVO> page = getSearchList(content,i,cu);
                    list.addAll(page.getRecordList());
                }
                //导出
                exportSL(list, systemCode, partyId);
            } catch (Exception e) {
                LOGGER.error("exportSearchList+++content=" + content + "systemCode=" + systemCode + "partyId=" + partyId);
            }
        });
    }


    @ParamLog("导出")
    private void exportSL(List<SearchBookVO> list, String systemCode, Long partyId) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Object[]> dataList = new ArrayList<>();
        for (int i = 0, size = list.size(); i < size; i++) {
            SearchBookVO dto = list.get(i);
            Object[] obj = new Object[4];
            obj[0] = i + 1;
            obj[1] = dto.getContent();
            obj[2] = dto.getSearchCount();
            obj[3] = dto.getAgentName();

            dataList.add(obj);
        }
        Date date = new Date();
        String[] rowsName = {"序号", "关键词搜书内容", "搜索次数", "出版社"};
        String fileName = "用户实搜记录--" + DateUtils.getStrFormTime("yyyyMMdd", date);
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        String letterType = "pcloud_book_download";
        String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(date), fileName);
        messageConsr.sendLetter(partyId, partyId, content, systemCode, letterType, fileUrl, fileName, null, null);
    }

    @ParamLog("填充搜索记录出版社")
    private void fillSearchAgent(List<SearchBookVO> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        List<Long> agentIds=list.stream().filter(s->s.getAgentId()!=null).map(SearchBookVO::getAgentId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(agentIds)){
            return;
        }
        Map<Long, String> names = agentConsr.getNames(agentIds);
        for (SearchBookVO searchBookVO:list){
            if (searchBookVO.getAgentId()!=null){
                searchBookVO.setAgentName(names.get(searchBookVO.getAgentId()));
            }
        }
    }

    @ParamLog("获取某个热门搜索列表")
    @Override
    public PageBeanNew<SearchRecord> getSearchRecordList(String content, Long bookId, Long agentId, Integer currentPage, Integer numPerPage) {
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        if (StringUtil.isEmpty(content)){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"内容不能为空！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("content",content);
        map.put("bookId",bookId);
        map.put("agentId",agentId);
        PageBeanNew<SearchRecord> pageNew = searchRecordDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getSearchRecordList");
        fillAgentAndWxInfo(pageNew.getRecordList());
        return pageNew;
    }

    @ParamLog("导出某个热门搜索列表")
    @Override
    public void exportSearchRecordList(String systemCode, Long partyId, String content, Long bookId, Long agentId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                Integer count = getSearchRecordList(content,bookId,agentId,0,1).getTotalCount();
                if (count > 10000) {
                    throw new BookBizException(BookBizException.ERROR, "数量超出限制，请添加筛选条件！");
                }
                List<SearchRecord> list = new ArrayList<>();
                Integer cu = 500;
                Integer p = (count / cu) + 1;
                for (int i = 0; i < p; i++) {
                    PageBeanNew<SearchRecord> page = getSearchRecordList(content,bookId,agentId,i,cu);
                    list.addAll(page.getRecordList());
                }
                //导出
                exportSRL(list, systemCode, partyId);
            } catch (Exception e) {
                LOGGER.error("exportSearchRecordList+++content=" + content + "bookId="+bookId+"agentId="+agentId+"systemCode=" + systemCode + "partyId=" + partyId);
            }
        });
    }

    @ParamLog("获取搜索书籍的用户头像H5")
    @Override
    public List<String> getBookSearchUserList4H5(Long bookId) {
        List<String> wxIds=searchRecordDao.getRecent5WxIds(bookId);
        List<String> headPics=new ArrayList<>();
        if (!ListUtils.isEmpty(wxIds)){
            Map<String, GroupUserDTO> userDTOMap = wechatGroupConsr.mapWxUserInfoByWxIdList(wxIds);
            for (String wxId:wxIds){
                GroupUserDTO userDTO = userDTOMap.get(wxId);
                if (userDTO!=null&&!StringUtil.isEmpty(userDTO.getHeadPic())){
                    headPics.add(userDTO.getHeadPic());
                }
            }
        }
        return headPics;
    }

    @ParamLog("获取用户搜索书籍前几")
    @Override
    public List<BookSearchTopVO> getBookSearchTop(Integer top) {
        if (top==null||top<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        List<BookSearchTopVO> list = searchRecordDao.getBookSearchTop(top);
        if (!ListUtils.isEmpty(list)){
            List<Long> bookIds=list.stream().filter(s->s.getBookId()!=null).map(BookSearchTopVO::getBookId).collect(Collectors.toList());
            Map<Long, BookDto> map = bookDao.getMapByIds(bookIds);
            for (BookSearchTopVO vo:list){
                if (map.get(vo.getBookId())!=null){
                    vo.setCoverImg(map.get(vo.getBookId()).getCoverImg());
                }
            }
        }
        return list;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("查询dis表有没有相同数据，没有就新增，有就更新")
    @Override
    public void createSearchRecordDis(SearchRecord searchRecord) {
        SearchRecordDis searchRecordDisOld=searchRecordDisDao.getByCondition(searchRecord.getWechatUserId(),searchRecord.getWxId(),searchRecord.getContent());
        if (searchRecordDisOld==null){
            SearchRecordDis searchRecordDis=new SearchRecordDis();
            BeanUtils.copyProperties(searchRecord,searchRecordDis);
            searchRecordDisDao.insert(searchRecordDis);
        } else {
            searchRecordDisDao.update(searchRecordDisOld);
        }
    }

    @Override
    @ParamLog("丢书新增搜索记录")
    public void createSearchRecord4Sale(SearchRecord searchRecord, Long officialAccountId) {
        if (searchRecord==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数为空！");
        }
        if (StringUtil.isEmpty(searchRecord.getContent())){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"内容不能为空！");
        }
        try {
            Long agentId = ResponseHandleUtil.parseResponse(accountSettingService.getAgentIdByAccountSettingId(officialAccountId), Long.class);
            searchRecord.setAgentId(agentId);
        } catch (Exception e) {
            LOGGER.info("[accountSettingService.getAgentIdByAccountSettingId] 获取 agentId 失败", e);
        }
        searchRecordSaleDao.insert(searchRecord);
        createSearchRecordDis4Sale(searchRecord);
    }

    @Override
    public PageBeanNew<SearchRecord> getUserSearchList4Sale(String wxId, Long wechatUserId, Integer currentPage, Integer numPerPage) {
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("wxId",wxId);
        map.put("wechatUserId",wechatUserId);
        PageBeanNew<SearchRecord> page = searchRecordDisSaleDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getUserSearchList4H5","countUserSearchList4H5");
        return page;
    }

    @Override
    public void deleteUserSearchList4Sale(String wxId, Long wechatUserId) {
        if (StringUtil.isEmpty(wxId)&&wechatUserId==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        if (!StringUtil.isEmpty(wxId)){
            searchRecordSaleDao.updateUserDeleteByWxId(wxId,true);
            //同时删除去重表
            searchRecordDisSaleDao.updateUserDeleteByWxId(wxId,true);
        }
        if (wechatUserId!=null){
            searchRecordSaleDao.updateUserDeleteByWechatUserId(wechatUserId,true);
            //同时删除去重表
            searchRecordDisSaleDao.updateUserDeleteByWechatUserId(wechatUserId,true);
        }
    }

    private void createSearchRecordDis4Sale(SearchRecord searchRecord) {
        SearchRecordDis searchRecordDisOld=searchRecordDisSaleDao.getByCondition(searchRecord.getWechatUserId(),searchRecord.getWxId(),searchRecord.getContent());
        if (searchRecordDisOld==null){
            SearchRecordDis searchRecordDis=new SearchRecordDis();
            BeanUtils.copyProperties(searchRecord,searchRecordDis);
            searchRecordDisSaleDao.insert(searchRecordDis);
        } else {
            searchRecordDisSaleDao.update(searchRecordDisOld);
        }
    }


    @ParamLog("导出")
    private void exportSRL(List<SearchRecord> list, String systemCode, Long partyId) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Object[]> dataList = new ArrayList<>();
        for (int i = 0, size = list.size(); i < size; i++) {
            SearchRecord dto = list.get(i);
            Object[] obj = new Object[7];
            obj[0] = i + 1;
            obj[1] = dto.getContent();
            obj[2] = dto.getWxId();
            obj[3] = dto.getNickName();
            Integer sex=dto.getSex();
            if (sex.equals(new Integer(0))){
                obj[4] = "男";
            } else if (sex.equals(new Integer(1))){
                obj[4] = "女";
            }else {
                obj[4] = "未知";
            }
            obj[5] = dto.getAgentName();
            Date creatTime=dto.getCreateTime();
            obj[6] = DateUtils.formatDate(creatTime);
            dataList.add(obj);
        }
        Date date = new Date();
        String[] rowsName = {"序号", "搜索词", "用户id","昵称", "性别","出版社","读者输入时间"};
        String fileName = "读者记录--" + DateUtils.getStrFormTime("yyyyMMdd", date);
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        String letterType = "pcloud_book_download";
        String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(date), fileName);
        messageConsr.sendLetter(partyId, partyId, content, systemCode, letterType, fileUrl, fileName, null, null);
    }

    @ParamLog("获取用户最近搜索列表H5")
    @Override
    public PageBeanNew<SearchRecord> getUserSearchList4H5(String wxId, Long wechatUserId, Integer currentPage, Integer numPerPage) {
        if (currentPage==null||currentPage<0||numPerPage==null||numPerPage<=0){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"分页参数有误！");
        }
        Map<String,Object> map=new HashMap<>();
        map.put("wxId",wxId);
        map.put("wechatUserId",wechatUserId);
        PageBeanNew<SearchRecord> page = searchRecordDisDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getUserSearchList4H5","countUserSearchList4H5");
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("删除用户搜索记录H5")
    @Override
    public void deleteUserSearchList4H5(String wxId, Long wechatUserId) {
        if (StringUtil.isEmpty(wxId)&&wechatUserId==null){
            throw new BookBizException(BookBizException.PARAM_IS_ERROR,"参数有误！");
        }
        if (!StringUtil.isEmpty(wxId)){
            searchRecordDao.updateUserDeleteByWxId(wxId,true);
            //同时删除去重表
            searchRecordDisDao.updateUserDeleteByWxId(wxId,true);
        }
        if (wechatUserId!=null){
            searchRecordDao.updateUserDeleteByWechatUserId(wechatUserId,true);
            //同时删除去重表
            searchRecordDisDao.updateUserDeleteByWechatUserId(wechatUserId,true);
        }
    }

    @ParamLog("填充出版社和用户信息")
    private void fillAgentAndWxInfo(List<SearchRecord> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        List<Long> agentIds=new ArrayList<>();
        List<String> wxIds=new ArrayList<>();
        for (SearchRecord record:list){
            if (record.getAgentId()!=null){
                agentIds.add(record.getAgentId());
            }
            if (!StringUtil.isEmpty(record.getWxId())){
                wxIds.add(record.getWxId());
            }
        }
        Map<Long, String> names=new HashMap<>();
        if (!ListUtils.isEmpty(agentIds)){
            names = agentConsr.getNames(agentIds);
        }
        Map<String, GroupUserDTO> userDTOMap=new HashMap<>();
        if (!ListUtils.isEmpty(wxIds)){
            userDTOMap = wechatGroupConsr.mapWxUserInfoByWxIdList(wxIds);
        }

        List<Long> collect = list.stream().filter(x -> Objects.nonNull(x.getWechatUserId())).map(SearchRecord::getWechatUserId).distinct().collect(Collectors.toList());
        Map<Long, WechatUser> userList = readerConsr.getUserList(collect);

        for (SearchRecord searchRecord:list){
            if (searchRecord.getAgentId()!=null){
                searchRecord.setAgentName(names.get(searchRecord.getAgentId()));
            }
            if (!StringUtil.isEmpty(searchRecord.getWxId())){
                GroupUserDTO userDTO = userDTOMap.get(searchRecord.getWxId());
                if (userDTO!=null){
                    searchRecord.setHeadUrl(userDTO.getHeadPic());
                    searchRecord.setNickName(userDTO.getNickName());
                    searchRecord.setSex(userDTO.getSex());
                }
            }
            if (CollUtil.isNotEmpty(userList) && Objects.nonNull(searchRecord.getWechatUserId()) && userList.containsKey(searchRecord.getWechatUserId())){
                WechatUser wechatUser = userList.get(searchRecord.getWechatUserId());
                searchRecord.setHeadUrl(wechatUser.getWechatUserHeadurl());
                searchRecord.setNickName(wechatUser.getWechatUserNickname());
                searchRecord.setSex(wechatUser.getWechatUserSex());
            }
        }
    }
}
