package com.xinelu.mobile.utils;

import com.alibaba.fastjson2.JSON;
import com.xinelu.common.config.WeChatAppletChatConfig;
import com.xinelu.common.config.WeChatOfficialAccountConfig;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.entity.AccessToken;
import com.xinelu.common.entity.MessageValueEntity;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.http.HttpUtils;
import com.xinelu.mobile.domain.TemplateContent;
import com.xinelu.mobile.vo.wechatofficialaccountcallback.PatientVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Description 院后公众号公众方法工具类
 * @Author 纪寒
 * @Date 2024-03-21 13:42:31
 * @Version 1.0
 */
@Slf4j
@Component
public class WeChatOfficialAccountUtils {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private WeChatOfficialAccountConfig weChatOfficialAccountConfig;
    @Resource
    private WeChatAppletChatConfig weChatAppletChatConfig;


    /**
     * 返回成功状态码
     */
    private static final int SUCCESS_CODE = 0;

    /**
     * 获取院后微信公众号accessToken
     *
     * @return 微信公众号的accessToken
     */
    public String getWeChatOfficialAccountAccessToken() {
        String accessToken;
        //公众号
        String accessTokenRedisKey = Constants.WE_CHAT_OFFICIAL_ACCOUNT_ACCESS_TOKEN + "accessToken";
        //从Redis中取出accessToken
        Object object = redisTemplate.opsForValue().get(accessTokenRedisKey);
        if (Objects.isNull(object)) {
            //没有，获取accessToken
            //公众号
            String accessTokenUrl = Constants.WE_CHAT_ACCESS_TOKEN_URL + "&appid=" + weChatOfficialAccountConfig.getOfficialAccountAppId() + "&secret=" + weChatOfficialAccountConfig.getOfficialAccountAppSecret();
            //发送请求
            String result = HttpUtils.sendGet(accessTokenUrl);
            if (StringUtils.isBlank(result)) {
                throw new ServiceException("获取微信公众号accessToken信息失败", 201);
            }
            AccessToken officialAccountAccessToken = JSON.parseObject(result, AccessToken.class);
            if (Objects.isNull(officialAccountAccessToken)) {
                throw new ServiceException("获取微信公众号accessToken信息失败");
            }
            if (Objects.nonNull(officialAccountAccessToken.getErrcode()) && officialAccountAccessToken.getErrcode() != SUCCESS_CODE) {
                throw new ServiceException("获取微信公众号accessToken信息失败，失败信息为：" + officialAccountAccessToken.getErrmsg(), 201);
            }
            if (StringUtils.isBlank(officialAccountAccessToken.getAccessToken())) {
                throw new ServiceException("微信公众号accessToken信息为空");
            }
            accessToken = officialAccountAccessToken.getAccessToken();
            //存入Redis中
            redisTemplate.opsForValue().set(accessTokenRedisKey, accessToken, 3600, TimeUnit.SECONDS);
        } else {
            accessToken = (String) object;
        }
        return accessToken;
    }

