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

import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.pcloud.book.applet.biz.BuyBookRequestBiz;
import com.pcloud.book.applet.dao.BuyBookRequestDao;
import com.pcloud.book.applet.dao.BuyBookRequestReplyDao;
import com.pcloud.book.applet.dto.BuyBookRequestDTO;
import com.pcloud.book.applet.dto.BuyBookRequestReplyDTO;
import com.pcloud.book.applet.dto.BuyBookRequetUserDTO;
import com.pcloud.book.applet.entity.BuyBookRequest;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.dto.BookDto;
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.util.common.ThreadPoolUtils;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.constant.SystemCode;
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.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.readercenter.wechat.dto.BuyBookProcessingDataDTO;
import com.pcloud.readercenter.wechat.entity.WechatUser;
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.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * (BuyBookRequest)表服务实现类
 *
 * @author makejava
 * @since 2020-10-14 19:51:41
 */
@Service("buyBookRequestBiz")
public class BuyBookRequestBizImpl implements BuyBookRequestBiz {

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


    @Autowired
    private BuyBookRequestDao buyBookRequestDao;
    @Autowired
    private ReaderConsr readerConsr;
    @Autowired
    private BookBiz bookBiz;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private BuyBookRequestReplyDao buyBookRequestReplyDao;

    @Override
    @ParamLog("通过ID查询单条数据")
    public BuyBookRequestDTO getById(Long id) {
        List<BuyBookRequestDTO> recordList = new ArrayList<>();
        BuyBookRequest byId = buyBookRequestDao.getById(id);
        BuyBookRequestDTO buyBookRequestDTO = new BuyBookRequestDTO();
        BeanUtils.copyProperties(byId,buyBookRequestDTO);
        recordList.add(buyBookRequestDTO);
        fillAgentInfo(recordList);
        return buyBookRequestDTO;
    }

