package com.rj.service;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.rj.config.HxrAdminProperties;
import com.rj.dto.hxr.HxrLbUserSelectResponse;
import com.rj.dto.hxr.HxrSimpleApiResponse;
import com.rj.dto.hxr.HxrUserRow;
import com.rj.dto.hxr.HxrUserSelectResponse;
import com.rj.util.IsoWorkdayUtils;
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.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;

/**
 * 调用 hxrd 后台用户查询、更新接口（与 {@link HxrAdminOrderSelectService} 共用 {@link HxrAdminProperties} 会话）。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HxrAdminUserService {

    /** 与后台 user/select 默认 limit 一致，用于判断是否还有下一页 */
    public static final int USER_SELECT_PAGE_SIZE = 90;

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

    private static final ObjectMapper USER_JSON = new ObjectMapper()
            .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
            .registerModule(new JavaTimeModule())
            .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

    private static final DateTimeFormatter VIP_TIME_FORMAT =
            DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private final HxrAdminProperties properties;

    /**
     * VIP 到期时间：以 {@code applyDate} 为起算日，若当天为周六、周日则先顺延到下一工作日，再顺延 2 个工作日；
     * 时刻与调用时「当前时刻」的时分秒相同（仅调整日期）。用于开通同事特权。
     */
    public static LocalDateTime computeVipExpireTime(LocalDate applyDate) {
        return computeVipExpireTime(applyDate, 2);
    }

    /**
     * VIP 到期时间：以 {@code applyDate} 为起算日，若当天为周六、周日则先顺延到下一工作日，
     * 再顺延 {@code workdaysAfterAlign} 个工作日；时刻与当前时分秒一致。
     */
    public static LocalDateTime computeVipExpireTime(LocalDate applyDate, int workdaysAfterAlign) {
        if (applyDate == null) {
            throw new IllegalArgumentException("applyDate不能为空");
        }
        if (workdaysAfterAlign < 0) {
            throw new IllegalArgumentException("workdaysAfterAlign不能为负");
        }
        LocalDateTime now = LocalDateTime.now();
        LocalDate d = applyDate;
        while (IsoWorkdayUtils.isWeekend(d)) {
            d = d.plusDays(1);
        }
        for (int i = 0; i < workdaysAfterAlign; i++) {
            d = d.plusDays(1);
            while (IsoWorkdayUtils.isWeekend(d)) {
                d = d.plusDays(1);
            }
        }
        return LocalDateTime.of(d, now.toLocalTime());
    }

    /**
     * VIP 到期时间：以 {@code applyDate} 为起算日顺延 {@code calendarDays} 个自然日，时刻与当前时分秒一致。
     */
    public static LocalDateTime computeVipExpireTimePlusCalendarDays(LocalDate applyDate, int calendarDays) {
        if (applyDate == null) {
            throw new IllegalArgumentException("applyDate不能为空");
        }
        if (calendarDays < 0) {
            throw new IllegalArgumentException("calendarDays不能为负");
        }
        LocalDateTime now = LocalDateTime.now();
        return LocalDateTime.of(applyDate.plusDays(calendarDays), now.toLocalTime());
    }

    /**
     * 分页拉取用户列表，{@code data} 解析为 {@link LbUser}（与 lb_user 字段对应）。
     *
     * @param page 页码，从 1 开始
     */
    public Optional<HxrLbUserSelectResponse> fetchUserSelectPage(int page) throws Exception {
        String cookieHeader = properties.resolveCookieHeader();
        if (cookieHeader == null || cookieHeader.isBlank()) {
            log.warn("hxr.admin 未配置 cookie 或 phpsid，跳过 user/select");
            return Optional.empty();
        }

        String uri = UriComponentsBuilder.fromUriString(properties.getUserSelectUrl())
                .replaceQueryParam("page", Math.max(1, page))
                .replaceQueryParam("limit", USER_SELECT_PAGE_SIZE)
                .replaceQueryParam("mobile", "")
                .replaceQueryParam("id", "")
                .replaceQueryParam("pid", "")
                .build()
                .encode()
                .toUriString();

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

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(uri))
                .timeout(java.time.Duration.ofSeconds(120))
                .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/user/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 user/select HTTP {} page={} bodyPrefix={}",
                    status, page, abbreviate(response.body(), 400));
            return Optional.empty();
        }

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

    /**
     * 调用第三方接口
     * 按手机号查询用户列表，返回第一条。
     */
    public Optional<HxrUserRow> fetchFirstUserByMobile(String mobile) throws Exception {
        String cookieHeader = properties.resolveCookieHeader();
        if (cookieHeader == null || cookieHeader.isBlank()) {
            log.warn("hxr.admin 未配置 cookie 或 phpsid，跳过 user/select");
            return Optional.empty();
        }
        if (mobile == null || mobile.isBlank()) {
            return Optional.empty();
        }

        String uri = UriComponentsBuilder.fromUriString(properties.getUserSelectUrl())
                .replaceQueryParam("mobile", mobile.trim())
                .replaceQueryParam("id", "")
                .replaceQueryParam("pid", "")
                .build()
                .encode()
                .toUriString();

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

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(uri))
                .timeout(java.time.Duration.ofSeconds(120))
                .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/user/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 user/select HTTP {} mobile={} bodyPrefix={}",
                    status, mobile, abbreviate(response.body(), 400));
            return Optional.empty();
        }

        HxrUserSelectResponse body = JSON.readValue(response.body(), HxrUserSelectResponse.class);
        if (body.code() != 0) {
            log.warn("hxr admin user/select api code={} msg={} mobile={}", body.code(), body.msg(), mobile);
            return Optional.empty();
        }
        List<HxrUserRow> data = body.data();
        if (data == null || data.isEmpty()) {
            return Optional.empty();
        }
        HxrUserRow first = data.get(0);
        if (first.id() == null) {
            return Optional.empty();
        }
        return Optional.of(first);
    }

    /**
     * 更新用户 VIP 相关字段（{@code application/x-www-form-urlencoded}）。
     *
     * @return 接口 {@code code==0} 时为 true
     */
    public boolean updateUserVipFields(long userId, int maxOrder, String viptimeFormatted) throws Exception {
        String cookieHeader = properties.resolveCookieHeader();
        if (cookieHeader == null || cookieHeader.isBlank()) {
            log.warn("hxr.admin 未配置 cookie 或 phpsid，跳过 user/update");
            return false;
        }

        String form = buildUpdateFormBody(userId, maxOrder, viptimeFormatted);

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

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(properties.getUserUpdateUrl()))
                .timeout(java.time.Duration.ofSeconds(120))
                .header("Accept", "application/json, text/javascript, */*; q=0.01")
                .header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                .header("Cookie", cookieHeader)
                .header("Referer", "https://hxrdhoutai.hxrdsm.cn/app/admin/user/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")
                .POST(HttpRequest.BodyPublishers.ofString(form, StandardCharsets.UTF_8))
                .build();

        HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
        int status = response.statusCode();
        if (status < 200 || status >= 300) {
            log.warn("hxr admin user/update HTTP {} id={} bodyPrefix={}",
                    status, userId, abbreviate(response.body(), 400));
            return false;
        }

        try {
            HxrSimpleApiResponse api = JSON.readValue(response.body(), HxrSimpleApiResponse.class);
            if (api.code() != 0) {
                log.warn("hxr admin user/update api code={} msg={} id={}", api.code(), api.msg(), userId);
                return false;
            }
            return true;
        } catch (Exception e) {
            log.warn("hxr admin user/update parse body id={} err={} bodyPrefix={}",
                    userId, e.getMessage(), abbreviate(response.body(), 400));
            return false;
        }
    }

    public static String formatVipTime(LocalDateTime t) {
        return t.format(VIP_TIME_FORMAT);
    }

    private static String buildUpdateFormBody(long userId, int maxOrder, String viptimeFormatted) {
        return "id=" + userId
                + "&max_order=" + maxOrder
                + "&is_vip=1"
                + "&is_resell=1"
                + "&status=1"
                + "&viptime=" + URLEncoder.encode(viptimeFormatted, StandardCharsets.UTF_8);
    }

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