package com.hdkj.lt.core.rest.service.impl;

import com.alibaba.fastjson.JSON;
import com.hdkj.lt.base.exception.ExceptionCast;
import com.hdkj.lt.core.rest.config.HttpClientConfig;
import com.hdkj.lt.core.rest.model.AbstractCallResponseEntity;
import com.hdkj.lt.core.rest.service.IRemoteCallService;
import com.hdkj.hussar.ResultCode;
import com.hdkj.hussar.HussarException;
import lombok.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Optional;

/**
 * @Description: 支持各平台远程调用的抽象类
 * @Author: wenhao
 * @Create: 2023/08/01 16:11
 * @Version: 1.0
 */
@Slf4j
public abstract class AbstractDefaultRemoteCallService implements IRemoteCallService {

    @Resource(name = HttpClientConfig.CONN_POOL_REST_TEMPLATE)
    protected RestTemplate restTemplate;

    protected abstract CallConfig buildCallConfig();

    protected abstract <B> HttpEntity<B> createHttpEntity(B body);

    @Override
    public <R> R call(String methodUrl, HttpMethod method, Object requestBody, Class<R> responseBody) {
        CallConfig callConfig = this.buildCallConfig();
        String requestUrl = callConfig.getRequestUri().concat(methodUrl);
        Class<? extends AbstractCallResponseEntity> responseType = callConfig.getResponseType();
        String requestBodyStr = JSON.toJSONString(requestBody);
        try {
            HttpEntity<Object> httpEntity = this.createHttpEntity(requestBody);
            ResponseEntity<? extends AbstractCallResponseEntity> restRespEntity = restTemplate.exchange(requestUrl, method, httpEntity, responseType);
            AbstractCallResponseEntity callRespEntity = restRespEntity.getBody();
            if (!HttpStatus.OK.equals(restRespEntity.getStatusCode()) || Objects.isNull(callRespEntity)
//                    || !Objects.equals(callRespEntity.getCode(), callConfig.getSuccessCode())
            ) {
                String messagePattern = String.format("call failed, methodUrl: %s,\n requestBody: %s,\n restRespEntity: %s", methodUrl, requestBodyStr, JSON.toJSONString(restRespEntity));
                StringBuilder errorMsg = new StringBuilder(messagePattern);
                Optional.ofNullable(callRespEntity).ifPresent(e -> errorMsg.append(",\n errorMsg：").append(e.getMsg()));
                ExceptionCast.cast(errorMsg.toString());
            }
            log.info("call successful, methodUrl: {},\n requestBody: {},\n callRespEntity: {}", methodUrl, requestBodyStr, JSON.toJSONString(callRespEntity));
            return JSON.parseObject(JSON.toJSONString(callRespEntity.getData()), responseBody);
        } catch (Exception e) {
            log.error("call failed, methodUrl: {},\n requestBody: {},\n errorMsg: {}", methodUrl, requestBodyStr, e.toString());
            throw new HussarException(ResultCode.FAILURE.getCode(), e.toString());
        }
    }

    @Getter
    @Setter
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class CallConfig {

        private String requestUri; //请求的uri

        private Object successCode; //响应成功状态码

        private Class<? extends AbstractCallResponseEntity> responseType; //响应结果泛型

    }

}
