package com.rj.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.rj.config.HxrAdminProperties;
import com.rj.util.HxrGoodsSignUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 调用 hxrd {@code POST /api/order/buy} 抢购（请求头 {@code token} + {@code S/T/N} 鉴权）。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HxrAdminBuyService {

    private static final SecureRandom RANDOM = new SecureRandom();

    private static final String USER_AGENT =
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                    + "(KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0";

    private static final ObjectMapper JSON = new ObjectMapper()
            .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

    private final HxrAdminProperties properties;

    /**
     * @return {@code apiCode} 为 -1 表示 HTTP 或解析失败
     */
    public BuyApiResult buy(long goodsId, long sellerId, String token) throws Exception {
        String resolvedToken = resolveToken(token);
        if (resolvedToken == null) {
            return BuyApiResult.failure(-1, "未提供 token 且未配置 hxr.admin.goods-api-token");
        }
        String appStr = properties.getGoodsApiAppStr();
        if (appStr == null || appStr.isBlank()) {
            return BuyApiResult.failure(-1, "未配置 hxr.admin.goods-api-app-str");
        }

        long timestamp = System.currentTimeMillis() / 1000;
        String noncestr = randomNoncestr();
        Map<String, Object> signParams = new LinkedHashMap<>();
        signParams.put("id", goodsId);
        signParams.put("seller_id", sellerId);
        signParams.put("timestamp", timestamp);
        signParams.put("noncestr", noncestr);
        String sign = HxrGoodsSignUtil.computeSign(signParams, appStr.trim());

        Map<String, Object> body = new LinkedHashMap<>();
        body.put("id", goodsId);
        body.put("seller_id", sellerId);
        String bodyJson = JSON.writeValueAsString(body);

        HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(60))
                .followRedirects(HttpClient.Redirect.NORMAL)
                .build();

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(properties.getBuyApiUrl()))
                .timeout(Duration.ofSeconds(120))
                .header("Accept", "application/json,*/*")
                .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
                .header("Content-Type", "application/json;charset=UTF-8")
                .header("Origin", properties.getGoodsApiOrigin())
                .header("Referer", properties.getGoodsApiReferer())
                .header("User-Agent", USER_AGENT)
                .header("token", resolvedToken)
                .header("S", sign)
                .header("T", String.valueOf(timestamp))
                .header("N", noncestr)
                .POST(HttpRequest.BodyPublishers.ofString(bodyJson, StandardCharsets.UTF_8))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        int status = response.statusCode();
        String bodyText = response.body();
        if (status < 200 || status >= 300) {
            log.warn("hxr /api/order/buy HTTP {} id={} sellerId={} bodyPrefix={}",
                    status, goodsId, sellerId, abbreviate(bodyText, 400));
            return BuyApiResult.failure(-1, "HTTP " + status);
        }
        if (bodyText == null || bodyText.isBlank()) {
            log.warn("hxr /api/order/buy empty body id={} sellerId={}", goodsId, sellerId);
            return BuyApiResult.failure(-1, "响应为空");
        }

        JsonNode root = JSON.readTree(bodyText);
        int code = root.path("code").asInt(-1);
        String msg = root.path("msg").asText("");
        if (code != 0) {
            log.warn("hxr /api/order/buy api code={} msg={} id={} sellerId={}",
                    code, msg, goodsId, sellerId);
        }
        return new BuyApiResult(code == 0, code, msg);
    }

    /** 优先使用入参 token，否则回退到配置 {@code goods-api-token}。 */
    private String resolveToken(String token) {
        if (token != null && !token.isBlank()) {
            return token.trim();
        }
        String configured = properties.getGoodsApiToken();
        if (configured != null && !configured.isBlank()) {
            return configured.trim();
        }
        return null;
    }

    public record BuyApiResult(boolean success, int apiCode, String apiMsg) {

        public static BuyApiResult failure(int code, String msg) {
            return new BuyApiResult(false, code, msg);
        }
    }

    private static String randomNoncestr() {
        String base36 = Long.toUnsignedString(Math.abs(RANDOM.nextLong()), 36);
        if (base36.length() >= 5) {
            return base36.substring(base36.length() - 5);
        }
        StringBuilder sb = new StringBuilder(base36);
        while (sb.length() < 5) {
            sb.append(Integer.toString(RANDOM.nextInt(36), 36));
        }
        return sb.toString();
    }

    private static String abbreviate(String s, int maxLen) {
        if (s == null) {
            return "";
        }
        return s.length() <= maxLen ? s : s.substring(0, maxLen) + "...";
    }
}
