package ink.wgink.module.wechat.request;

import ink.wgink.module.wechat.enums.ErrorMsgEnum;
import ink.wgink.module.wechat.manager.OfficialAccountAccessTokenManager;
import ink.wgink.module.wechat.pojo.OfficialAccountAccessToken;
import ink.wgink.module.wechat.result.AccessTokenResult;
import ink.wgink.properties.wechat.official.account.OfficialAccountProperties;
import ink.wgink.util.request.AbstractRestTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: AccessTokenRestTemplate
 * @Description:
 * @Author: wanggeng
 * @Date: 2021/4/28 5:31 上午
 * @Version: 1.0
 */
public class AccessTokenRestTemplate extends AbstractRestTemplate<AccessTokenResult, MultiValueMap> {
    private static final Logger LOG = LoggerFactory.getLogger(AccessTokenRestTemplate.class);
    private OfficialAccountProperties officialAccountProperties;

    public AccessTokenRestTemplate(OfficialAccountProperties officialAccountProperties) {
        this.officialAccountProperties = officialAccountProperties;
    }

    @Override
    public MultiValueMap postBody() {
        MultiValueMap multiValueMap = new LinkedMultiValueMap<>();
        multiValueMap.add("grant_type", officialAccountProperties.getGrantType());
        multiValueMap.add("appid", officialAccountProperties.getAppId());
        multiValueMap.add("secret", officialAccountProperties.getAppSecret());
        return multiValueMap;
    }

    @Override
    public Class<AccessTokenResult> successResultType() {
        return AccessTokenResult.class;
    }

    @Override
    public void success200(AccessTokenResult result) {
        if (result.getErrcode() == ErrorMsgEnum.SUCCESS.getErrCode()) {
            OfficialAccountAccessToken officialAccountAccessToken = new OfficialAccountAccessToken();
            officialAccountAccessToken.setAccessToken(result.getAccess_token());
            officialAccountAccessToken.setLastUpdated(System.currentTimeMillis());
            OfficialAccountAccessTokenManager.getInstance().setAccessToken(officialAccountAccessToken);
            return;
        }
        if (result.getErrcode() == ErrorMsgEnum.SYSTEM_BUSY.getErrCode()) {
            LOG.error("系统繁忙，3s后重试");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                LOG.error(e.getMessage(), e);
            }
            this.get(getAccessTokenUrl());
            return;
        }
        LOG.error(ErrorMsgEnum.getErrMsg(result.getErrcode()));
    }

    @Override
    public void error400(HttpClientErrorException error) {
        LOG.error(error.getMessage(), error);
    }

    /**
     * access_token路径
     *
     * @return
     */
    public String getAccessTokenUrl() {
        return String.format("%s?grant_type=%s&appid=%s&secret=%s",
                officialAccountProperties.getAccessTokenUrl(),
                officialAccountProperties.getGrantType(),
                officialAccountProperties.getAppId(),
                officialAccountProperties.getAppSecret());
    }

}
