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

import com.alibaba.fastjson.JSON;
import com.pcloud.appcenter.app.dto.AppDto;
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.feedback.FeedbackConsr;
import com.pcloud.book.consumer.shareimage.ShareImageConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.custom.biz.CustomPlanBiz;
import com.pcloud.book.custom.entity.CustomPlan;
import com.pcloud.book.custom.entity.CustomPlanModule;
import com.pcloud.book.custom.entity.CustomPlanModuleSuggestion;
import com.pcloud.book.custom.enums.PlanModuleTypeEnum;
import com.pcloud.book.custom.enums.PlanUseStateEnum;
import com.pcloud.book.custom.mapper.CustomPlanMapper;
import com.pcloud.book.custom.mapper.CustomPlanModuleMapper;
import com.pcloud.book.custom.mapper.CustomPlanModuleSuggestionMapper;
import com.pcloud.book.custom.vo.AddCustomPlan4UserVO;
import com.pcloud.book.custom.vo.AddSuggestionListVO;
import com.pcloud.book.custom.vo.AddSuggestionVO;
import com.pcloud.book.custom.vo.CustomPlanModuleVO;
import com.pcloud.book.custom.vo.CustomPlanPaperVO;
import com.pcloud.book.custom.vo.EditCustomPlanModuleVO;
import com.pcloud.book.custom.vo.ModuleSuggestionVO;
import com.pcloud.book.custom.vo.SuggestionListVO;
import com.pcloud.book.custom.vo.ToPdfVO;
import com.pcloud.book.group.biz.WeixinQrcodeBiz;
import com.pcloud.book.group.tools.Kit;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.UUIDUitl;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.feedback.paper.dto.PaperDto;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.group.dto.GroupUserDTO;
import com.sdk.wxgroup.SendMessageTypeEnum;
import com.sdk.wxgroup.SendTextMessageVO;
import com.sdk.wxgroup.WxGroupSDK;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

@Component
public class CustomPlanBizImpl implements CustomPlanBiz {

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

    @Autowired
    private CustomPlanMapper customPlanMapper;
    @Autowired
    private CustomPlanModuleMapper customPlanModuleMapper;
    @Value("${wechat.group.link.prefix}")
    private String wechatLinkPrefix;
    @Autowired
    private FeedbackConsr feedbackConsr;
    @Autowired
    private ShareImageConsr shareImageConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private CustomPlanModuleSuggestionMapper customPlanModuleSuggestionMapper;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeBiz weixinQrcodeBiz;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createCustomPlan(CustomPlan customPlan) {
        customPlanMapper.insert(customPlan);
        this.fillCustomPlanInfo(customPlan);
        return customPlan.getId();
    }

