package com.fjhx.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.fjhx.constants.WxAppletConstant;
import lombok.Data;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;

import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;

public class WxAppletUtil {

    private static final RestTemplate restTemplate = new RestTemplate();
    private static final BladeRedis bladeRedis = SpringUtil.getBean(BladeRedis.class);
    private static final String APPLET_ACCESS_TOKEN_KEY = "wxAppletAccessTokenKey:";

    static {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(
                Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM, MediaType.TEXT_HTML));
        restTemplate.getMessageConverters().add(mappingJackson2HttpMessageConverter);
    }

    /**
     * 获取openId
     */
    public static String getOpenId(String url, String code) {
        String wxResult;
        try {
            wxResult = restTemplate.getForObject(String.format(url, code), String.class);
        } catch (ResourceAccessException ignored) {
            throw new ServiceException("网络连接失败");
        }

        JSONObject wxResultMap = JSONObject.parseObject(wxResult);
        return wxResultMap.get("openid").toString();
    }

    /**
     * 获取accessToken
     */
    public synchronized static String getAccessToken(String url) {

        String redisKey = APPLET_ACCESS_TOKEN_KEY + url;

        // 缓存获取accessToken
        String accessToken = bladeRedis.get(redisKey);
        if (ObjectUtil.isNotEmpty(accessToken)) {
            return accessToken;
        }

        AccessTokenResult body;
        try {
            body = restTemplate.getForEntity(url, AccessTokenResult.class).getBody();
        } catch (ResourceAccessException ignored) {
            throw new ServiceException("网络连接失败");
        }

        String errorStr = "微信小程序获取accessToken失败";
        if (body == null) {
            throw new ServiceException(errorStr);
        }

        Integer errcode = body.getErrcode();
        if (errcode != null) {
            throw new ServiceException(errorStr + ", errorcode= " + errcode + " ,errormsg= " + body.getErrmsg());
        }

        String access_token = body.getAccess_token();
        Integer expires_in = body.getExpires_in();

        // 赋值缓存
        bladeRedis.setEx(redisKey, access_token, new Double(expires_in * 0.8).longValue());

        return access_token;
    }


    /**
     * 小程序发送消息
     */
    public static void sendMessage(UniformSendEntity uniformSendEntity) {
        String sendMessageUrl = WxAppletConstant.SEND_MESSAGE_URL + getAccessToken(WxAppletConstant.GET_ACCESS_TOKEN_URL);
        restTemplate.postForObject(sendMessageUrl, uniformSendEntity, String.class);
    }

//    public static void main(String[] args) {
//
//        UniformSendEntity uniformSendEntity = new UniformSendEntity();
//        // openId
//        uniformSendEntity.setTouser("odMjv5Yndizr4ybYaShMt9s9GMVI");
//        // 赋值模板id
//        uniformSendEntity.setTemplate_id("Tt0C6SOrtd2QXIdLqrm0CNdarUE4LG_lNJblUnkqTPM");
//        // 跳转路径
//        uniformSendEntity.setPage("pages/user/login");
//        // 模板信息
//        uniformSendEntity.addData("thing1", "小小的一个测试");
//        uniformSendEntity.addData("thing2", "测试啥我也不懂");
//        uniformSendEntity.addData("time3", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm"));
//
//        sendMessage(uniformSendEntity);
//    }

    @Data
    public static class AccessTokenResult implements Serializable {
        private static final long serialVersionUID = 1L;

        // 	获取到的凭证
        private String access_token;
        // 凭证有效时间，单位：秒。目前是7200秒之内的值。
        private Integer expires_in;
        // 错误码
        private Integer errcode;
        // 错误信息
        private String errmsg;
    }

    @Data
    public static class UniformSendEntity implements Serializable {
        private static final long serialVersionUID = 1L;

        // 用户openid，可以是小程序的openid
        private String touser;
        // 小程序模板ID
        private String template_id;
        // 小程序页面路径
        private String page;
        // 	跳转小程序类型：developer为开发版；trial为体验版；formal为正式版；默认为正式版
        private String miniprogram_state;
        // 模板参数
        private HashMap<String, Object> data = new HashMap<>();

        public void addData(String key, String value) {
            HashMap<String, String> map = new HashMap<>();
            map.put("value", value);
            data.put(key, map);
        }

    }

}
