package com.yiqi.crm.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yiqi.common.config.CompositeWxMaService;
import com.yiqi.common.utils.StringUtils;
import com.yiqi.common.utils.file.ImageUtils;
import com.yiqi.crm.domain.CrmWeChatSetting;
import com.yiqi.crm.handle.EventMsgHandler;
import com.yiqi.crm.handle.MsgHandler;
import com.yiqi.crm.handle.SubscribeHandler;
import com.yiqi.crm.handle.TextMsgHandler;
import com.yiqi.crm.mapper.CrmWechatSettingMapper;
import com.yiqi.crm.service.CrmWechatSettingService;
import com.yiqi.crm.service.IWxReplyService;
import lombok.extern.java.Log;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.WxMpMaterial;
import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult;
import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import me.chanjar.weixin.common.api.WxConsts;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.Objects;

/**
 * @author xiaohei
 * @date 2023/7/18
 */
@Log
@Service
public class CrmWechatSettingServiceImpl extends ServiceImpl<CrmWechatSettingMapper, CrmWeChatSetting> implements CrmWechatSettingService {

    @Autowired
    CompositeWxMaService compositeWxMaService;

    @Autowired
    private IWxReplyService wxReplyService;

    @Override
    public String getOutMsg(String requestBody, String signature, String encType, String timestamp, String nonce, String msgSignature) {
        if (!compositeWxMaService.getPublic().checkSignature(timestamp, nonce, signature)) {
            throw new IllegalArgumentException("非法请求，可能属于伪造的请求！");
        }
        String out = null;
        if (encType == null) {
            // 明文传输的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(requestBody);
            System.out.println("inMessage =  " + inMessage);
            WxMpXmlOutMessage outMessage = this.getMsgByRoute(inMessage);
            if (outMessage == null) {
                return "";
            }
            out = outMessage.toXml();
        } else if ("aes".equalsIgnoreCase(encType)) {
            // aes加密的消息
            WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(requestBody, compositeWxMaService.getPublic().getWxMpConfigStorage(),
                    timestamp, nonce, msgSignature);
            log.info("\n消息解密后内容为：\n{} " + inMessage.toString());
            WxMpXmlOutMessage outMessage = this.getMsgByRoute(inMessage);
            if (outMessage == null) {
                return "";
            }
            out = outMessage.toEncryptedXml(compositeWxMaService.getPublic().getWxMpConfigStorage());
        }
        log.info("\n组装回复信息：" + out);
        return out;
    }

    private WxMpXmlOutMessage getMsgByRoute(WxMpXmlMessage message) {
        try {
            // 创建一个路由，通过XmlMsgType分类处理
            final WxMpMessageRouter newRouter = new WxMpMessageRouter(compositeWxMaService.getPublic());
            // 自定义菜单事件
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.CLICK).handler(EventMsgHandler.build(wxReplyService)).end();

            //点击菜单链接事件 不做处理
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.VIEW).handler(null).end();

            // 关注事件
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.SUBSCRIBE).handler(SubscribeHandler.build(wxReplyService)).end();

            // 处理文本回复
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.TEXT).handler(TextMsgHandler.build(wxReplyService)).end();

            // 上报地理位置事件 不做处理
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT).event(WxConsts.EventType.LOCATION_SELECT).handler(null).end();

            // 接收地理位置消息 不做处理
            newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION).handler(null).end();

            // 不满足上面类型，走这个兜底处理
            newRouter.rule().async(false).handler(MsgHandler.build(wxReplyService)).end();
            return newRouter.route(message);
        } catch (Exception e) {
            log.info("路由消息时出现异常！" + e);
        }
        return null;
    }

    /**
     * 前端上传图片到微信素材管理
     * @param file
     * @param type
     * @return
     * @throws IOException
     */
    @Override
    public String uploadMaterial(MultipartFile file, String type) throws IOException {
        WxMpMaterial material = new WxMpMaterial();
        WxMpMaterialUploadResult result;
        InputStream ins = file.getInputStream();
        File file1 = new File(Objects.requireNonNull(file.getOriginalFilename()));
        OutputStream stream = new FileOutputStream(file1);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
            stream.write(buffer, 0, bytesRead);
        }
        stream.close();
        ins.close();
        material.setFile(file1);
        material.setName(file.getName());
        material.setVideoTitle("");
        material.setVideoIntroduction("");
        try {
            result = compositeWxMaService.getPublic().getMaterialService().materialFileUpload(type, material);
            File del = new File(file1.toURI());
            del.delete();
            result.getMediaId();
            return result.getMediaId();
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        return "";
    }

    @Override
    public String uploadPicToMaterial(String url) throws Exception {
        File file = ImageUtils.download(url);

        WxMpMaterial material = new WxMpMaterial();
        material.setFile(file);
        material.setName(file.getName());
        material.setVideoTitle("");
        material.setVideoIntroduction("");
        WxMpMaterialUploadResult image = compositeWxMaService.getPublic().getMaterialService().materialFileUpload("image", material);
        // 删除本地文件
        File del = new File(file.toURI());
        del.delete();
        return image.getMediaId();
    }

    @Override
    public Boolean deleteMaterial(String mediaId) throws Exception {
        if (StrUtil.isNotEmpty(mediaId)){
            return compositeWxMaService.getPublic().getMaterialService().materialDelete(mediaId);
        }
        return false;
    }


}
