package cn.hztech.sdk.client;

import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 重试拦截器
 *
 * 功能：
 * - 自动重试失败的请求
 * - 可配置重试次数和间隔
 * - 支持指数退避
 */
@Slf4j
public class RetryInterceptor implements Interceptor {

    private final int maxRetries;
    private final long retryInterval;
    private final boolean enableRetry;

    public RetryInterceptor(boolean enableRetry, int maxRetries, long retryInterval) {
        this.enableRetry = enableRetry;
        this.maxRetries = maxRetries;
        this.retryInterval = retryInterval;
    }

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = null;
        IOException lastException = null;

        if (!enableRetry) {
            return chain.proceed(request);
        }

        for (int i = 0; i <= maxRetries; i++) {
            try {
                response = chain.proceed(request);

                if (response.isSuccessful()) {
                    if (i > 0) {
                        log.info("重试成功: 第{}次重试", i);
                    }
                    return response;
                }

                // 如果响应不成功，关闭响应并准备重试
                response.close();

            } catch (IOException e) {
                lastException = e;

                if (i < maxRetries) {
                    long waitTime = retryInterval * (i + 1);
                    log.warn("请求失败，{}ms后进行第{}次重试: {}", waitTime, i + 1, e.getMessage());

                    try {
                        TimeUnit.MILLISECONDS.sleep(waitTime);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw new IOException("重试被中断", ie);
                    }
                }
            }
        }

        // 所有重试都失败
        if (lastException != null) {
            throw lastException;
        }

        return response;
    }
}
