package com.cool.store.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.cool.store.dto.xgj.XgjBranchBankDTO;
import com.cool.store.dto.xgj.XgjPartnerPageDTO;
import com.cool.store.dto.xgj.XgjPayResultDTO;
import com.cool.store.enums.ErrorCodeEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.request.xgj.*;
import com.cool.store.response.XgjAccessTokenDTO;
import com.cool.store.response.oppty.OpportunityApiResponse;
import com.cool.store.service.ThirdXgjService;
import com.cool.store.utils.HmacSigner;
import com.cool.store.utils.poi.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 新管家三方接口 服务实现类
 * </p>
 *
 * @author wangff
 * @since 2025/11/28
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ThirdXgjServiceImpl implements ThirdXgjService {
    @Value("${xgj.api.auth.url}")
    private String xgjUrl;

    @Value("${xgj.api.token.url}")
    private String xgjTokenUrl;

    @Value("${xgj.api.auth.username}")
    private String xgjUsername;

    @Value("${xgj.api.auth.secret}")
    private String xgjSecret;

    @Resource
    OkHttpClient okHttpClient;
    @Resource
    ObjectMapper objectMapper;

    @Override
    public String accountClose(XgjAccountCloseRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-join/open/closeStore";
        return executePostApiCall(apiUrl, request, String.class);
    }

    @Override
    public String reimburse(XgjReimburseRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-join/open/dmpJoinCloseOpen";
        return executePostApiCall(apiUrl, request, String.class);
    }

    @Override
    public String savePartner(XgjSavePartnerRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-join/open/saveMKPartner";
        return executePostApiCall(apiUrl, request, String.class);
    }

    @Override
    public XgjPayResultDTO queryOrderStatus(XgjPaymentRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-join/open/quryOrderStatus";
        return executePostApiCall(apiUrl, request, XgjPayResultDTO.class);
    }

    @Override
    public XgjPartnerPageDTO queryPartnerPage(XgjPartnerQueryRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-join/open/partnerPage";
        return executePostApiCall(apiUrl, request, XgjPartnerPageDTO.class);
    }

    @Override
    public List<XgjBranchBankDTO> queryBranchBankList(XgjBankQueryRequest request) {
        String apiUrl = xgjUrl + "/dmp/dmp-payment/open/queryOpenBankNoByBankName";
        return executePostApiCall(apiUrl, request, List.class);
    }

    private <T> T executePostApiCall(String url, Object requestBody, Class<T> responseType) {
        // 1. 打印请求前日志
        logRequest(url, requestBody);

        try {
            String accessToken = getXgjAccessToken().getAccess_token();

            Request request = buildRequest(requestBody, url,accessToken);

            request.headers().names().forEach(x->{
                log.info(x+": {}",request.header(x));
            });

            try (Response response = okHttpClient.newCall(request).execute()) {
                // 2. 获取原始响应内容
                String responseBody = response.body().string();

                // 3. 打印响应日志
                logResponse(url, response.code(), responseBody);

                if (!response.isSuccessful()) {
                    throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
                            "HTTP请求失败，状态码: " + response.code());
                }

                // 4. 解析响应
                JavaType javaType = objectMapper.getTypeFactory()
                        .constructParametricType(OpportunityApiResponse.class, responseType);

                OpportunityApiResponse<T> apiResponse = objectMapper.readValue(responseBody, javaType);

                if (apiResponse.getCode() != 200) {
                    String msg = StringUtils.isNotBlank(apiResponse.getRetMsg()) ? apiResponse.getRetMsg() : apiResponse.getMsg();
                    throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, msg);
                }
                return apiResponse.getData();
            }
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("API调用异常 - URL: {}, 错误: {}", url, e.getMessage(), e);
            throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
        }
    }

    private void logRequest(String url, Object requestBody) {
        if (log.isInfoEnabled()) {
            try {
                log.info("\n======= 请求开始 =======\n" +
                                "API地址: {}\n" +
                                "请求参数: {}\n" +
                                "======= 请求结束 =======",
                        url,
                        objectMapper.writerWithDefaultPrettyPrinter()
                                .writeValueAsString(requestBody));
            } catch (JsonProcessingException e) {
                log.warn("日志JSON序列化失败", e);
            }
        }
    }

    public XgjAccessTokenDTO getXgjAccessToken() {
        String apiUrl = xgjTokenUrl + "/oauth2/token?grant_type=client_credentials&scope=server";
        String clientId = "dmp-join";
        String clientSecret = "dmp20250528";
        String auth = clientId + ":" + clientSecret;
        String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes(StandardCharsets.UTF_8));
        byte[] bytes = new byte[0];
        Request request = new Request.Builder()
                .url(apiUrl)
                .post(RequestBody.create(MediaType.parse("application/json; charset=UTF-8"),bytes))
                .header("Authorization", "Basic " + encodedAuth)
                .build();
        try (Response response = okHttpClient.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
                        "HTTP请求失败，状态码: " + response.code());
            }
            String responseBody = response.body().string();
            XgjAccessTokenDTO xgjAccessTokenDTO = objectMapper.readValue(responseBody, XgjAccessTokenDTO.class);
            return xgjAccessTokenDTO;
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.error("API调用异常 - URL: {}, 错误: {}", apiUrl, e.getMessage(), e);
            throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
        }
    }

    private Request buildRequest(Object requestBody, String url,String accessToken) {

        try {
            Map<String, String> authHeaders = HmacSigner.generateHeaders(
                    xgjUsername, xgjSecret, JSONObject.toJSONString(requestBody));

            log.debug("签名生成 -  签名结果: {}", JSONObject.toJSONString(authHeaders));

            RequestBody body = RequestBody.create(MediaType.parse("application/json"),
                    JSONObject.toJSONString(requestBody)
            );
            log.info(JSONObject.toJSONString(requestBody));
            Request.Builder builder = new Request.Builder()
                    .url(url)
                    .post(body)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Accept", "application/json")
                    .addHeader("x-Date", authHeaders.get("x-Date"))
                    .addHeader("Digest", authHeaders.get("Digest"));
            if (!url.contains("get-token-byshopcode")&& StringUtils.isEmpty(accessToken)){
                builder.addHeader("Authorization", authHeaders.get("Authorization"));
            }
            //新管家特定接口
            if (StringUtils.isNotEmpty(accessToken)){
                builder.addHeader("Authorization", "Bearer "+accessToken);
            }
            return builder.build();
        } catch (Exception e) {
            log.error("签名生成异常", e);
            throw new ServiceException(ErrorCodeEnum.THIRD_API_SIGN_ERROR, e);
        }
    }

    /**
     * 记录响应日志
     */
    private void logResponse(String url, int statusCode, String responseBody) {
        if (log.isInfoEnabled()) {
            try {
                // 尝试美化JSON输出
                Object json = objectMapper.readValue(responseBody, Object.class);
                String prettyResponse = objectMapper.writerWithDefaultPrettyPrinter()
                        .writeValueAsString(json);

                log.info("\n======= 响应开始 =======\n" +
                                "API地址: {}\n" +
                                "HTTP状态码: {}\n" +
                                "响应内容: {}\n" +
                                "======= 响应结束 =======",
                        url,
                        statusCode,
                        prettyResponse);
            } catch (Exception e) {
                // 非JSON响应或解析失败时直接输出原始内容
                log.info("\n======= 响应开始 =======\n" +
                                "API地址: {}\n" +
                                "HTTP状态码: {}\n" +
                                "原始响应: {}\n" +
                                "======= 响应结束 =======",
                        url,
                        statusCode,
                        responseBody);
            }
        }
    }
}