    private void fillCustomPlanInfo(CustomPlan customPlan) {
        Integer planId = customPlan.getId();
        customPlan.setPlanNumber(StringUtil.getByObj(100000 + planId));
        String h5Url = wechatLinkPrefix + "/personalCenter/madeProject?planId=" + planId;
        String previewQrcodeUrl = QrcodeUtils.create(UrlUtils.getShortUrl4Own(h5Url));
        customPlan.setH5Url(h5Url);
        customPlan.setPreviewQrcodeUrl(previewQrcodeUrl);
        customPlan.setUseState(PlanUseStateEnum.NO.value);
        customPlanMapper.update(customPlan);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void copyCustomPlan(Integer planId) {
        CustomPlan customPlan = customPlanMapper.getById(planId);
        CustomPlan newCustomPlan = new CustomPlan();
        BeanUtils.copyProperties(customPlan, newCustomPlan);
        customPlanMapper.insert(newCustomPlan);
        this.fillCustomPlanInfo(newCustomPlan);
        //复制方案模块
        Integer copyPlanId = newCustomPlan.getId();
        List<CustomPlanModuleVO> planModuleVOList = this.getCustomPlanModule(planId);
        this.addPlanModule(copyPlanId, planModuleVOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCustomPlan(CustomPlan customPlan) {
        customPlanMapper.update(customPlan);
    }

    @Override
    public CustomPlan getCustomPlanById(Integer planId) {
        return customPlanMapper.getById(planId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCustomPlanById(Integer planId) {
        customPlanMapper.deleteById(planId);
    }

    @Override
    public PageBeanNew<CustomPlan> listCustomPlanByPage(Integer currentPage, Integer numPerPage, String content, Integer useState, Integer hasPdf) {
        int count = customPlanMapper.getCustomPlanCount(content, useState, hasPdf);
        if(count <= 0) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        List<CustomPlan> customPlanList = customPlanMapper.listCustomPlanByPage(currentPage * numPerPage, numPerPage, content, useState, hasPdf);
        return new PageBeanNew<>(currentPage, numPerPage, count, customPlanList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editCustomPlanModule(EditCustomPlanModuleVO editCustomPlanModuleVO) {
        Integer planId = editCustomPlanModuleVO.getPlanId();
        CustomPlan plan = customPlanMapper.getById(planId);
        if(plan == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "方案不存在！");
        }
        customPlanModuleMapper.deleteByPlanId(planId);
        this.addPlanModule(planId, editCustomPlanModuleVO.getPlanModuleVOS());
        //异步生成PDF，并更新数据库
        String htmlUrl= plan.getH5Url();
        if(!StringUtil.isEmpty(htmlUrl)) {
            ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
                try {
                    Thread.sleep(2000);

                    ToPdfVO toPdfVO = new ToPdfVO();
                    toPdfVO.setUrl(htmlUrl);
                    toPdfVO.setContainer("#App");
                    toPdfVO.setFileName(UUIDUitl.generateMixString(10));
                    LOGGER.info("=========toPdfVO========Start" + toPdfVO.toString());
                    String resultStr = Kit.post("https://puppeteer.5rs.me/generator/imgGenerator/generatorPdfByUrl", JSON.toJSONString(toPdfVO));
                    LOGGER.info("=========resultStr========End" + resultStr);
                    Map map = JSON.parseObject(resultStr, Map.class);
                    String pdfUrl = (String) ((Map) map.get("data")).get("url");
                    LOGGER.info("=========pdfUrl========" + pdfUrl);
                    if(pdfUrl != null) {
                        CustomPlan customPlan = new CustomPlan();
                        customPlan.setId(planId);
                        customPlan.setPdfUrl(pdfUrl);
                        customPlanMapper.updatePdfUrl(customPlan);
                    }
                } catch (Exception e) {
                    LOGGER.error("转PDF失败", e);
                }

            });
        }

    }

    private void addPlanModule(Integer planId, List<CustomPlanModuleVO> planModuleVOList) {
        for(CustomPlanModuleVO parentPlanModuleVO : planModuleVOList) {
            CustomPlanModule parentPlanModule = new CustomPlanModule();
            BeanUtils.copyProperties(parentPlanModuleVO, parentPlanModule);
            parentPlanModule.setParentId(0);
            parentPlanModule.setPlanId(planId);
            customPlanModuleMapper.insert(parentPlanModule);
            if(PlanModuleTypeEnum.GROUP.value.equals(parentPlanModuleVO.getModuleType())
                    && !CollectionUtils.isEmpty(parentPlanModuleVO.getCustomPlanModuleVOList())) {
                for(CustomPlanModuleVO planModuleVO : parentPlanModuleVO.getCustomPlanModuleVOList()) {
                    CustomPlanModule planModule = new CustomPlanModule();
                    BeanUtils.copyProperties(planModuleVO, planModule);
                    planModule.setParentId(parentPlanModule.getId());
                    planModule.setPlanId(planId);
                    customPlanModuleMapper.insert(planModule);
                }
            }
        }
    }

    @Override
    public List<CustomPlanModuleVO> getCustomPlanModule(Integer planId) {
        List<CustomPlanModuleVO> parentPlanModuleVOList = customPlanModuleMapper.getCustomPlanModuleByPlanId(planId, 0);
        for(CustomPlanModuleVO planModuleVO : parentPlanModuleVOList) {
            if(PlanModuleTypeEnum.GROUP.value.equals(planModuleVO.getModuleType())) {
                List<CustomPlanModuleVO> planModuleVOList = customPlanModuleMapper.getCustomPlanModuleByPlanId(planId, planModuleVO.getId());
                if(!CollectionUtils.isEmpty(planModuleVOList)) {
                    planModuleVO.setCustomPlanModuleVOList(planModuleVOList);
                }
            }
        }
        return parentPlanModuleVOList;
    }

    @Override
    public PageBeanNew<CustomPlanPaperVO> listPlanPaperByPage(Integer currentPage, Integer numPerPage, Integer paperState, String content) {
        List<Long> paperIds = new ArrayList<>();
        if(paperState != null) {
            paperIds = feedbackConsr.getPaperIdsByState(paperState);
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("paperIds", paperIds);
        paramMap.put("content", content);
        int count = customPlanMapper.getPlanPaperCount(paramMap);
        if(count <= 0) {
            return new PageBeanNew<>(currentPage, numPerPage, new ArrayList<>());
        }
        paramMap.put("pageNum", currentPage * numPerPage);
        paramMap.put("numPerPage", numPerPage);
        List<CustomPlanPaperVO> planPaperVOList = customPlanMapper.listPlanPaperByPage(paramMap);
        List<Long> resultPaperIds = new ArrayList<>();
        for(CustomPlanPaperVO planPaperVO : planPaperVOList) {
            resultPaperIds.add(planPaperVO.getPaperId().longValue());
        }
        Map<Long, PaperDto> paperDtoMap = feedbackConsr.getPaperListByIds(resultPaperIds);
        for(CustomPlanPaperVO planPaperVO : planPaperVOList) {
            if(paperDtoMap.containsKey(planPaperVO.getPaperId().longValue())) {
                PaperDto paperDto = paperDtoMap.get(planPaperVO.getPaperId().longValue());
                if(paperDto != null) {
                    planPaperVO.setPaperState(paperDto.getState());
                    planPaperVO.setPaperUserCount(paperDto.getUsefulCount());
                }
            }
        }
        return new PageBeanNew<>(currentPage, numPerPage, count, planPaperVOList);
    }

    @Override
    public Map<String, Object> getShortLinkUrl(Long appId, Long productId, String linkUrl) {
        if(appId == null && productId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "作品ID或应用ID不能为空！");
        }
        if(appId != null && productId != null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "作品ID或应用ID不能同时存在！");
        }
        if(StringUtil.isEmpty(linkUrl)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "链接URL不能为空！");
        }
        Map<String, Object> resultMap = new HashMap<>();
        if(appId != null) {
            resultMap.put("appId", appId);
            AppDto appDto = appConsr.getBaseById(appId);
            if (appDto != null) {
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                String shortUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, linkUrl);
                resultMap.put("shortUrl", UrlUtils.getShortUrl4Own(shortUrl));
            }

        }
        if(productId != null) {
            resultMap.put("productId", productId);
            resultMap.put("shortUrl", UrlUtils.getShortUrl4Own(linkUrl));
        }
        return resultMap;
    }

    @Override
    public PageBeanNew<SuggestionListVO> listSuggestion4Plan(Integer currentPage, Integer numPerPage, String startTime,
                                                             String endTime, String search, Integer planId) {
        List<SuggestionListVO> list = new ArrayList<>();
        List<String> wxIdList = null;
        if (!StringUtil.isEmpty(search)) {
            wxIdList = wechatGroupConsr.getByUserQuery(search);
            if (ListUtils.isEmpty(wxIdList)) {
                return new PageBeanNew<>(currentPage, numPerPage, list);
            }
        }
        Integer count = customPlanModuleSuggestionMapper.getSuggestionCount(startTime, endTime, wxIdList, planId);
        if (count <= 0) {
            return new PageBeanNew<>(currentPage, numPerPage, list);
        }
        list = customPlanModuleSuggestionMapper.listSuggestion4Plan(currentPage * numPerPage, numPerPage, startTime, endTime, wxIdList, planId);
        List<String> userIds = list.stream().map(SuggestionListVO::getWxId).distinct().collect(Collectors.toList());
        Map<String, GroupUserDTO> userDTOMap = wechatGroupConsr.mapWxUserInfoByWxIdList(userIds);
        list.forEach(suggestionListVO -> {
            //封装用户信息
            String wxId = suggestionListVO.getWxId();
            if (userDTOMap != null && userDTOMap.get(wxId) != null) {
                GroupUserDTO groupUserDTO = userDTOMap.get(wxId);
                suggestionListVO.setNickName(groupUserDTO.getNickName());
                suggestionListVO.setHeadUrl(groupUserDTO.getHeadPic());
                suggestionListVO.setSex(groupUserDTO.getSex());
            }
        });
        return new PageBeanNew<>(currentPage, numPerPage, count, list);
    }

    @Override
    public List<ModuleSuggestionVO> getSuggestionInfo(Integer batchId, Integer planId) {
        return customPlanModuleSuggestionMapper.getSuggestionInfo(batchId, planId);
    }

    @Override
    public Integer addSuggestion4Module(AddSuggestionVO addSuggestionVO) {
        String wxId = addSuggestionVO.getWxId();
        Integer planId = addSuggestionVO.getPlanId();
        int maxBatchId = customPlanModuleSuggestionMapper.getMaxBatchId();
        List<AddSuggestionListVO> suggestionList = addSuggestionVO.getSuggestionList();
        List<CustomPlanModuleSuggestion> list = new ArrayList<>();
        suggestionList.forEach(addSuggestionListVO -> {
            if (null == addSuggestionListVO.getSuggestionLevel()) {
                addSuggestionListVO.setSuggestionLevel(0);
                addSuggestionListVO.setSuggestion(null);
            }
            CustomPlanModuleSuggestion suggestion = CustomPlanModuleSuggestion.builder().wxId(wxId).planId(planId)
                    .suggestionLevel(addSuggestionListVO.getSuggestionLevel()).suggestion(addSuggestionListVO.getSuggestion())
                    .batchId(maxBatchId + 1).moduleId(addSuggestionListVO.getModuleId()).build();
            list.add(suggestion);
        });
        customPlanModuleSuggestionMapper.batchInsert(list);
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            CustomPlan customPlan = customPlanMapper.getById(planId);
            if (!StringUtil.isEmpty(customPlan.getConfirmFeedbackReply()) && addSuggestionVO.getRobotWxId() != null) {
                //发送return消息
                String robotWxId = addSuggestionVO.getRobotWxId();
                GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(robotWxId);
                String ip = weixinQrcodeBiz.getRobotIpByGeneration(groupRobotDTO.getVersion());
                SendTextMessageVO sendTextMessageVO = new SendTextMessageVO();
                sendTextMessageVO.setContent(customPlan.getConfirmFeedbackReply());
                sendTextMessageVO.setCode(SendMessageTypeEnum.SELF.getCode());
                sendTextMessageVO.setWxId(robotWxId);
                sendTextMessageVO.setAltId(robotWxId);
                sendTextMessageVO.setWxGroupId(wxId);
                sendTextMessageVO.setIp(ip);
                WxGroupSDK.sendTextMessage(sendTextMessageVO);
            }
        });
        return maxBatchId + 1;
    }

    @Override
    public Integer addCustomPlan4User(AddCustomPlan4UserVO addCustomPlan4UserVO) {
        return customPlanModuleSuggestionMapper.addCustomPlan4User(addCustomPlan4UserVO);
    }
}
