package com.liquidnet.service.adam.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.liquidnet.commons.lang.util.CollectionUtil;
import com.liquidnet.commons.lang.util.CurrentUtil;
import com.liquidnet.commons.lang.util.HttpUtil;
import com.liquidnet.commons.lang.util.JsonUtils;
import com.liquidnet.service.adam.constant.AdamEnum;
import com.liquidnet.service.adam.dto.vo.AdamRealInfoVo;
import com.liquidnet.service.adam.dto.vo.AdamUserBizAcctVo;
import com.liquidnet.service.adam.service.AdamRdmService;
import com.liquidnet.service.adam.service.IAdamUserBusiAcctService;
import com.liquidnet.service.adam.service.IAdamUserService;
import com.liquidnet.service.adam.util.QueueUtils;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.constant.MQConst;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

@Slf4j
@Service
public class AdamUserBusiAcctServiceImpl implements IAdamUserBusiAcctService {
    @Autowired
    private QueueUtils queueUtils;
    @Autowired
    private AdamRdmService adamRdmService;
    @Autowired
    private IAdamUserService adamUserService;


    @Value("${liquidnet.service.galaxy.url}")
    private String serviceGalaxyUrl;
    @Value("${liquidnet.service.goblin.url}")
    private String serviceGoblinUrl;

    @Override
    public ResponseDto<AdamUserBizAcctVo> openAccount(String uid, String bizCode, String name, String idCard, String mobile) {
        List<AdamUserBizAcctVo> userBizAcctVoList = adamRdmService.getBizAcctVosByUid(uid);
        if (!CollectionUtils.isEmpty(userBizAcctVoList)) {
            Optional<AdamUserBizAcctVo> optional = userBizAcctVoList.stream().filter(r -> r.getBizCode().equals(bizCode)).findAny();
            if (optional.isPresent()) return ResponseDto.success(optional.get());
        }

        if (AdamEnum.BizAcct.NFT_ZX.name().equals(bizCode)) {
            boolean inputNameIdCardInvalidFlg = StringUtils.isBlank(name) || name.contains("*") || StringUtils.isBlank(idCard) || idCard.contains("*");
            AdamRealInfoVo realInfoVo = adamRdmService.getRealInfoVoByUidPlain(uid);
            if (null != realInfoVo) {// 账号已实名
                if (realInfoVo.getNode() == 2) {// 二要素认证的
                    if (inputNameIdCardInvalidFlg) {
                        name = realInfoVo.getName();
                        idCard = realInfoVo.getIdCard();
                    }
                    adamUserService.identityForUpsert(uid, name, idCard, mobile, true);
                } else {// 三要素认证的
                    name = realInfoVo.getName();
                    idCard = realInfoVo.getIdCard();
                }
            } else {// 账号未实名
                if (inputNameIdCardInvalidFlg) {
                    return ResponseDto.failure(ErrorMapping.get("10101"));
                }
                adamUserService.identityForUpsert(uid, name, idCard, mobile, false);
            }

            ResponseDto<AdamUserBizAcctVo> responseDto = this.openAccountForNftZXin(uid, name, idCard, mobile);
            if (responseDto.isSuccess()) {
                AdamUserBizAcctVo userBizAcctVo = responseDto.getData();
                adamRdmService.addBizAcctVoByUid(uid, userBizAcctVoList, userBizAcctVo);

//                LinkedList<String> toMqSqls = CollectionUtil.linkedListString();
//                toMqSqls.add(SqlMapping.get("adam_user_busi_acct.add"));
//                LinkedList<Object[]> initUserBusiAcctObjs = CollectionUtil.linkedListObjectArr();
//                initUserBusiAcctObjs.add(new Object[]{
//                        uid, AdamEnum.BizAcct.NFT_ZX.name(), userBizAcctVo.getUuid(), null, null, 1, LocalDateTime.now()
//                });
                queueUtils.sendMsgByRedis(MQConst.AdamQueue.SQL_UCENTER.getKey(),
                        SqlMapping.get("adam_user_busi_acct.add", uid, AdamEnum.BizAcct.NFT_ZX.name(), userBizAcctVo.getUuid(), null, null, 1, LocalDateTime.now())
                );

                try {
                    LinkedMultiValueMap<String, String> paramsMap = CollectionUtil.linkedMultiValueMapStringString();
                    paramsMap.add("userId", uid);
                    HttpUtil.post(serviceGoblinUrl + "/goblin/rsc/nft/sync/acc", paramsMap);
                } catch (Exception e) {
                    log.error("Ex.开通业务账号:同步Goblin缓存异常[UID={},URL={}],ex:{}", uid, serviceGoblinUrl, e.getMessage());
                }
            }
            return responseDto;
        }
        log.warn("#开通业务账号:无效的业务码[UID={},bizCode={}]", bizCode, uid);
        return ResponseDto.failure();
    }

    /**
     * 数字藏品账号开通-至信链
     *
     * @param uid
     * @param name
     * @param idCard
     * @param mobile
     * @return ResponseDto<AdamUserBizAcctVo>
     */
    private ResponseDto<AdamUserBizAcctVo> openAccountForNftZXin(String uid, String name, String idCard, String mobile) {
        ObjectNode postBodyNode = JsonUtils.OM().createObjectNode();
        postBodyNode.put("routerType", "zxinchain");
        postBodyNode.put("idCardType", "1");
        postBodyNode.put("idCard", idCard);
        postBodyNode.put("userName", name);
        postBodyNode.put("mobile", mobile);
        postBodyNode.put("userId", uid);
        String postUrl = serviceGalaxyUrl + "/galaxy/user/register", blockChainAddress;
        try {
            String postRespStr = HttpUtil.postRaw(postUrl, postBodyNode.toString(), null);
            JsonNode postRespJNode = JsonUtils.fromJson(postRespStr, JsonNode.class), postRespCode;
            if (null == postRespJNode || null == (postRespCode = postRespJNode.get("code")) || !postRespCode.asText().equals("0")) {
                log.warn("#开通业务账号:至信数字藏品账号开通失败[postBody={},postRespStr={}]", postBodyNode, postRespStr);
                return ResponseDto.failure(ErrorMapping.get("10113"));
            }
            JsonNode postRespDataJNode = postRespJNode.get("data");
            blockChainAddress = postRespDataJNode.get("blockChainAddress").asText();
        } catch (Exception e) {
            log.error("Ex.开通业务账号:至信数字藏品账号开通请求异常[url={},postBody={}],ex:{}", postUrl, postBodyNode, e.getMessage());
            return ResponseDto.failure(ErrorMapping.get("10113"));
        }

        AdamUserBizAcctVo userBizAcctVo = AdamUserBizAcctVo.getNew();
        userBizAcctVo.setBizCode(AdamEnum.BizAcct.NFT_ZX.name());
        userBizAcctVo.setState(AdamEnum.BizAcctStatus.OPENED.getVal());
        userBizAcctVo.setUuid(blockChainAddress);
        return ResponseDto.success(userBizAcctVo);
    }
}
