package org.jeecg.modules.adweb.dmp.controller;

import com.alibaba.fastjson.JSONObject;

import jakarta.servlet.http.HttpServletRequest;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.FastJsonUtil;
import org.jeecg.modules.adweb.quota.entity.ResourceQuota;
import org.jeecg.modules.adweb.quota.service.IResourceQuotaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;

import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 外贸大数据 - TradeSparq API转发
 *
 * @author wfansh
 */
@RestController
@RequestMapping(TradeSparqController.BASE_PATH)
@Slf4j
public class TradeSparqController {
    static final String BASE_PATH = "/tradesparq";

    @Value("${tradesparq.api.host}")
    private String apiHost;

    @Value("${tradesparq.api.id}")
    private String apiId;

    @Value("${tradesparq.api.secret}")
    private String apiSecret;

    @Autowired private IResourceQuotaService resourceQuotaService;

    private RestTemplate restTemplate = new RestTemplate();

    @PostMapping("/**")
    @ResponseBody
    public Result<JSONObject> forwardPost(
            HttpServletRequest httpRequest, @RequestBody JSONObject requestBody) {
        String uid = ((LoginUser) SecurityUtils.getSubject().getPrincipal()).getId();

        // 0. 校验用户资源额度
        boolean isQuotaLimited = this.isQuotaLimited(httpRequest, requestBody);
        if (isQuotaLimited) {
            Pair<Integer, Integer> customsDataQuota = resourceQuotaService.getCustomsDataQuota(uid);
            if (customsDataQuota.getLeft() <= customsDataQuota.getRight()) {
                log.warn("用户 {} 海关查询资源额度不足", uid);
                return Result.error(
                        String.format(
                                "查询失败。用户资源额度为%d，已使用%d",
                                customsDataQuota.getLeft(), customsDataQuota.getRight()),
                        null);
            }
        }

        // 1. 生成签名
        String sortedValues =
                requestBody.keySet().stream()
                        .sorted()
                        .map(key -> FastJsonUtil.toJSONString(requestBody.get(key)))
                        .collect(Collectors.joining());
        String sign = DigestUtils.md5DigestAsHex((apiSecret + sortedValues).getBytes());

        // 2. 构建并发送POST请求
        String apiPath = httpRequest.getServletPath().split(BASE_PATH)[1]; // 获取TradeSparq API路径
        RequestEntity<String> requestEntity =
                RequestEntity.post(apiHost + apiPath)
                        .headers(this.getHttpHeaders(sign))
                        .body(requestBody.toJSONString());
        try {
            ResponseEntity<JSONObject> responseEntity =
                    restTemplate.exchange(requestEntity, JSONObject.class);

            // 2.1 记录资源额度消耗
            if (isQuotaLimited) {
                resourceQuotaService.consumeCustomsDataQuota(uid);
            }

            return Result.ok(responseEntity.getBody());
        } catch (RestClientResponseException e) {
            return Result.error(e.getStatusCode().value(), e.getMessage());
        }
    }

    @GetMapping("/**")
    @ResponseBody
    public Result<JSONObject> forwardGet(HttpServletRequest httpRequest) {
        // 1. 生成签名
        String apiPath = httpRequest.getServletPath().split(BASE_PATH)[1]; // 获取TradeSparq API路径
        String queryString = httpRequest.getQueryString();
        String apiUrl =
                String.format(
                        "%s%s%s",
                        apiHost,
                        apiPath,
                        StringUtils.isNotBlank(queryString) ? "?" + queryString : "");
        String sign = DigestUtils.md5DigestAsHex((apiSecret + apiUrl).getBytes());

        // 2. 构建并发送GET请求
        RequestEntity<?> requestEntity =
                RequestEntity.get(apiUrl).headers(this.getHttpHeaders(sign)).build();
        try {
            ResponseEntity<JSONObject> responseEntity =
                    restTemplate.exchange(requestEntity, JSONObject.class);
            return Result.ok(responseEntity.getBody());
        } catch (RestClientResponseException e) {
            return Result.error(e.getStatusCode().value(), e.getMessage());
        }
    }

    private HttpHeaders getHttpHeaders(String sign) {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.set("X-API-UID", apiId);
        httpHeaders.set("X-API-REQUEST-SIGN", sign);

        return httpHeaders;
    }

    /** 判断TradeSparq API请求是否受资源额度限制 - {@link ResourceQuota} */
    private boolean isQuotaLimited(HttpServletRequest httpRequest, JSONObject requestBody) {
        // TODO: 假定当前只限制详单查询(/cds_v2/old_api/record)第一页请求
        return StringUtils.endsWithIgnoreCase(
                        httpRequest.getServletPath(), "/cds_v2/old_api/record")
                && Objects.equals(requestBody.getInteger("page"), 1);
    }
}
