package cn.pluss.platform.wx.impl;

import cn.pluss.platform.api.ResultCode;
import cn.pluss.platform.cacheInfo.CacheInfoService;
import cn.pluss.platform.entity.CacheInfo;
import cn.pluss.platform.exception.MsgException;
import cn.pluss.platform.util.ParametersUtil;
import cn.pluss.platform.util.SignUtils;
import cn.pluss.platform.util.StringUtil;
import cn.pluss.platform.utils.WechatUtils;
import cn.pluss.platform.wx.*;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 *
 *@description:
 *@author: bzg
 *@time: 2021/11/29 15:28
 */
@Service
@Slf4j
public class WxCommonServiceImpl implements WxCommonService {


    @Resource
    private CacheInfoService cacheInfoService;

    @Resource
    protected RestTemplate restTemplate;

    private final String API_TOKEN_URL = "https://shop.shouyinbei.net/addons/we7_wmall/api/cache.php?key=KEY&keyCode=CODE&refresh=REFRESH";
    /**
     * 获取wx access_token 参数
     * @date: 2021/11/29 15:35
     * @param request:
     * @param refresh:
     * @return cn.pluss.platform.wx.WxAccessTokenResponse
     */
    @Override
    public String getAccessToken(WxAccessTokenRequest request,Boolean refresh) {
        checkCommonParams(request);
        String keyCode = WX_ACCESS_TOKEN_PREFIX_CODE + request.getAppid();
        String url = API_TOKEN_URL.replace("KEY",request.getAppid()).replace("CODE",WX_ACCESS_TOKEN_PREFIX_CODE).replace("REFRESH",refresh ? "1" : "0");
        JSONObject result = restTemplate.getForObject(url, JSONObject.class);
        if(result.getInteger("code") != ResultCode.SUCCESS.code()){
            CacheInfo cache = cacheInfoService.getCacheInfoByKeyCode(keyCode);
            if(cache == null){
                WxAccessTokenResponse response = WechatUtils.getAccessToken(request);
                CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
                cacheInfoService.save(cacheInfo);
                return response.getAccess_token();
            }else{
                Long time = System.currentTimeMillis() / 1000;
                if(time >= cache.getExpiresIn() - CacheInfo.MAX_CRITICAL_VALUE){
                    WxAccessTokenResponse response = WechatUtils.getAccessToken(request);
                    CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
                    cacheInfo.setId(cache.getId());
                    cacheInfoService.saveOrUpdate(cacheInfo);
                    return response.getAccess_token();
                }else{
                    return cache.getAccessToken();
                }
            }
        }else{
            CacheInfo cache = cacheInfoService.getCacheInfoByKeyCode(keyCode);
            JSONObject data = result.getJSONObject("data");
            if(cache == null){
                CacheInfo cacheInfo = new CacheInfo(request,keyCode,data.getString("accessToken"),data.getLong("expire"),data.getString("refreshToken"));
                cacheInfoService.save(cacheInfo);
                return data.getString("accessToken");
            }else{
                if(!cache.getAccessToken().equals(data.getString("accessToken"))){
                    cache.setAccessToken(data.getString("accessToken"));
                    cache.setExpiresIn(data.getLong("expire"));
                    if(StringUtil.isNotEmpty(data.getString("refreshToken"))){
                        cache.setRefreshToken(data.getString("refreshToken"));
                    }
                    cacheInfoService.saveOrUpdate(cache);
                }
                return data.getString("accessToken");
            }
        }
    }

    @Override
    public WxOpenidResponse getWxOpenId(WxAccessTokenRequest request) {
        checkCommonParams(request);
        WxOpenidResponse response = WechatUtils.getWxOpenid(request);
        if(StringUtil.isNotEmpty(response.getExpires_in())){
            String keyCode = WX_OAUTH2_ACCESS_TOKEN_PREFIX_CODE + request.getAppid();
            CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
            after(cacheInfo,keyCode);
        }
        return response;
    }

    private void after(CacheInfo cacheInfo,String keyCode) {
        CacheInfo cache = cacheInfoService.getCacheInfoByKeyCode(keyCode);
        if(cache == null){
            cacheInfoService.save(cacheInfo);
        }else {
            cacheInfo.setId(cache.getId());
            cacheInfoService.updateById(cacheInfo);
        }
    }


    @Override
    public void sendTemplateMsg(WxTemolateRequest request,WxAccessTokenRequest tokenRequest) {
        String accessToken = this.getAccessToken(tokenRequest,false);
        try {
            WechatUtils.sendTemplateMsg(accessToken,request);
        }catch (MsgException e){
            e.printStackTrace();
            log.info("发送模板消息失败，异常信息:{},再次发送");
            accessToken = this.getAccessToken(tokenRequest,true);
            WechatUtils.sendTemplateMsg(accessToken,request);
        }
    }

    public void checkCommonParams(WxAccessTokenRequest request){
        MsgException.checkBlank(request.getAppid(),"缺失appid参数");
        MsgException.checkBlank(request.getSecret(),"缺失secret参数");
    }