    /**
     * 获取院后小程序accessToken
     *
     * @return 微信小程序的accessToken
     */
    public String getWeChatAppletAccessToken() {
        String accessToken;
        //小程序
        String accessTokenRedisKey = Constants.WE_CHAT_APPLET_ACCESS_TOKEN + "accessToken";
        //从Redis中取出accessToken
        Object object = redisTemplate.opsForValue().get(accessTokenRedisKey);
        if (Objects.isNull(object)) {
            //没有，获取accessToken
            //小程序
            String accessTokenUrl = Constants.WE_CHAT_ACCESS_TOKEN_URL + "&appid=" + weChatAppletChatConfig.getAppletId() + "&secret=" + weChatAppletChatConfig.getSecret();
            //发送请求
            String result = HttpUtils.sendGet(accessTokenUrl);
            if (StringUtils.isBlank(result)) {
                throw new ServiceException("获取微信小程序accessToken信息失败", 201);
            }
            AccessToken officialAccountAccessToken = JSON.parseObject(result, AccessToken.class);
            if (Objects.isNull(officialAccountAccessToken)) {
                throw new ServiceException("获取微信小程序accessToken信息失败");
            }
            if (Objects.nonNull(officialAccountAccessToken.getErrcode()) && officialAccountAccessToken.getErrcode() != SUCCESS_CODE) {
                throw new ServiceException("获取微信小程序accessToken信息失败，失败信息为：" + officialAccountAccessToken.getErrmsg(), 201);
            }
            if (StringUtils.isBlank(officialAccountAccessToken.getAccessToken())) {
                throw new ServiceException("微信小程序accessToken信息为空");
            }
            accessToken = officialAccountAccessToken.getAccessToken();
            //存入Redis中
            redisTemplate.opsForValue().set(accessTokenRedisKey, accessToken, 3600, TimeUnit.SECONDS);
        } else {
            accessToken = (String) object;
        }
        return accessToken;
    }

