package shop.alien.config.feign;

import feign.Response;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.zip.GZIPInputStream;

/**
 * 实现支持 GZip 的解码器
 *
 * @author ssk
 * @version 1.0
 * @date 2025/3/19 9:47
 */
@Slf4j
public class GzipResponseDecoder implements Decoder {

    private final Decoder delegate;

    public GzipResponseDecoder(Decoder delegate) {
        this.delegate = delegate;
    }

    @Override
    public Object decode(Response response, Type type) throws IOException {
        // 判断是否为 GZip 压缩响应
        if (isGzipResponse(response)) {
            try (InputStream is = response.body().asInputStream();
                 GZIPInputStream gzipIs = new GZIPInputStream(is)) {
                // 读取解压后的数据
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int len;
                while ((len = gzipIs.read(buffer)) > 0) {
                    baos.write(buffer, 0, len);
                }
//                // 打印解压后的原始内容
//                String rawBody = baos.toString("UTF-8");
//                System.out.println("[GZip 解压内容] " + rawBody);
                // 构造新的响应对象供后续解析
                Response modifiedResponse = Response.builder()
                        .body(baos.toByteArray())
                        .headers(response.headers())
                        .status(response.status())
                        .request(response.request())
                        .build();
                return delegate.decode(modifiedResponse, type);
            }
        }
        return delegate.decode(response, type);
    }

    /**
     * 判断是否为 GZip 压缩响应
     *
     * @param response 请求内容
     * @return 是否为 GZip 压缩响应
     */
    private boolean isGzipResponse(Response response) {
        Collection<String> strings = response.headers().get("Content-Encoding");
        if (null == strings) {
            return false;
        }
        return response.headers().get("Content-Encoding")
                .stream()
                .anyMatch(enc -> enc.contains("gzip"));
    }

}