package cn.newfeifan.mall.module.trade.utils.wechat;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import cn.newfeifan.mall.module.member.service.user.MemberUserService;
import cn.newfeifan.mall.module.system.dal.dataobject.config.SystemConfigDO;
import cn.newfeifan.mall.module.system.dal.dataobject.wechatmsgtemplate.WechatMsgTemplateDO;
import cn.newfeifan.mall.module.system.service.config.SystemConfigService;
import cn.newfeifan.mall.module.system.service.permission.PermissionService;
import cn.newfeifan.mall.module.system.service.social.SocialUserService;
import cn.newfeifan.mall.module.system.service.wechatmsgtemplate.WechatMsgTemplateService;
import cn.newfeifan.mall.module.trade.controller.admin.messagelog.vo.MessageLogSaveReqVO;
import cn.newfeifan.mall.module.trade.enums.wxmessage.WcChatMessageTemplateIdEnum;
import cn.newfeifan.mall.module.trade.service.messagelog.MessageLogService;
import com.google.gson.JsonObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import static cn.newfeifan.mall.module.system.constant.SystemConstants.WX_TICK_KEY_APPID;

/**
 * 发送微信消息的工具类
 */
@Data
@Component
@Slf4j
public class WcChatMessageUtils {

    @Value("${wx.mp.app-id}")
    private String appid;
    @Value("${wx.mp.secret}")
    private String Wxgsecret;

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private WechatMsgTemplateService wechatMsgTemplateService;
    @Resource
    private SocialUserService socialUserService;
    @Resource
    private MessageLogService messageLogService;
    @Resource
    private SystemConfigService configService;
    @Resource
    private PermissionService permissionService;
    @Resource
    private MemberUserService memberUserService;

    /**
     * 获取微信的accessToken
     *
     * @return accessToken
     */
    public String getAccessToken() {

        String accessToken = stringRedisTemplate.opsForValue().get(WX_TICK_KEY_APPID);

        if (StrUtil.isEmpty(accessToken)) {
            // 服务号的appid以及秘钥
            String requestUrl = StrUtil.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}", appid, Wxgsecret);
            String returnMsg = HttpUtil.get(requestUrl);
            cn.hutool.json.JSONObject responseJsonObject = JSONUtil.parseObj(returnMsg);
            if (ObjectUtil.isNull(responseJsonObject)) try {
                throw new Exception("响应异常:获取信息为空!");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            accessToken = responseJsonObject.getStr("access_token");

            //微信的accessToken的失效时间是两个小时,这里改为一小时五十五分钟,怕双方的时间误差导致accessToken失效
            long expireTime = 60 * 60 + 55 * 60; // 1小时55分钟转换为秒
            stringRedisTemplate.opsForValue().set(WX_TICK_KEY_APPID, accessToken, expireTime, java.util.concurrent.TimeUnit.SECONDS);
        }

        log.info("===========Access_token:{}", accessToken);

        return accessToken;
    }

