package com.face.weixin;


import com.face.global.enums.CommonCode;
import com.face.util.JsonUtils;
import com.face.util.SystemExceptionUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.env.Environment;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class WeiXinRemoteService {

    @Autowired
    protected WXProperties wxProperties;

    @Autowired
    @Qualifier("proxyRestTemplate")
    protected RestTemplate restTemplate;



    @Autowired
    private Environment environment;

    public WXRefreshAccessTokenResult getOfficialAccessToken() {
        Map<String, String> params = new HashMap<>();
        params.put("appid", wxProperties.getAppId());
        params.put("secret", wxProperties.getAppSecret());
        return restTemplate.getForObject(wxProperties.getOfficial().getAccessTokenUrl(), WXRefreshAccessTokenResult.class, params);
    }

    public WXRefreshTicketResult getTicket(String accessToken) {
        Map<String, String> params = new HashMap<>();
        params.put("accessToken", accessToken);
        return restTemplate.getForObject(wxProperties.getOfficial().getGetticketUrl(), WXRefreshTicketResult.class, params);
    }





    public boolean checkResultVO(String function, boolean throwWxError, WxResultVO wxResultVO) {
        if (wxResultVO == null || wxResultVO.getErrcode() != WxResultEnum.SUCCESS.getCode()) {
            log.error("call function {} fail {}", function, wxResultVO != null ? JsonUtils.toJsonString(wxResultVO) : "no data");
            if (throwWxError && wxResultVO != null && StringUtils.isNotBlank(wxResultVO.getErrmsg())) {
                throw SystemExceptionUtils.buildBusinessException("callWxMiniNotResultFail", wxResultVO.getErrmsg());
            }
            if (throwWxError) {
                throw SystemExceptionUtils.buildBusinessException("callWxMiniNotResultFail");
            }
            return false;
        }
        return true;
    }

    protected HttpEntity buildJsonRequestBody(Object body, Map<String, String> headers) {
        HttpHeaders requestHeaders = new HttpHeaders();
        if (headers != null) {
            headers.entrySet().forEach(entry -> requestHeaders.add(entry.getKey(), entry.getValue()));
        }
        requestHeaders.add("Content-Type", MediaType.APPLICATION_JSON_UTF8_VALUE);
        return new HttpEntity(body, requestHeaders);
    }

    protected <T> T httpPostForStr(String url, Object requstBody, Map<String, String> headers, Map params, TypeReference<T> typeReference) {
        log.info("startHttpPostForStr {}", url);
        long startTime = System.currentTimeMillis();
        try {
            HttpEntity httpEntity = null;
            if (requstBody != null) {
                httpEntity = this.buildJsonRequestBody(requstBody, headers);
            }
            ResponseEntity<String> response = this.restTemplate.postForEntity(url, httpEntity, String.class, params);
            String body = response.getBody();
            if (response.getStatusCode().is2xxSuccessful()) {
                try {
                    return JsonUtils.parseObject(body, typeReference);
                } catch (Exception e) {
                    log.error("httpPostForStrError {} {}", response.getStatusCode().value(), body, e);
                    throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), body, e);
                }
            } else {
                log.error("httpPostForStrError {} {}", url, response.getStatusCode().value(), body);
                throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), body);
            }
        } finally {
            log.info("endHttpPostForStr {} {}", url, System.currentTimeMillis() - startTime);
        }
    }


    protected  <T> T httpGetForStr(String url, Map<String, String> headers, Map params, TypeReference<T> typeReference) {
        log.info("startHttpGetForStr {}", url);
        long startTime = System.currentTimeMillis();
        try {
            HttpHeaders httpHeaders = new HttpHeaders();
            if (!CollectionUtils.isEmpty(headers)) {
                headers.entrySet().forEach(entry -> {
                    httpHeaders.add(entry.getKey(), entry.getValue());
                });
            }
            ResponseEntity<String> response = this.restTemplate.exchange(url, HttpMethod.GET, null, String.class, params);
            String body = response.getBody();
            if (response.getStatusCode().is2xxSuccessful()) {
                try {
                    return JsonUtils.parseObject(body, typeReference);
                } catch (Exception e) {
                    log.error("httpGetForStrError {} {}", response.getStatusCode().value(), body, e);
                    throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), body);
                }
            } else {
                log.error("httpGetForStrError {} {}", url, response.getStatusCode().value(), body);
                throw SystemExceptionUtils.buildBusinessException(CommonCode.ERROR.getCode(), body);
            }
        } finally {
            log.info("endHttpGetForStr {} {}", url, System.currentTimeMillis() - startTime);
        }
    }
}