    /**
     * 获取网页授权信息
     * @date: 2021/11/30 10:28
     * @param request:
     * @return cn.pluss.platform.wx.WxOauth2AccessTokenResponse
     */
    @Override
    public WxOauth2AccessTokenResponse getOauth2Info(WxAccessTokenRequest request) {
        MsgException.checkBlank(request.getCode(),"缺失code参数");
        String keyCode = WX_OAUTH2_ACCESS_TOKEN_PREFIX_CODE + request.getAppid();
        WxOauth2AccessTokenResponse response = WechatUtils.getOauth2AccessToken(request);
        CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
        after(cacheInfo,keyCode);
        return response;
    }


    /**
     * @description:获取微信用户信息
     * @date: 2021/11/30 13:50
     * @param request:
     * @param openid:
     * @return cn.pluss.platform.wx.WxUserInfoResponse
     */
    @Override
    public WxUserInfoResponse getWxUserInfo(WxAccessTokenRequest request,String openid) {
        String accessToken = this.getAccessToken(request,false);
        WxUserInfoResponse wxUserInfo = null;
        try {
            wxUserInfo = WechatUtils.getWxUserInfo(accessToken, openid);
        }catch (MsgException e){
            e.printStackTrace();
            log.info("获取用户信息异常，异常信息:{},再次获取");
            accessToken = this.getAccessToken(request,true);
            wxUserInfo = WechatUtils.getWxUserInfo(accessToken, openid);
        }
        return wxUserInfo;
    }

    /**
     * 生成带参数的二维码
     * @date: 2021/12/9 11:22
     * @param tokenRequest:
     * @param qrCodeRequest:
     * @return cn.pluss.platform.wx.WxCreateQrCodeResponse
     */
    @Override
    public WxCreateQrCodeResponse getWxQrCode(WxAccessTokenRequest tokenRequest, WxCreateQrCodeRequest qrCodeRequest) {
        String accessToken = this.getAccessToken(tokenRequest,false);
        WxCreateQrCodeResponse response = null;
        try {
            response = WechatUtils.getWxQrCode(accessToken,qrCodeRequest);
        }catch (MsgException e){
            e.printStackTrace();
            log.info("生成带参数的二维码，异常信息:{},再次获取");
            accessToken = this.getAccessToken(tokenRequest,true);
            response = WechatUtils.getWxQrCode(accessToken,qrCodeRequest);
        }
        return response;
    }

    /**
     * 获取微信全局jsapiticket 方法
     * @date: 2022/3/10 15:16
     * @param request:
     * @param type:
     * @return java.lang.String
     */
    @Override
    public String getJsapiTicket(WxAccessTokenRequest request, String type) {
        String keyCode = WX_JSAPI_TICKET_PREFIX_CODE + request.getAppid();
        CacheInfo cache = cacheInfoService.getCacheInfoByKeyCode(keyCode);
        if(cache == null){
            String accessToken = this.getAccessToken(request,false);
            WxJsApiTicketResponse response = WechatUtils.getJsapiTicket(accessToken,type);
            CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
            cacheInfoService.save(cacheInfo);
            return response.getTicket();
        }else{
            Long time = System.currentTimeMillis() / 1000;
            if(time >= cache.getExpiresIn() - CacheInfo.MAX_CRITICAL_VALUE){
                String accessToken = this.getAccessToken(request,false);
                WxJsApiTicketResponse response = WechatUtils.getJsapiTicket(accessToken,type);
                CacheInfo cacheInfo = new CacheInfo(response,request,keyCode);
                cacheInfo.setId(cache.getId());
                cacheInfoService.saveOrUpdate(cacheInfo);
                return response.getTicket();
            }else{
                return cache.getAccessToken();
            }
        }
    }

    /**
     * 获取微信jsapi校验参数
     * @date: 2022/3/10 15:27
     * @param request:
     * @return com.alibaba.fastjson.JSONObject
     */
    @Override
    public JSONObject getJsApiConfigParam(HttpServletRequest request) {
        JSONObject result = new JSONObject(4);
        WxAccessTokenRequest req = WxAccessTokenRequest.buidWxToken(ParametersUtil.APPID,ParametersUtil.APPSECRET);
        String ticket = this.getJsapiTicket(req, "jsapi");
        String noncestr = StringUtil.generateMixStr(10);
        Long timestamp = System.currentTimeMillis() / 1000;
        String pUrl = request.getRequestURL().toString() + "?" + request.getQueryString();
        String signContent = "jsapi_ticket=" + ticket + "&noncestr="+noncestr + "&timestamp="+ timestamp + "&url="+pUrl;
        String sign = SignUtils.sha1Encrypt(signContent);
        result.put("signature",sign);
        result.put("nonceStr",noncestr);
        result.put("timestamp",timestamp);
        result.put("appId",req.getAppid());
        return result;
    }

    /**
     * 获取微信小程序secheme码
     * @param tokenRequest
     * @return
     */
    @Override
    public WxUrlschemeResponse getUrlecheme(WxAccessTokenRequest tokenRequest,WxJumpWxa wxJumpWxa) {
        String accessToken = this.getAccessToken(tokenRequest,false);
        WxUrlschemeRequest request = new WxUrlschemeRequest(wxJumpWxa,5);
        WxUrlschemeResponse response = WechatUtils.getUrlecheme(request,accessToken);
        return response;
    }
}