    /**
     * 发送微信消息
     *
     * @param userId              接口消息的用户id
     * @param data                模板参数
     * @param wechatMsgTemplateId 自定义的消息模板id
     */
    private void sendWxgMessage(Long userId, JsonObject data, String wechatMsgTemplateId, Long systemUserId, Long memberUserId, Long objectId) {

        // 组装消息内容
        String userOpenId;
        if (wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK2.getTemplateId()) ||
                wechatMsgTemplateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY2.getTemplateId())) {
            userOpenId = getOpenIdBySysTemUserId(systemUserId);
        } else {
            userOpenId = getOpenId(userId);
        }

        //如果用户没有绑定微信,则不发送消息
        if (userOpenId == null) {
            return;
        }

        String templateId = getTemplateId(wechatMsgTemplateId).getWechatMsgTemplateId(); // 模板id
        String url = getDoMain(wechatMsgTemplateId, objectId, memberUserId);       // 跳转路径(小程序之外)
        String client_msg_id = UUID.randomUUID().toString();  // 防重入id


        WeChatTemplateMessage message = new WeChatTemplateMessage();
        message.setTouser(userOpenId);
        message.setTemplate_id(templateId);
        message.setUrl(url);
        message.setClient_msg_id(client_msg_id);
        message.setData(data);

        sendWecChatMessage(userId, wechatMsgTemplateId, systemUserId, memberUserId, objectId, message, userOpenId ,1);
    }

    private void sendWecChatMessage(Long userId, String wechatMsgTemplateId, Long systemUserId, Long memberUserId, Long objectId, WeChatTemplateMessage message, String userOpenId, int maxRetries) {
        // 发送消息
        String returnMsg = HttpUtil.post(StrUtil.format("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={}", getAccessToken()), message.toString());
        cn.hutool.json.JSONObject jsonObject2 = JSONUtil.parseObj(returnMsg);
        String errmsg = jsonObject2.getStr("errmsg");

        //记录发送的微信消息
        MessageLogSaveReqVO messageLogSaveReqVO = MessageLogSaveReqVO.builder()
                .openid(userOpenId)
                .memberUserId(userId)
                .systemUserId(systemUserId)
                .memberUserId(memberUserId)
                .wechatMsgTemplateId(Long.valueOf(wechatMsgTemplateId))
                .wechatMsgTemplateParams(message.toString())
                .objectId(objectId)
                .sendStatus(true)
                .sendTime(LocalDateTime.now())
                .responseResult(returnMsg)
                .build();
        if (!StrUtil.equals("ok", errmsg)) {
            log.info("=====消息发送失败,原因:{}", errmsg);
            messageLogSaveReqVO.setSendStatus(false);
        }

        messageLogService.createMessageLog(messageLogSaveReqVO);

        // 如果微信的accessToken失效,则重新获取,最多重试3次
        if (jsonObject2.getStr("errcode").equals("40001") && maxRetries <= 3) {
            maxRetries++;
            stringRedisTemplate.delete(WX_TICK_KEY_APPID);
            sendWecChatMessage(userId, wechatMsgTemplateId, systemUserId, memberUserId, objectId, message, userOpenId, maxRetries);
        }
    }

    /**
     * 获取待发货模板参数
     *
     * @return 待发货模板参数
     */
    public JsonObject getTemplateData(List<String> dataParams, List<String> params) {

        JsonObject data = new JsonObject();

        // 添加字段及其值
        for (int i = 0; i < Math.min(params.size(), dataParams.size()); i++) {
            String paramName = dataParams.get(i);
            String paramValue = params.get(i);

            JsonObject obj = new JsonObject();
            obj.addProperty("value", paramValue);
            data.add(paramName, obj);
        }

        return data;
    }

    /**
     * 发送微信信息
     *
     * @param userId       用户id
     * @param templateId   自定义消息模板id
     * @param params       消息参数
     * @param systemUserId 系统用户id
     * @param memberUserId 会员用户id
     * @param objectId     对象id
     */
    public void sendWcChatMessage(Long userId, String templateId, List<String> params, Long systemUserId, Long memberUserId, Long objectId) {
        WechatMsgTemplateDO template = getTemplateId(templateId);
        String messageTemplateParameters = template.getMessageTemplateParameters();

        // 去除首尾的括号，并去除空格
        messageTemplateParameters = messageTemplateParameters.substring(1, messageTemplateParameters.length() - 1).trim();

        // 使用逗号分割字符串，并去除空格
        String[] parts = messageTemplateParameters.split(",\\s*");

        // 创建集合并将数组转换为集合
        List<String> dataParams = Arrays.asList(parts);
        JsonObject templateData = getTemplateData(dataParams, params);

        // 发送微信消息
        sendWxgMessage(userId, templateData, templateId, systemUserId, memberUserId, objectId);
    }

    /**
     * 获取不同端域名(不同的端的代码略有不同)
     *
     * @param templateId 自定义模板id
     * @return 域名加路径
     */
    public String getDoMain(String templateId, Long objectId, Long memberUserId) {
        SystemConfigDO redisConfig = configService.getRedisConfig();
        String username = memberUserService.getUsernameByUserId(memberUserId);
        if (templateId.equals(WcChatMessageTemplateIdEnum.ORDER_DELIVERY2.getTemplateId())) {
            //订单已发货
            return redisConfig.getMallDomain() + "/#/pages/order/detail?id=" + objectId + "&username=" + username;
        } else if (templateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_CHECK2.getTemplateId())) {
            //售后订单审核完成
            return redisConfig.getMallDomain() + "/#/pages/order/aftersale/detail?id=" + objectId + "&username=" + username;
        } else if (templateId.equals(WcChatMessageTemplateIdEnum.AFTER_SALE_NO_CHECK2.getTemplateId())) {
            //售后订单待审核
            return redisConfig.getMerchantDomain() + "/after-sale";
        } else if (templateId.equals(WcChatMessageTemplateIdEnum.ORDER_NO_DELIVERY2.getTemplateId())) {
            //订单待发货
            return redisConfig.getMerchantDomain() + "/order";
        }
        return null;
    }

    /**
     * 通过自己定义消息模板id获取微信第三方模板
     *
     * @param wechatMsgTemplateId 自己定义消息模板id
     * @return 微信第三方模板
     */
    private WechatMsgTemplateDO getTemplateId(String wechatMsgTemplateId) {
        return wechatMsgTemplateService.getWechatSsgTemplate(Long.valueOf(wechatMsgTemplateId));
    }

    private String getOpenId(Long userId) {
        return socialUserService.getOpenIdByUserId(userId);
    }

    private String getOpenIdBySysTemUserId(Long systemUserId) {
        Long memberUserId = memberUserService.getUserIdBySystemUserId(systemUserId);
        if (memberUserId == null) {
            return null;
        }
        return getOpenId(memberUserId);
    }
}
