package com.ruoyi.app.utils.linepay;

import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Component
public class ApacheLinePayHttpTransport implements LinePayHttpTransport {

    private static final int MAX_RESPONSE_BYTES = 1024 * 1024;

    @Override
    public LinePayHttpResponse execute(String method, String url, String body,
                                       Map<String, String> headers, int readTimeoutMs) throws Exception {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(5_000)
                .setConnectionRequestTimeout(5_000)
                .setSocketTimeout(readTimeoutMs)
                .build();
        HttpRequestBase request;
        if ("GET".equals(method)) {
            request = new HttpGet(url);
        } else if ("POST".equals(method)) {
            HttpPost post = new HttpPost(url);
            post.setEntity(new StringEntity(body == null ? "" : body,
                    ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8)));
            request = post;
        } else {
            throw new IllegalArgumentException("Unsupported LINE Pay HTTP method");
        }
        request.setConfig(requestConfig);
        headers.forEach(request::setHeader);
        try (CloseableHttpClient client = HttpClients.custom().disableRedirectHandling().build();
             CloseableHttpResponse response = client.execute(request)) {
            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return new LinePayHttpResponse(response.getStatusLine().getStatusCode(), "");
            }
            long length = entity.getContentLength();
            if (length > MAX_RESPONSE_BYTES) {
                throw new IllegalStateException("LINE Pay response is too large");
            }
            byte[] bytes = EntityUtils.toByteArray(entity);
            if (bytes.length > MAX_RESPONSE_BYTES) {
                throw new IllegalStateException("LINE Pay response is too large");
            }
            return new LinePayHttpResponse(response.getStatusLine().getStatusCode(),
                    new String(bytes, StandardCharsets.UTF_8));
        }
    }
}
