package com.qdb.sdk.api;

import com.alibaba.fastjson2.TypeReference;
import com.qdb.sdk.QdbClient;
import com.qdb.sdk.QdbException;
import com.qdb.sdk.model.response.QdbResponse;
import com.qdb.sdk.util.HttpUtil;
import com.qdb.sdk.util.JsonUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 企得宝ERP API 基类
 * <p>
 * 提供通用的API调用方法，所有业务API类需继承此类。
 * 封装了请求执行、响应解析、异常处理等通用逻辑。
 * </p>
 *
 * @author qdb-sdk
 * @version 1.0.0
 */
@Slf4j
public abstract class BaseQdbApi {

    protected final QdbClient client;
    protected final HttpUtil httpUtil;

    protected BaseQdbApi(QdbClient client) {
        this.client = client;
        this.httpUtil = client.getHttpUtil();
    }

    /**
     * 执行API调用（返回泛型响应）
     *
     * @param method    API 方法名
     * @param request   请求参数对象
     * @param <T>       data 字段类型
     * @return 解析后的响应对象
     * @throws QdbException 调用失败时抛出
     */
    protected <T> QdbResponse<T> execute(String method, Object request) throws QdbException {
        return execute(method, request, (Class<T>) null);
    }

    /**
     * 执行API调用（指定data类型）
     *
     * @param method      API 方法名
     * @param request     请求参数对象
     * @param dataClass   data 字段的具体类型，为 null 时不解析 data
     * @param <T>         data 字段类型
     * @return 解析后的响应对象
     * @throws QdbException 调用失败时抛出
     */
    @SuppressWarnings("unchecked")
    protected <T> QdbResponse<T> execute(String method, Object request, Class<T> dataClass) throws QdbException {
        try {
            // 序列化请求参数为 JSON
            String businessJson = request != null ? JsonUtil.toJsonString(request) : "{}";

            // 执行 HTTP 请求
            String responseJson = httpUtil.post(client.getConfig(), method, businessJson);

            log.debug("QDB API 原始响应: {}", responseJson);

            // 解析通用响应
            QdbResponse<T> qdbResponse = JsonUtil.parseObject(responseJson,
                    new TypeReference<QdbResponse<T>>() {});

            if (qdbResponse == null) {
                throw new QdbException("API 响应解析失败，响应为空");
            }

            // 检查业务是否成功
            if (!qdbResponse.isSuccess()) {
                String errorMsg = qdbResponse.getMsg() != null ? qdbResponse.getMsg() : "未知错误";
                String errorCode = qdbResponse.getErrorCode();
                throw new QdbException(errorCode, "API 调用失败 [" + method + "]: " + errorMsg);
            }

            // 如果指定了 dataClass，尝试转换 data 字段
            if (dataClass != null && qdbResponse.getData() != null) {
                String dataJson = JsonUtil.toJsonString(qdbResponse.getData());
                T typedData = JsonUtil.parseObject(dataJson, dataClass);
                qdbResponse.setData(typedData);
            }

            return qdbResponse;

        } catch (QdbException e) {
            throw e;
        } catch (Exception e) {
            log.error("API 调用异常 [{}]", method, e);
            throw new QdbException("API 调用异常 [" + method + "]: " + e.getMessage(), e);
        }
    }

    /**
     * 执行API调用（指定data的TypeReference类型，支持泛型List等）
     *
     * @param method      API 方法名
     * @param request     请求参数对象
     * @param typeRef     data 字段的 TypeReference，用于泛型类型（如 List&lt;SysGoodsVO&gt;）
     * @param <T>         data 字段类型
     * @return 解析后的响应对象
     * @throws QdbException 调用失败时抛出
     */
    @SuppressWarnings("unchecked")
    protected <T> QdbResponse<T> execute(String method, Object request, TypeReference<T> typeRef) throws QdbException {
        try {
            String businessJson = request != null ? JsonUtil.toJsonString(request) : "{}";
            String responseJson = httpUtil.post(client.getConfig(), method, businessJson);

            log.debug("QDB API 原始响应: {}", responseJson);

            QdbResponse<T> qdbResponse = JsonUtil.parseObject(responseJson,
                    new TypeReference<QdbResponse<T>>() {});

            if (qdbResponse == null) {
                throw new QdbException("API 响应解析失败，响应为空");
            }

            if (!qdbResponse.isSuccess()) {
                String errorMsg = qdbResponse.getMsg() != null ? qdbResponse.getMsg() : "未知错误";
                String errorCode = qdbResponse.getErrorCode();
                throw new QdbException(errorCode, "API 调用失败 [" + method + "]: " + errorMsg);
            }

            if (typeRef != null && qdbResponse.getData() != null) {
                String dataJson = JsonUtil.toJsonString(qdbResponse.getData());
                T typedData = JsonUtil.parseObject(dataJson, typeRef);
                qdbResponse.setData(typedData);
            }

            return qdbResponse;

        } catch (QdbException e) {
            throw e;
        } catch (Exception e) {
            log.error("API 调用异常 [{}]", method, e);
            throw new QdbException("API 调用异常 [" + method + "]: " + e.getMessage(), e);
        }
    }
}
