package com.imdroid.beidou.utils;


import com.imdroid.beidou.config.WxMiniProperties;
import com.imdroid.beidou.data.WxMiniUserSession;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.imdroid.beidou.data.dto.MiniHardwareDeviceMessageDTO;
import com.imdroid.beidou.data.dto.MiniSnTicketBodyDTO;
import com.imdroid.beidou.data.dto.MiniSubscribeMessageDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 微信相关工具类
 *
 * @author LiGang
 */
@Slf4j
@Component
public class WXUtils {

    private final WxMiniProperties wxMiniProperties;

    public WXUtils(WxMiniProperties wxMiniProperties) {
        this.wxMiniProperties = wxMiniProperties;
    }

    private String accessToken;
    private long accessTokenExpireTime = 0L;
    private static final long PRE_EXPIRE_TIME = 5 * 60 * 1000L;

    /**
     * 微信小程序登录api地址
     */
    protected final String API_URL = "https://api.weixin.qq.com/sns/jscode2session";

    protected final String API_SEND_SUBSCRIBE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";

    protected final String API_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    protected final String API_SN_TICKET_URL = "https://api.weixin.qq.com/wxa/getsnticket";

    protected final String API_HARDWARE_DEVICE_MESSAGE_URL = "https://api.weixin.qq.com/cgi-bin/message/device/subscribe/send";

    /**
     * 获取小程序 access_token
     *
     * @return access_token
     */
    public String getAccessToken() {
        if (accessTokenExpireTime - System.currentTimeMillis() >= PRE_EXPIRE_TIME ) {
            return accessToken;
        }
        String url = API_ACCESS_TOKEN_URL + "?grant_type=client_credential&appid=" + wxMiniProperties.getAppid() +
                "&secret=" + wxMiniProperties.getSecret();
        try {
            final String response = HttpUtil.doGet(url);
            log.info("小程序获取access_token结果：{}", response);
            JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject();
            accessTokenExpireTime = System.currentTimeMillis() + 7200 * 1000;
            accessToken = jsonObject.get("access_token").getAsString();
            return accessToken;
        } catch (Exception e) {
            log.error("小程序登录结果：{}", e.toString());
            return null;
        }
    }

    /**
     * 获取小程序用户的openid
     *
     * @param code 登录码
     * @return 小程序用户的openid
     */
    public WxMiniUserSession getMiniProgramUserOpenid(String code) {
        String requestUrl = String.format(API_URL + "?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"
                , wxMiniProperties.getAppid(), wxMiniProperties.getSecret(), code);
        try {
            final String response = HttpUtil.doGet(requestUrl);
            log.info("小程序登录结果：{}", response);
            JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject();
            String sessionKey = jsonObject.get("session_key").getAsString();
            String openid = jsonObject.get("openid").getAsString();
            return new WxMiniUserSession(sessionKey, openid);
        } catch (Exception e) {
            log.error("小程序登录结果：{}", e.toString());
            return null;
        }

    }

    /**
     * 发送小程序订阅消息
     *
     * @param miniSubscribeMessageDTO 小程序订阅消息对象
     */
    public void sendSubscribeMessage(MiniSubscribeMessageDTO miniSubscribeMessageDTO) {
        String requestUrl = API_SEND_SUBSCRIBE_MESSAGE_URL + "?access_token=" + getAccessToken();
        try {
            String dataJson = GsonUtils.toJson(miniSubscribeMessageDTO);
            final String response = HttpUtil.doPostJson(requestUrl, dataJson);
            log.info("发送订阅消息结果：{}", response);
        } catch (Exception e) {
            log.error("发送订阅消息结果：{}",e.toString());
        }
    }

    /**
     * 获取设备snTicket
     *
     * @param miniSnTicketBodyDTO MiniSnTicketBodyDTO
     * @return 设备snTicket
     */
    public String getSnTicket(MiniSnTicketBodyDTO miniSnTicketBodyDTO) {
        String requestUrl = API_SN_TICKET_URL + "?access_token=" + getAccessToken();
        try {
            String dataJson = GsonUtils.toJson(miniSnTicketBodyDTO);
            final String response = HttpUtil.doPostJson(requestUrl, dataJson);
            log.info("获取设备snTicket结果：{}", response);
            JsonObject jsonObject = JsonParser.parseString(response).getAsJsonObject();
            return jsonObject.get("sn_ticket").getAsString();
        } catch (Exception e) {
            log.error("获取设备snTicket结果：{}",e.toString());
        }
        return null;
    }

    /**
     * 发送设备消息
     *
     * @param hardwareDeviceMessageDTO MiniHardwareDeviceMessageDTO
     */
    public void sendHardwareDeviceMessage(MiniHardwareDeviceMessageDTO hardwareDeviceMessageDTO) {
        String requestUrl = API_HARDWARE_DEVICE_MESSAGE_URL + "?access_token=" + getAccessToken();
        try {
            String dataJson = GsonUtils.toJson(hardwareDeviceMessageDTO);
            final String response = HttpUtil.doPostJson(requestUrl, dataJson);
            log.info("发送设备消息结果：{}", response);
        } catch (Exception e) {
            log.error("发送设备消息结果: {}", e.toString());
        }
    }

}
