package com.cm.common.wechat.service.impl;

import com.cm.common.exception.SearchException;
import com.cm.common.exception.WechatAccessTokenForUserException;
import com.cm.common.exception.WechatUserInfoException;
import com.cm.common.exception.base.SystemException;
import com.cm.common.result.SuccessResultData;
import com.cm.common.utils.AesUtil;
import com.cm.common.utils.http.RestRequestUtil;
import com.cm.common.wechat.config.pojo.WechatMiniAppProperties;
import com.cm.common.wechat.manager.miniapp.WechatMiniAppManager;
import com.cm.common.wechat.pojo.WechatMiniAppLoginVO;
import com.cm.common.wechat.pojo.WechatMiniAppUserInfo;
import com.cm.common.wechat.pojo.WechatOfficialAccountUserInfo;
import com.cm.common.wechat.service.IWechatMiniAppAuthService;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: WechatMiniAppAuthServiceImpl
 * @Description: 小程序认证
 * @Author: WangGeng
 * @Date: 2020/5/9 18:16
 * @Version: 1.0
 **/
@Service
public class WechatMiniAppAuthServiceImpl implements IWechatMiniAppAuthService {

    private static final Logger LOG = LoggerFactory.getLogger(WechatMiniAppAuthServiceImpl.class);

    @Autowired
    private WechatMiniAppProperties wechatMiniAppProperties;

    @Override
    public SuccessResultData login(WechatMiniAppLoginVO wechatMiniAppLoginVO) throws Exception {
        if (wechatMiniAppProperties == null) {
            throw new SystemException("未有相关配置");
        }
        if (wechatMiniAppProperties.getActive() == null || !wechatMiniAppProperties.getActive()) {
            throw new SystemException("未激活小程序配置");
        }
        Map<String, Object> params = new HashMap<>(2);
        params.put("appid", wechatMiniAppProperties.getAppKey());
        params.put("secret", wechatMiniAppProperties.getAppSecret());
        params.put("js_code", wechatMiniAppLoginVO.getJsCode());
        params.put("grant_type", wechatMiniAppProperties.getGrantType());

        StringBuilder url = new StringBuilder(wechatMiniAppProperties.getAuthorizeUrl());
        url.append("?appid={appid}&secret={secret}&js_code={js_code}&grant_type={grant_type}");
        RestTemplate restTemplate = new RestTemplate();

        String resultJson = restTemplate.getForObject(url.toString(), String.class, params);
        WechatMiniAppUserInfo wechatMiniAppUserInfo = new ObjectMapper().readValue(resultJson, WechatMiniAppUserInfo.class);
        if (wechatMiniAppUserInfo == null) {
            throw new WechatUserInfoException("获取微信用户信息失败");
        }
        if (wechatMiniAppUserInfo.getErrcode() != null && wechatMiniAppUserInfo.getErrcode() != 0) {
            throw new WechatAccessTokenForUserException(String.format("获取用户信息失败，错误码：%s，错误信息：%s", wechatMiniAppUserInfo.getErrcode(), wechatMiniAppUserInfo.getErrmsg()));
        }
        LOG.debug("绑定用户 | 登录");
        String wechatSignInfo = Base64.encodeBase64String(AesUtil.aesCommonEncoder("WECHAT_SIGN_INFO", new StringBuilder(wechatMiniAppUserInfo.getOpenid()).append("_WenG_").append(wechatMiniAppProperties.getAppKey()).toString()).getBytes("UTF-8"));
        String token = getAppToken(wechatSignInfo);
        if (token.endsWith("_0") || token.endsWith("_1")) {
            WechatMiniAppManager.getInstance().addUser(token.substring(0, token.length() - 2), wechatMiniAppUserInfo);
        } else {
            WechatMiniAppManager.getInstance().addUser(token, wechatMiniAppUserInfo);
        }
        return new SuccessResultData(token);
    }

    /**
     * 获取token
     *
     * @param wechatSignInfo
     * @return
     */
    public String getAppToken(String wechatSignInfo) {
        RestTemplate restTemplate = new RestTemplate();
        Map<String, Object> params = new HashMap<>(1);
        params.put("signInfo", wechatSignInfo);
        HttpEntity<Map<String, Object>> requestBody = new HttpEntity<>(params);
        try {
            ResponseEntity<Map> result = restTemplate.postForEntity(wechatMiniAppProperties.getBindUserUrl(), requestBody, Map.class);
            LOG.debug("状态码：{}", result.getStatusCodeValue());
            if (HttpStatus.OK.value() != result.getStatusCodeValue()) {
                throw new SearchException("获取Token失败");
            }
            Map body = result.getBody();
            return (String) body.get("data");
        } catch (HttpClientErrorException e) {
            if (e.getRawStatusCode() == HttpStatus.BAD_REQUEST.value()) {
                throw new SearchException(e.getResponseBodyAsString());
            }
            throw new SearchException("绑定用户 | 登录失败");
        }
    }

}
