package com.crm.ucard.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.dto.base.*;
import com.crm.rely.backend.core.dto.ucard.vaultody.VaultodyDepositAddressDto;
import com.crm.rely.backend.core.entity.ucard.crypto.currency.vaultody.*;
import com.crm.rely.backend.core.pojo.table.SysConfigTable;
import com.crm.rely.backend.core.pojo.table.ucard.CardWalletAddressTable;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.util.HttpUtil;
import com.crm.ucard.config.VaultodyConfig;
import com.crm.ucard.dao.mapper.CardWalletAddressMapper;
import com.crm.ucard.dao.repository.CardWalletAddressRepository;
import com.crm.ucard.service.SysConfigService;
import com.crm.ucard.service.VaultodyService;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Connection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
@Service
public class VaultodyServiceImpl implements VaultodyService {

    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private CardWalletAddressRepository walletAddressRepository;
    @Autowired
    private CardWalletAddressMapper walletAddressMapper;

    public String getPath(String pathTemplate, String vaultId, String blockchain, String network) {
//        String pathTemplate = "/vaults/%s/%s/%s/addresses";
        String actualPath = String.format(pathTemplate, vaultId, blockchain, network);
        return actualPath;
    }

    public VaultodyConfig getVaultodyConfig() throws ServiceException {
        SysConfigTable sysConfigTable = sysConfigService.getByCode(Constants.VAULTODY_CONFIG);
        if (sysConfigTable == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        VaultodyConfig vaultodyConfig = JSON.parseObject(sysConfigTable.getValue(), VaultodyConfig.class);
        return vaultodyConfig;
    }

    public static VaultodyConfig getConfig() {
        VaultodyConfig config = new VaultodyConfig();
        config.setApiKey("f5dc4ad66d1dd85b15f46cdc570b8a13e9e8b825");
        config.setApiSecret("x+D75AW10JH2xg==");
        config.setPassphrase("Gaochao@7starpro.com");
        config.setMethod("POST");
        config.setNetwork("sepolia");
        config.setVaultId("691ad28a059b380007af005c");
        config.setBaseUrl("https://rest.vaultody.com");
        config.setAddressPathTemplate("/vaults/%s/%s/%s/addresses");
        return config;
    }


    public static String getSignature(String message, String apiSecret) {
        try {
            byte[] decodedSecret = Base64.getDecoder().decode(apiSecret);
            Mac mac = Mac.getInstance("HmacSHA256");
            SecretKeySpec secretKeySpec = new SecretKeySpec(decodedSecret, "HmacSHA256");
            mac.init(secretKeySpec);
            byte[] hash = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));

            return Base64.getEncoder().encodeToString(hash);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Coin
     */
    public static void main4(String[] args) {
        try {
            // ------------------ 配置 ------------------
            String apiKey = "f5dc4ad66d1dd85b15f46cdc570b8a13e9e8b825";
            String apiSecret = "x+D75AW10JH2xg==";        // Base64编码的secret
            String passphrase = "Gaochao@7starpro.com";
            String method = "POST";
            String requestPath = "/vaults/691c1b59f19f990007704efe/ethereum/sepolia/transaction-requests";
            String baseUrl = "https://rest.vaultody.com";
            List<Map<String, Object>> recipientsList = new ArrayList<>();
            List<Map<String, Object>> sendersList = new ArrayList<>();
            Map<String, Object> recipientsMap = new HashMap<>();
            recipientsMap.put("address", "0x63f25f2ef69605ac3e60e549adc6854d3a4e8f61");
            recipientsMap.put("amount", "0.0001");
            recipientsList.add(recipientsMap);
            Map<String, Object> sendersMap = new HashMap<>();
            sendersMap.put("address", "0xa9160a2eb91ccce4ab44c532fc91a78ac21d806f");
            sendersList.add(sendersMap);

            Map<String, Object> labelMap = new HashMap<>();
            labelMap.put("feePriority", "slow");
//            labelMap.put("maxFee", "0.003");
            labelMap.put("note", "yourAdditionalInformationhere");
//            labelMap.put("prepareStrategy", "minimize-dust");
            labelMap.put("recipients", recipientsList);
            labelMap.put("senders", sendersList);
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("item", labelMap);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("data", itemMap);
            paramMap.put("context", "token-transaction-requests");

            // POST JSON body
            String body = "{\"data\":{\"item\":{\"label\":\"0a3b142570574b92a029bce7e2b0cb7b\"}},\"context\":\"yourExampleString\"}";
            String query = "{}"; // POST 时 query 通常为空，否则按接口要求填写

            // ------------------ 时间戳（秒） ------------------
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

            // ------------------ 构建消息用于签名 ------------------
            String message = timestamp + method + requestPath + JSON.toJSONString(paramMap) + query;

            String signature = getSignature(message, apiSecret);
            System.out.println("Signature: " + signature);
            Map<String, String> headers = new HashMap<>();
            headers.put("x-api-key", apiKey);
            headers.put("x-api-sign", signature);
            headers.put("x-api-timestamp", timestamp);
            headers.put("x-api-passphrase", passphrase);
            headers.put("Content-Type", "application/json");

            try {
                Connection.Response response = HttpUtil.post(baseUrl + requestPath, headers, JSON.toJSONString(paramMap));
                System.out.println(response.statusCode());
                System.out.println(JSON.toJSONString(response.body()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * token
     */
    public static void main3(String[] args) {
        try {
            // ------------------ 配置 ------------------
            String apiKey = "f5dc4ad66d1dd85b15f46cdc570b8a13e9e8b825";
            String apiSecret = "x+D75AW10JH2xg==";        // Base64编码的secret
            String passphrase = "Gaochao@7starpro.com";
            String method = "POST";
            String requestPath = "/vaults/691c1b59f19f990007704efe/ethereum/sepolia/token-transaction-requests";
            String baseUrl = "https://rest.vaultody.com";

            Map<String, Object> labelMap = new HashMap<>();
            labelMap.put("amount", "0.0001");
            labelMap.put("contractAddress", "0xdac17f958d2ee523a2206206994597c13d831ec7");
            labelMap.put("feePriority", "slow");
            labelMap.put("fromAddress", "0xa9160a2eb91ccce4ab44c532fc91a78ac21d806f");
//            labelMap.put("maxFee", "0.004");
//            labelMap.put("note", "yourAdditionalInformationhere");
            labelMap.put("recipientAddress", "0x63f25f2ef69605ac3e60e549adc6854d3a4e8f61");
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("item", labelMap);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("data", itemMap);
            paramMap.put("context", "token-transaction-requests");

            // POST JSON body
            String body = "{\"data\":{\"item\":{\"label\":\"0a3b142570574b92a029bce7e2b0cb7b\"}},\"context\":\"yourExampleString\"}";
            String query = "{}"; // POST 时 query 通常为空，否则按接口要求填写

            // ------------------ 时间戳（秒） ------------------
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

            // ------------------ 构建消息用于签名 ------------------
            String message = timestamp + method + requestPath + JSON.toJSONString(paramMap) + query;

            String signature = getSignature(message, apiSecret);
            System.out.println("Signature: " + signature);
            Map<String, String> headers = new HashMap<>();
            headers.put("x-api-key", apiKey);
            headers.put("x-api-sign", signature);
            headers.put("x-api-timestamp", timestamp);
            headers.put("x-api-passphrase", passphrase);
            headers.put("Content-Type", "application/json");

            try {
                Connection.Response response = HttpUtil.post(baseUrl + requestPath, headers, JSON.toJSONString(paramMap));
                System.out.println(response.statusCode());
                System.out.println(JSON.toJSONString(response.body()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * address
     */
    public static void main(String[] args) {
        try {
            // ------------------ 配置 ------------------
            String apiKey = "f5dc4ad66d1dd85b15f46cdc570b8a13e9e8b825";
            String apiSecret = "x+D75AW10JH2xg==";        // Base64编码的secret
            String passphrase = "Gaochao@7starpro.com";
            String method = "POST";
            String requestPath = "/vaults/691ad28a059b380007af005c/ethereum/sepolia/addresses";
            String baseUrl = "https://rest.vaultody.com";

            Map<String, Object> labelMap = new HashMap<>();
            labelMap.put("label", "0a3b142570574b92a029bce7e2b0cb7b");
            Map<String, Object> itemMap = new HashMap<>();
            itemMap.put("item", labelMap);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("data", itemMap);
            paramMap.put("context", "address");

            // POST JSON body
            String body = "{\"data\":{\"item\":{\"label\":\"0a3b142570574b92a029bce7e2b0cb7b\"}},\"context\":\"yourExampleString\"}";
            String query = "{}"; // POST 时 query 通常为空，否则按接口要求填写

            // ------------------ 时间戳（秒） ------------------
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

            // ------------------ 构建消息用于签名 ------------------
            String message = timestamp + method + requestPath + body + query;

            // ------------------ HMAC-SHA256 签名 ------------------
//            byte[] decodedSecret = Base64.getDecoder().decode(apiSecret);
//            Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
//            SecretKeySpec secretKeySpec = new SecretKeySpec(decodedSecret, "HmacSHA256");
//            sha256_HMAC.init(secretKeySpec);
//            byte[] hash = sha256_HMAC.doFinal(message.getBytes(StandardCharsets.UTF_8));
//
//            String signatureB64 = Base64.getEncoder().encodeToString(hash);
            String signature = getSignature(message, apiSecret);
//            System.out.println("signatureB64: " + signatureB64);
            System.out.println("Signature: " + signature);
            Map<String, String> headers = new HashMap<>();
            headers.put("x-api-key", apiKey);
            headers.put("x-api-sign", signature);
            headers.put("x-api-timestamp", timestamp);
            headers.put("x-api-passphrase", passphrase);
            headers.put("Content-Type", "application/json");

            try {
                Connection.Response response = HttpUtil.post(baseUrl + requestPath, headers, body);
                System.out.println(response.statusCode());
                System.out.println(JSON.toJSONString(response.body()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
//
//            // ------------------ 发起 POST 请求 ------------------
//            URL url = new URL(baseUrl + requestPath);
//            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//            conn.setRequestMethod("POST");
//
//            conn.setDoOutput(true); // 允许写入 body
//
//            // 设置请求头
//            conn.setRequestProperty("x-api-key", apiKey);
//            conn.setRequestProperty("x-api-sign", signatureB64);
//            conn.setRequestProperty("x-api-timestamp", timestamp);
//            conn.setRequestProperty("x-api-passphrase", passphrase);
//            conn.setRequestProperty("Content-Type", "application/json");
//
//
//            // 写入 JSON body
//            try (OutputStream os = conn.getOutputStream()) {
//                os.write(body.getBytes(StandardCharsets.UTF_8));
//                os.flush();
//            }
//
//            // ------------------ 读取响应 ------------------
//            int responseCode = conn.getResponseCode();
//            BufferedReader in = new BufferedReader(new InputStreamReader(
//                    responseCode >= 200 && responseCode < 300 ? conn.getInputStream() : conn.getErrorStream()
//            ));
//            String inputLine;
//            StringBuilder response = new StringBuilder();
//
//            while ((inputLine = in.readLine()) != null) {
//                response.append(inputLine);
//            }
//            in.close();
//
//            System.out.println("Response Code: " + responseCode);
//            System.out.println("Response Body: " + response.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成钱包地址
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto generateDepositAddress(VaultodyGenerateDepositAddressEntity entity) throws Exception {
        // 查询数据库是否有未重置的地址
        CardWalletAddressTable table = walletAddressRepository.findFirstByUniqueIdAndBlockchainAndIsReset(entity.getUniqueId(), entity.getBlockchain(), false);
        if (table != null) {
            return BaseResultDto.success(Constants.SUCCESS, table.getAddress());
        }
        VaultodyConfig config = getVaultodyConfig();
//        VaultodyConfig config = getConfig();
        String requestPath = this.getPath(config.getAddressPathTemplate(), config.getVaultId(), entity.getBlockchain(), config.getNetwork());
        String apiKey = config.getApiKey();
        String apiSecret = config.getApiSecret();
        String passphrase = config.getPassphrase();
        String method = config.getMethod();
        String baseUrl = config.getBaseUrl();

        Map<String, Object> labelMap = new HashMap<>();
        labelMap.put("label", entity.getUniqueId());
        Map<String, Object> itemMap = new HashMap<>();
        itemMap.put("item", labelMap);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("data", itemMap);

        // POST JSON body
        String body = JSON.toJSONString(paramMap);
        String query = "{}"; // POST 时 query 通常为空，否则按接口要求填写

        // ------------------ 时间戳（秒） ------------------
        String timestamp = String.valueOf(System.currentTimeMillis() / 1000);

        // ------------------ 构建消息用于签名 ------------------
        String message = timestamp + method + requestPath + body + query;

        String signature = getSignature(message, apiSecret);
        System.out.println("Signature: " + signature);
        Map<String, String> headers = new HashMap<>();
        headers.put("x-api-key", apiKey);
        headers.put("x-api-sign", signature);
        headers.put("x-api-timestamp", timestamp);
        headers.put("x-api-passphrase", passphrase);
        headers.put("Content-Type", "application/json");

        Connection.Response response = HttpUtil.post(baseUrl + requestPath, headers, body);
        if (response.statusCode() != 200) {
            log.error("用户: {} 钱包地址生成失败: {}", entity.getUniqueId(), response.body());
            throw new ServiceException("钱包地址生成失败");
        }
        // 解析 JSON 字符串
        JSONObject jsonObject = JSON.parseObject(response.body());

        // 获取 address 和 label 字段
        String address = jsonObject.getJSONObject("data").getJSONObject("item").getString("address");
        // 保存数据库数据
        table = new CardWalletAddressTable();
        table.setAddress(address);
        table.setBlockchain(entity.getBlockchain());
        table.setUniqueId(entity.getUniqueId());
        table.setIsReset(false);
        table.setAddTime(new Date());
        walletAddressRepository.save(table);
        return BaseResultDto.success(Constants.SUCCESS, address);
    }

    /**
     * 钱包地址分页列表
     */
    @Override
    public ResultWithPagerDto<VaultodyDepositAddressDto> getDepositAddressPage(VaultodyDepositAddressPageEntity entity) throws ServiceException {
        try {
            // 获取总数
            Integer count = walletAddressMapper.countList(entity);
            PageDto pageDto = PageDto.format(entity, count);
            if (count == null || count <= 0) {
                return ResultWithPagerDto.success(pageDto);
            }

            List<VaultodyDepositAddressDto> dtos = walletAddressMapper.pageList(entity);
            return ResultWithPagerDto.success(pageDto, dtos);
        } catch (Exception e) {
            log.error("获取钱包地址分页列表失败", e);
            throw new ServiceException("获取钱包地址分页列表失败");
        }
    }

    /**
     * 重置钱包地址
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResultDto resetDepositAddress(VaultodyResetDepositAddressEntity entity) throws ServiceException {
        CardWalletAddressTable table = walletAddressRepository.findFirstById(entity.getId());
        if (table == null) {
            return BaseResultDto.error("钱包地址不存在");
        }
        if (table.getIsReset()) {
            return BaseResultDto.error("钱包地址已重置");
        }
        table.setIsReset(true);
        walletAddressRepository.save(table);
        return BaseResultDto.success();
    }


}
