package com.rj.service;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.rj.config.HxrAdminProperties;
import com.rj.dto.hxr.HxrOrderRow;
import com.rj.dto.hxr.HxrOrderSelectResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Optional;

/**
 * 调用 hxrd 后台订单列表接口并解析 JSON。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HxrAdminOrderSelectService {

    private static final ObjectMapper JSON = new ObjectMapper()
            .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    private final HxrAdminProperties properties;

    /**
     * 拉取订单列表；配置未就绪或 HTTP 非 2xx 时返回 empty。
     * <p>使用 {@link HxrAdminProperties#getOrderSelectUrl()} 原样请求（与定时任务一致）。
     */
    public Optional<HxrOrderSelectResponse> fetchOrderSelect() throws Exception {
        return fetchOrderSelectInternal(properties.getOrderSelectUrl());
    }

    /**
     * 拉取未支付订单，使用 {@link HxrAdminProperties#getOrderSelectUnPayUrl()}。
     */
    public Optional<HxrOrderSelectResponse> fetchUnpaidOrderSelect() throws Exception {
        return fetchOrderSelectInternal(properties.getOrderSelectUnPayUrl());
    }

    /**
     * 按购买时间区间、转卖状态等条件拉取订单列表（在配置的 {@code orderSelectUrl} 上覆盖查询参数）。
     *
     * @param buyTimeStart 购买时间起，对应 {@code buy_time[0]}，可为 null 或空串表示不限制
     * @param buyTimeEnd   购买时间止，对应 {@code buy_time[1]}
     * @param isResell     转卖筛选，对应 {@code is_resell}；为 null 时不改写该参数
     */
    public Optional<HxrOrderSelectResponse> fetchOrderSelect(
            String buyTimeStart, String buyTimeEnd, Integer isResell) throws Exception {
        return fetchOrderSelect(buyTimeStart, buyTimeEnd, isResell, 1);
    }

    /**
     * 按购买时间区间、转卖状态及页码拉取订单列表。
     *
     * @param page 页码，从 1 开始；与配置 URL 中的 {@code limit} 配合分页
     */
    public Optional<HxrOrderSelectResponse> fetchOrderSelect(
            String buyTimeStart, String buyTimeEnd, Integer isResell, int page) throws Exception {
        return fetchOrderSelectInternal(buildOrderSelectUrl(buyTimeStart, buyTimeEnd, isResell, page));
    }

    /**
     * 按购买时间区间及页码拉取未支付订单（{@code status=0}，基于 {@link HxrAdminProperties#getOrderSelectUnPayUrl()}）。
     */
    public Optional<HxrOrderSelectResponse> fetchUnpaidOrderSelect(
            String buyTimeStart, String buyTimeEnd, int page) throws Exception {
        return fetchOrderSelectInternal(
                buildStatusOrderSelectUrl(properties.getOrderSelectUnPayUrl(), buyTimeStart, buyTimeEnd, page));
    }

    /**
     * 按购买时间区间及页码拉取已支付订单（{@code status=1}，基于 {@link HxrAdminProperties#getOrderSelectPaidUrl()}）。
     */
    public Optional<HxrOrderSelectResponse> fetchPaidOrderSelect(
            String buyTimeStart, String buyTimeEnd, int page) throws Exception {
        return fetchOrderSelectInternal(
                buildStatusOrderSelectUrl(properties.getOrderSelectPaidUrl(), buyTimeStart, buyTimeEnd, page));
    }

    private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
        String cookieHeader = properties.resolveCookieHeader();
        if (cookieHeader == null || cookieHeader.isBlank()) {
            log.warn("hxr.admin 未配置 cookie 或 phpsid，跳过拉取");
            return Optional.empty();
        }

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

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(requestUri))
                .timeout(Duration.ofSeconds(160))
                .header("Accept", "application/json, text/javascript, */*; q=0.01")
                .header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
                .header("Cookie", cookieHeader)
                .header("Priority", "u=1, i")
                .header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/order/index")
                .header("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")
                .GET()
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        int status = response.statusCode();
        if (status < 200 || status >= 300) {
            log.warn("hxr admin order/select HTTP {} bodyPrefix={}", status, abbreviate(response.body(), 500));
            return Optional.empty();
        }

        HxrOrderSelectResponse body = JSON.readValue(response.body(), HxrOrderSelectResponse.class);
        if (body.code() != 0) {
            log.warn("hxr admin order/select api code={} msg={}", body.code(), body.msg());
            return Optional.empty();
        }
        return Optional.of(body);
    }

    /**
     * 在 {@link HxrAdminProperties#getOrderSelectUrl()} 上覆盖 {@code buy_time[0]}、{@code buy_time[1]}、{@code is_resell}。
     */
    private String buildOrderSelectUrl(String buyTimeStart, String buyTimeEnd, Integer isResell, int page) {
        UriComponentsBuilder b = UriComponentsBuilder.fromUriString(properties.getOrderSelectUrl());
        b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
        b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
        if (isResell != null) {
            b.replaceQueryParam("is_resell", isResell);
        }
        b.replaceQueryParam("page", Math.max(1, page));
        return b.build().encode().toUriString();
    }

    private String buildStatusOrderSelectUrl(String baseUrl, String buyTimeStart, String buyTimeEnd, int page) {
        UriComponentsBuilder b = UriComponentsBuilder.fromUriString(baseUrl);
        b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
        b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
        b.replaceQueryParam("page", Math.max(1, page));
        return b.build().encode().toUriString();
    }

    /**
     * 拉取并逐条打日志（一行一条 JSON）。
     */
    public void fetchAndLogEachOrder() throws Exception {
        fetchAndLogEachOrder(fetchOrderSelect(), "未寄卖");
    }

    /**
     * 拉取未支付订单（{@code status=0}）并逐条打日志。
     */
    public void fetchAndLogUnpaidOrders() throws Exception {
        fetchAndLogEachOrder(fetchUnpaidOrderSelect(), "未支付");
    }

    private void fetchAndLogEachOrder(
            Optional<HxrOrderSelectResponse> opt, String label) throws Exception {
        if (opt.isEmpty()) {
            return;
        }
        HxrOrderSelectResponse body = opt.get();
        log.info("{} order/select ok count={} allMoney={}", label, body.count(), body.allMoney());
//        for (HxrOrderRow row : body.data()) {
//            log.info("hxr order row {}", JSON.writeValueAsString(row));
//        }
    }

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