    /**
     * 微信公众号模板消息发送
     */
    public void sendOfficialAccountTemplateMessage() {
        //获取微信公众号的accessToken
        String accessToken = this.getWeChatOfficialAccountAccessToken();
        //定义模板内容，公众模板内容
        Map<String, Object> paramsMap = new LinkedHashMap<>();
        paramsMap.put("touser", "oSwvX5qknp3DrAXfBgFjoMvG6WCI");
        paramsMap.put("template_id", "WUCYtSbH-QFRV_fMcfmn86QLsz1zo881QW7fQNTWOjc");
        //微信小程序跳转内容
        Map<String, Object> miniprogramMap = new LinkedHashMap<>();
        miniprogramMap.put("appid", "wxdc32268eca6b78f9");
        miniprogramMap.put("pagepath", "pages/startup/startup");
        //微信小程序模板data内容
        Map<String, Object> dataMap = new LinkedHashMap<>();
        dataMap.put("phrase7", new MessageValueEntity("泉医陪护"));
        dataMap.put("character_string3", new MessageValueEntity("000026315412331612100"));
        dataMap.put("time6", new MessageValueEntity("2024-03-25 16:21:32"));
        dataMap.put("time10", new MessageValueEntity("2024-03-27 10:00:00"));
        dataMap.put("thing11", new MessageValueEntity("济南市槐荫区首诺城市之光东座22楼E10"));
        paramsMap.put("miniprogram", miniprogramMap);
        paramsMap.put("data", dataMap);
        //拼接请求地址并发送
        String messageUrl = Constants.OFFICIAL_ACCOUNT_TEMPLATE_SEND_URL + accessToken;
        String param = JSON.toJSONString(paramsMap);
        String result = HttpUtils.sendPostJson(messageUrl, param);
        //返回参数映射
        AccessToken errCode = JSON.parseObject(result, AccessToken.class);
        if (Objects.nonNull(errCode) && Objects.nonNull(errCode.getErrcode())) {
            switch (errCode.getErrcode()) {
                case Constants.SUCCESS_ERROR_CODE:
                    log.info("发送消息成功！");
                    break;
                case Constants.INVALID_CREDENTIAL_ACCESS_TOKEN_ISINVALID_OR_NOT_LATEST:
                    log.error("取 access_token 时 AppSecret 错误，或者 access_token 无效！");
                    break;
                case Constants.INVALID_OPENID:
                    log.error("不合法的 OpenId！");
                    break;
                case Constants.INVALID_ACCESS_TOKEN:
                    log.error("合法的 access_token！");
                    break;
                case Constants.INVALID_TEMPLATE_ID:
                    log.error("不合法的 template_id！");
                    break;
                case Constants.ARGUMENT_INVALID:
                    log.error("参数无效！");
                    break;
                case Constants.API_UNAUTHORIZED:
                    log.error("API 功能未授权！");
                    break;
                case Constants.DENY_SUBSCRIPTION:
                    log.error("用户拒接订阅！");
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 微信小程序模板消息发送
     */
    public Integer sendAppletTemplateMessage(PatientVO patientVO) {
        //微信模版组装
        List<TemplateContent> templateContents = new ArrayList<>();
        String thing5 = null;
        String thing1 = null;
        try {
            //判断推送内容格式是否符合
            templateContents = JSON.parseArray(patientVO.getAppletNodeContent(), TemplateContent.class);
            if (CollectionUtils.isNotEmpty(templateContents)) {
                TemplateContent templateContent = templateContents.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getName()) && Objects.nonNull(item.getValue()) && "thing5".equals(item.getName())).findFirst().orElse(new TemplateContent());
                thing5 = templateContent.getValue();
                TemplateContent templateContentTwo = templateContents.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getName()) && Objects.nonNull(item.getValue()) && "thing1".equals(item.getName())).findFirst().orElse(new TemplateContent());
                thing1 = templateContentTwo.getValue();
            }
        } catch (Exception e) {
            thing5 = "每日阅读有助于了解当前情况哦";
            thing1 = "新入院注意事项指导、术前须知";
        }
        //获取微信小程序的accessToken
        String accessToken = this.getWeChatAppletAccessToken();
        //定义模板内容
        Map<String, Object> paramsMap = new LinkedHashMap<>();
        paramsMap.put("touser", patientVO.getOpenId());
        paramsMap.put("template_id", weChatAppletChatConfig.getHealthyPropagandaId());
        //跳转小程序类型：developer为开发版；trial为体验版；formal为正式版；默认为正式版
        paramsMap.put("miniprogram_state", "developer");
        paramsMap.put("page", "pages/pushDetails/pushDetails?manageRouteNodeId=" + patientVO.getSignPatientManageRouteNodeId());
        Map<String, Object> dataMap = new LinkedHashMap<>();
        dataMap.put("thing5", new MessageValueEntity(thing5));
        dataMap.put("thing4", new MessageValueEntity(patientVO.getHospitalAgencyName()));
        dataMap.put("time3", new MessageValueEntity(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))));
        dataMap.put("thing6", new MessageValueEntity(patientVO.getRouteNodeName() + "第" + patientVO.getRouteNodeDay() + "天"));
        dataMap.put("thing1", new MessageValueEntity(thing1));
        paramsMap.put("data", dataMap);
        //拼接请求地址并发送
        String messageUrl = Constants.OFFICIAL_ACCOUNT_SUBSCRIBE_SEND_URL + accessToken;
        String param = JSON.toJSONString(paramsMap);
        String result = HttpUtils.sendPostJson(messageUrl, param);
        //返回参数映射
        AccessToken errCode = JSON.parseObject(result, AccessToken.class);
        if (Objects.nonNull(errCode) && Objects.nonNull(errCode.getErrcode())) {
            switch (errCode.getErrcode()) {
                case Constants.SUCCESS_ERROR_CODE:
                    log.info("发送消息成功！");
                    break;
                case Constants.INVALID_CREDENTIAL_ACCESS_TOKEN_ISINVALID_OR_NOT_LATEST:
                    log.error("取 access_token 时 AppSecret 错误，或者 access_token 无效！");
                    break;
                case Constants.INVALID_OPENID:
                    log.error("不合法的 OpenId！");
                    break;
                case Constants.INVALID_ACCESS_TOKEN:
                    log.error("合法的 access_token！");
                    break;
                case Constants.INVALID_TEMPLATE_ID:
                    log.error("不合法的 template_id！");
                    break;
                case Constants.ARGUMENT_INVALID:
                    log.error("参数无效！");
                    break;
                case Constants.API_UNAUTHORIZED:
                    log.error("API 功能未授权！");
                    break;
                case Constants.DENY_SUBSCRIPTION:
                    log.error("用户拒接订阅！");
                    break;
                default:
                    break;
            }
        }
        return errCode.getErrcode();
    }
}