    @Override
    @ParamLog("查询多条数据")
    public PageBeanNew getList(Integer currentPage, Integer numPerPage, Long agentId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId" , agentId);
        paramMap.put("isDelete", 0);
        PageBeanNew pageBeanNew = buyBookRequestDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getList");
        List<BuyBookRequestDTO> recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return pageBeanNew;
        }
        // 加载其它数据
        fillAgentInfo(recordList);
        return pageBeanNew;
    }

    private void fillAgentInfo(List<BuyBookRequestDTO> recordList) {
        List<Long> bookIds = recordList.stream().map(e -> e.getBookId()).collect(Collectors.toList());
        List<Long> agentIds = recordList.stream().map(e -> e.getAgentId()).collect(Collectors.toList());
        List<Long> adviserIds = recordList.stream().map(e -> e.getAdviserId()).collect(Collectors.toList());
        List<Long> requestIds = recordList.stream().map(e -> e.getId()).collect(Collectors.toList());
        Map<Long, BookDto> bookDtoMap = new HashMap<>();
        Map<Long, String> agentNameMap = new HashMap<>();
        Map<Long, String> adviserNameMap = new HashMap<>();
        List<BuyBookRequestReplyDTO> requestReplyDTOS = new ArrayList<>();
        if (!ListUtils.isEmpty(bookIds)) {
            bookDtoMap = bookBiz.getListByIds(bookIds);
        }
        if (!ListUtils.isEmpty(agentIds)) {
            agentNameMap = agentConsr.getNames(agentIds);
        }
        if (!ListUtils.isEmpty(agentIds)) {
            adviserNameMap = adviserConsr.getNames(adviserIds);
        }
        if (!ListUtils.isEmpty(requestIds)){
            requestReplyDTOS = buyBookRequestReplyDao.getListByIds(requestIds);
        }
        for (BuyBookRequestDTO buyBookRequestDTO : recordList) {
            if (null == buyBookRequestDTO) {
                continue;
            }
            if (MapUtils.isNotEmpty(bookDtoMap) && null != bookDtoMap.get(buyBookRequestDTO.getBookId())) {
                buyBookRequestDTO.setBookName(bookDtoMap.get(buyBookRequestDTO.getBookId()).getBookName());
                buyBookRequestDTO.setCoverImg(bookDtoMap.get(buyBookRequestDTO.getBookId()).getCoverImg());
                buyBookRequestDTO.setIsbn(bookDtoMap.get(buyBookRequestDTO.getBookId()).getIsbn());
            }
            if (MapUtils.isNotEmpty(agentNameMap) && null != agentNameMap.get(buyBookRequestDTO.getAgentId())) {
                buyBookRequestDTO.setAgentName(agentNameMap.get(buyBookRequestDTO.getAgentId()));
            }
            if (MapUtils.isNotEmpty(adviserNameMap) && null != adviserNameMap.get(buyBookRequestDTO.getAdviserId())) {
                buyBookRequestDTO.setAdviserName(adviserNameMap.get(buyBookRequestDTO.getAdviserId()));
            }
            //填充回复
            if ( !ListUtils.isEmpty(requestReplyDTOS) ){
                Long requestId = buyBookRequestDTO.getId();
                List<BuyBookRequestReplyDTO> replyList = new ArrayList<>();
                for (BuyBookRequestReplyDTO requestReplyDTO : requestReplyDTOS) {
                    if (Objects.equals(requestReplyDTO.getRequestId(),requestId)){
                        replyList.add(requestReplyDTO);
                    }
                }
                buyBookRequestDTO.setReplyList(replyList == null? new ArrayList<>() : replyList);
            }
        }


    }

    @Override
    @ParamLog("新增")
    public Long insert(BuyBookRequest buyBookRequest,Long officialAccountId) {
        Long wechatUserId = buyBookRequest.getWechatUserId();
        //根据公众号Id与微信Id，获取小程序openId和用户昵称。
        List<Long> idList = new ArrayList<>();
        idList.add(wechatUserId);
        List<BuyBookProcessingDataDTO> processingData = readerConsr.getProcessingData(idList);
        if (null == processingData && processingData.size() == 0 ){
            LOGGER.error("[BuyBookRequestBizImpl.insert]: 获取openId和用户昵称失败 wechatUserId:{}",wechatUserId);
            return null;
        }
        //只会返回一个，列表中只有一个元素
        for (BuyBookProcessingDataDTO processingDatum : processingData) {
            buyBookRequest.setMiniOpenId(processingDatum.getMiniOpenId());
            buyBookRequest.setNickName(processingDatum.getNickName());
        }
        buyBookRequest.setReplyState(0);
        buyBookRequest.setIsDelete(0);
        buyBookRequestDao.insert(buyBookRequest);
        return buyBookRequest.getId();
    }

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

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

    @Override
    public BuyBookRequetUserDTO getUserCount(Integer topCount) {
        List<BuyBookRequest> buyBookRequests =   buyBookRequestDao.getUserCount();
        BuyBookRequetUserDTO buyBookRequetUserDTO = new BuyBookRequetUserDTO();
        List<String> headUrls = new ArrayList<>();
        if (ListUtils.isEmpty(buyBookRequests)) {
            buyBookRequetUserDTO.setUserCount(0);
        } else {
            buyBookRequetUserDTO.setUserCount(buyBookRequests.size());
            List<Long> wechatUserIds = new ArrayList<>();
            wechatUserIds = buyBookRequests.stream().map(e -> e.getWechatUserId()).distinct().collect(Collectors.toList());
            if (!ListUtils.isEmpty(wechatUserIds)) {
                if (wechatUserIds.size() > topCount) {
                    wechatUserIds =  wechatUserIds.subList(0, topCount);
                }
                Map<Long, WechatUser> userList = readerConsr.getUserList(wechatUserIds);
                if (MapUtils.isNotEmpty(userList)) {
                    headUrls = userList.values().stream().map(e -> e.getWechatUserHeadurl()).collect(Collectors.toList());
                }
            }
        }
        buyBookRequetUserDTO.setUserCount(buyBookRequetUserDTO.getUserCount() < 3000 ? 300 + buyBookRequetUserDTO.getUserCount() : buyBookRequetUserDTO.getUserCount());
        buyBookRequetUserDTO.setWechatUserHeadUrl(headUrls);
        return buyBookRequetUserDTO;
    }

    @Override
    public void exportRequestList(Long agentId, Integer currentPage, Integer numPerPage, Long partyId) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
        PageBeanNew pageBeanNew = this.getList(currentPage, numPerPage, agentId);
        List<BuyBookRequestDTO> recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return ;
        }
        // 字段名
        String[] rowsName = {"书籍id", "书籍名称", "编辑名称", "出版社名称", "用户姓名", "手机号码", "收货地址", "申请时间", "小程序id", "微信昵称", "小程序openid"};
        List<Object[]> dataList = new ArrayList<>();
        Object[] objs;
        for (int i = 0; i < recordList.size(); i++) {
            BuyBookRequestDTO buyBookRequestDTO = recordList.get(i);
            objs = new Object[rowsName.length];
            objs[0] = buyBookRequestDTO.getBookId();
            objs[1] = buyBookRequestDTO.getBookName();
            objs[2] = buyBookRequestDTO.getAdviserName();
            objs[3] = buyBookRequestDTO.getAgentName();
            objs[4] = buyBookRequestDTO.getUserName();
            objs[5] = buyBookRequestDTO.getPhone();
            objs[6] = buyBookRequestDTO.getAddress();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            objs[7] = null == buyBookRequestDTO.getCreateTime() ? "": simpleDateFormat.format(buyBookRequestDTO.getCreateTime());
            objs[8] = buyBookRequestDTO.getMiniWechatUserId();
            objs[9] = buyBookRequestDTO.getNickName();
            objs[10] = buyBookRequestDTO.getMiniOpenId();
            dataList.add(objs);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String fileName ="研发-购书申请表导出-" + simpleDateFormat.format(new Date());

        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        if (!StringUtil.isEmpty(fileUrl)) {
            JSONObject content = new JSONObject();
            content.put("commitTime", DateUtils.formatDate(new Date()));
            content.put("type", "购书申请表导出");
            messageConsr.sendLetter(partyId, partyId, content.toJSONString(), SystemCode.pcloud.code, "book_download", fileUrl, fileName);
        }
    });
    }

    @Override
    public PageBeanNew getByState(Integer currentPage,Integer numPerPage,Long wechatUserId, Integer state,Integer requestEnv) {
        if ( null == wechatUserId ){
            LOGGER.warn("[BuyBookRequestBizImpl.getByState] 请求参数为空");
            return new PageBeanNew();
        }
        Map<String,Object> param = new HashMap<>();
        param.put("replyState",state);
        param.put("isDelete",0);
        param.put("requestEvn",requestEnv);
        if (YesOrNoEnums.YES.getValue().equals(requestEnv)) {
            param.put("wechatUserId",wechatUserId);
        } else {
            param.put("miniWechatUserId",wechatUserId);
        }
        PageBeanNew pageBeanNew = buyBookRequestDao.getRequestByWechatUserIdAndState(currentPage, numPerPage, param);
        List<BuyBookRequestDTO> recordList = pageBeanNew.getRecordList();
        //填充其他消息
        fillAgentInfo(recordList);
        return pageBeanNew;
    }

    @Override
    public void fakeDelete(Long requestId) {
        if (requestId == null) {
            LOGGER.warn("[BuyBookRequestBizImpl.fakeDelete]记录假删除失败，记录Id为空");
            return;
        }
        BuyBookRequest buyBookRequest = new BuyBookRequest();
        buyBookRequest.setId(requestId);
        buyBookRequest.setIsDelete(1);
        buyBookRequest.setUpdateTime(new Date());
        buyBookRequestDao.update(buyBookRequest);
    }

    @Override
    public List<Long> listIdsByWeChatUserId(Long wechatUserId) {
        if (null == wechatUserId){
            throw BizException.PARAM_IS_NULL;
        }
        return buyBookRequestDao.listIdsByWeChatUserId(wechatUserId);
    }

    @Override
    public List<Long> listAllWeChatUserId() {
        return buyBookRequestDao.listAllWeChatUserId();
    }

    @Override
    public void processingData(Integer open) {
        List<Long> weChatUserIds = listAllWeChatUserId();
        if (ListUtils.isEmpty(weChatUserIds)){
            LOGGER.error("[BuyBookRequestBiz.processingData] 处理数据失败，获取wechatUserId列表失败");
            return;
        }
        List<BuyBookProcessingDataDTO> processingData = readerConsr.getProcessingData(weChatUserIds);
        for (BuyBookProcessingDataDTO processingDatum : processingData) {
            Map<String, Object> param = new HashMap<>();
            param.put("wechatUserId", processingDatum.getWechatUserId());
            param.put("miniWechatUserId", processingDatum.getMiniWechatUserId());
            param.put("miniOpenId", processingDatum.getMiniOpenId());
            param.put("nickName", processingDatum.getNickName());
            if (open == 1) {
                param.put("isDelete", "0");
                param.put("replyState", "0");
            }
            buyBookRequestDao.update2ProcessingData(param);
        }
    }


}