package com.izouma.nineth.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.kevinsawicki.http.HttpRequest;
import com.izouma.nineth.dto.NFT;
import com.izouma.nineth.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.UUID;

@Service
@Slf4j
@AllArgsConstructor
public class HCChainService {

    private static final String baseUrl         = "http://47.107.77.154:10000";
    private static final String adminAddress    = "0x7c3eb0db638057af2cfbb0e7758ae37ff8dcca27";
    private static final String contractAddress = "0xce50d8fb56f8f0d90daa8e11ca1ba125a17ce9a8";

    @Retryable(maxAttempts = 10, backoff = @Backoff(delay = 5000), value = BusinessException.class)
    public String createAccount(Long userId) {
        String body = HttpRequest.get(baseUrl + "/api/privateKey?type=2&userName=" + UUID.randomUUID() + "&signUserId="
                + userId + RandomStringUtils.randomAlphabetic(8) + "&appId=1&returnPrivateKey=true").body();
        JSONObject res = JSON.parseObject(body);
        log.info("create account result: {}", JSON.toJSONString(res, true));
        return res.getString("address");
    }

    @Retryable(maxAttempts = 10, backoff = @Backoff(delay = 5000), value = BusinessException.class)
    public NFT mint(String address, String tokenId) {
        String body = HttpRequest.post(baseUrl + "/api/trans/handle").contentType("application/json")
                .send("{\n" +
                        "    \"groupId\": \"1\",\n" +
                        "    \"user\": \"" + adminAddress + "\",\n" +
                        "    \"funcName\": \"mint\",\n" +
                        "    \"funcParam\": [\n" +
                        "        \"" + address + "\",\n" +
                        "        \"" + new BigInteger(tokenId.replaceAll("^0x", ""), 16).toString(10) + "\"\n" +
                        "    ],\n" +
                        "    \"contractAddress\": \"" + contractAddress + "\",\n" +
                        "    \"contractAbi\": [\n" +
                        "        {\n" +
                        "            \"inputs\": [\n" +
                        "                {\n" +
                        "                    \"internalType\": \"address\",\n" +
                        "                    \"name\": \"to\",\n" +
                        "                    \"type\": \"address\"\n" +
                        "                },\n" +
                        "                {\n" +
                        "                    \"internalType\": \"uint256\",\n" +
                        "                    \"name\": \"tokenId\",\n" +
                        "                    \"type\": \"uint256\"\n" +
                        "                }\n" +
                        "            ],\n" +
                        "            \"name\": \"mint\",\n" +
                        "            \"outputs\": [],\n" +
                        "            \"stateMutability\": \"nonpayable\",\n" +
                        "            \"type\": \"function\"\n" +
                        "        }\n" +
                        "    ],\n" +
                        "    \"useAes\": false,\n" +
                        "    \"useCns\": false,\n" +
                        "    \"cnsName\": \"\"\n" +
                        "}").body();
        JSONObject res = JSON.parseObject(body);
        log.info("mint result: {}", JSON.toJSONString(res, true));
        if ("0x0".equals(res.getString("status"))) {
            BigInteger gas = new BigInteger(res.getString("gasUsed"));
            String txHash = res.getString("transactionHash");
            BigInteger blockNumber = new BigInteger(res.getString("blockNumber"));
            return new NFT(txHash, tokenId, blockNumber, gas);
        } else {
            String msg = res.getString("message");
            throw new BusinessException(msg);
        }
    }
}
