package org.dromara.system.zwy.client;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.system.zwy.properties.EncryptProperties;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.StandardCharsets;
import java.util.UUID;
import java.util.Base64;

/**
 * 解密服务，使用aop的方式
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DecryptClient {

    private final EncryptProperties properties;
    private final EncryptTokenClient encryptTokenClient;
    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper objectMapper = new ObjectMapper();

    public String decrypt(String ciphertextBlob) {
        try {
            log.info("准备解密，密文长度：{} 字符", ciphertextBlob != null ? ciphertextBlob.length() : 0);

            MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
            formData.add("ciphertextBlob", ciphertextBlob);

            HttpHeaders headers = buildHeaders(formData);
            HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(formData, headers);
            String url = properties.getServerUrl() + "/key/v3/decrypt";

            log.info("调用解密服务，URL: {}, 请求参数 ciphertextBlob hash: {}", url, ciphertextBlob != null ? ciphertextBlob.hashCode() : "null");

            ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
            String responseBody = response.getBody();

            log.debug("解密服务响应体：{}", responseBody);

            JsonNode root = objectMapper.readTree(responseBody);
            int code = root.path("code").asInt();
            String msg = root.path("msg").asText();

            if (code != 0) {
                log.warn("解密服务响应失败，code: {}, msg: {}, body: {}", code, msg, responseBody);
                throw new RuntimeException("调用解密服务失败，code=" + code + "，msg=" + msg);
            }

            String base64Plain = root.path("data").path("plaintext").asText();
            if (base64Plain == null || base64Plain.isEmpty()) {
                log.error("解密服务响应中 plaintext 字段为空，原始响应：{}", responseBody);
                throw new RuntimeException("解密服务响应中 plaintext 字段为空");
            }

            String plaintext = new String(Base64.getDecoder().decode(base64Plain), StandardCharsets.UTF_8);
            log.info("解密成功，明文长度：{} 字符", plaintext.length());
            log.debug("解密后明文内容：{}", plaintext);

            return plaintext;
        } catch (Exception e) {
            log.error("调用解密服务失败，密文 hash: {}", ciphertextBlob != null ? ciphertextBlob.hashCode() : "null", e);
            throw new RuntimeException("调用解密服务失败", e);
        }
    }



    private HttpHeaders buildHeaders(MultiValueMap<String, String> params) {
        String appId = properties.getAppId();

        // 生成 timestamp 和 nonce
        String timestamp = String.valueOf(System.currentTimeMillis());
        String nonce = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);

        // 获取应用 Token（从缓存或刷新）
        String gateWayToken = encryptTokenClient.getAppToken();

        // 构造 Headers
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("appId", appId);
        headers.add("timestamp", timestamp);
        headers.add("nonce", nonce);
        headers.add("gateWayToken", gateWayToken);

        // 打印调试日志
        log.debug("构建请求 Headers: appId={}, timestamp={}, nonce={}, gateWayToken={}", appId, timestamp, nonce, gateWayToken);

        return headers;
    }

}

