package com.friday.custody.service.trustService.haitong.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.friday.custody.dto.HaitongAppSecretDTO;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.entity.InvokeRecordEntity;
import com.friday.custody.service.basicService.InvokeRecordService;
import com.friday.custody.service.basicService.PullDataFailureLogService;
import com.friday.custody.service.trustService.haitong.common.HaiTongConstants;
import com.friday.custody.service.trustService.haitong.dto.HaiTongBaseDto;
import com.friday.custody.service.trustService.haitong.dto.HaiTongRemoteDto;
import com.friday.custody.service.trustService.htsc.utils.HTSCGetDataUtil;
import com.friday.custody.utils.PullDataFailureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @Description
 * @Author wulifeng
 * @Date: 2022/3/22
 */
@Slf4j
@Service("haiTongHttpUtil")
public class HaiTongHttpUtil {
    @Autowired
    private HTSCGetDataUtil hTSCGetDataUtil ;

    private RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;

    @Autowired
    private InvokeRecordService invokeRecordService;
    @Value("${custody.remote.url.haitong.haiTongUrlPrefix}")
    private String preffixUrl;

    public Map<String,Object> sendMessage(HaitongAppSecretDTO haitongAppSecretDTO, String json0, String api, TenantEscrowAuthorizationInfoDto tenant, String trustNo) {
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("HaiTongHttpUtil_sendMessage 睡眠被打断了!");
        }
        log.info("海通HaiTongHttpUtil的sendMessage入参情况为json0={},api={},tenant={},trustNo={}",json0,api,tenant,trustNo);
        HttpHeaders headers = new HttpHeaders();
        List<JSONObject> result = new ArrayList<>();
        Map mapReturn =new HashMap();
        HaiTongBaseDto baseResultDto = new HaiTongBaseDto();
        String errorMsg = null;
        try {
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());

            String paramAfterEncrypt = CipherUtil.rsaEncryptToBase64(haitongAppSecretDTO.getPublicKey(), json0);

            Date date = new Date();
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            String timeStamp = format.format(date);
            String clientId = haitongAppSecretDTO.getClientId();
            String license = haitongAppSecretDTO.getLicense();

            String privateKey = haitongAppSecretDTO.getPrivateKey();
            String appSecret = haitongAppSecretDTO.getAppSecret();


            String  appSigned= "bizParam="+paramAfterEncrypt+"&businessLicense="+license+"&clientid="+clientId+"&timeStamp="+timeStamp;
            log.info("加密前appSigned "+appSigned);
            String appSignedAfterSha256 = SignatureUtil.sha256(appSigned,appSecret);

            Map map = new HashMap();
            map.put("clientid",clientId);
            map.put("timeStamp",timeStamp);
            map.put("businessLicense",license);
            map.put("bizParam",paramAfterEncrypt);
            map.put("appSigned",appSignedAfterSha256);
            String jsonReq = JSON.toJSONString(map);


            String urlWithParam = preffixUrl + api +"?clientid="+clientId;
            log.info("urlWithParam = " + urlWithParam);



            HttpEntity<String> httpEntity = new HttpEntity<>(jsonReq, headers);
            ResponseEntity<HaiTongRemoteDto> responseEntity = restTemplate.postForEntity(urlWithParam, httpEntity, HaiTongRemoteDto.class);
            HaiTongRemoteDto bodyFromRemote = responseEntity.getBody();
            int i = 0;
            if(bodyFromRemote == null){
                log.error("bodyFromRemote为空");
            }else if("200".equals(bodyFromRemote.getCode())){
                String returnBodyAfterCipher = CipherUtil.rsaDecryptFromBase64(privateKey, bodyFromRemote.getData());
                log.info("返回内容为"+returnBodyAfterCipher);

                //如果调 jjtgb/zjqs/queryBankAccBal ，/jjtgb/ta/queryFundOpenInfo 直接返回结果数组
                if(urlWithParam.contains(HaiTongConstants.MJ_ACCOUNT_BALANCE_INFO)
                        || urlWithParam.contains(HaiTongConstants.FUND_OPEN_INFO)
                        || urlWithParam.contains(HaiTongConstants.RAISING_ACCOUNT_FLOW)){
                    List<JSONObject> jsonObjects = JSON.parseArray(returnBodyAfterCipher, JSONObject.class);
                    baseResultDto.setResult(jsonObjects);
                    baseResultDto.setTotalCount("1");
                }else{
                    baseResultDto = JSON.parseObject(returnBodyAfterCipher, HaiTongBaseDto.class);
                }
                if(baseResultDto==null){
                    baseResultDto= new HaiTongBaseDto();
                }
                baseResultDto.setMessage(bodyFromRemote.getMessage());
                baseResultDto.setCode(bodyFromRemote.getCode());
                result = baseResultDto.getResult();

                // 保存结果
                log.info("the url is {} ; the params is {} ; the res is {}", api, json0, JSON.toJSONString(baseResultDto));
                Date now = new Date();
                InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .invokeType(api)
                        .reqHeader(JSON.toJSONString(headers))
                        .reqParam(jsonReq)
                        .invokeTime(now)
                        .invokeResult(JSON.toJSONString(baseResultDto))
                        .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + api)
                        .remark(json0)
                        .createTime(now)
                        .updateTime(now)
                        .build();
                invokeRecordService.save(invokeRecordEntity);
                log.info("调用结果: " + JSON.toJSONString(result));

                mapReturn.put("result",true);
                mapReturn.put("totalCount",baseResultDto.getTotalCount());
                mapReturn.put("data",result);
                return mapReturn;
            }else{
                log.error("url：{},response:{},admin:{},trust:{}", api,JSON.toJSONString(bodyFromRemote),tenant.getTenantName(),trustNo);
                if (ObjectUtils.isNotEmpty(bodyFromRemote.getData())) {
                    String returnBodyAfterCipher = CipherUtil.rsaDecryptFromBase64(privateKey, bodyFromRemote.getData());
                    log.error("返回信息转义为{}", returnBodyAfterCipher);
                    bodyFromRemote.getData();
                }
                baseResultDto.setCode(bodyFromRemote.getCode());
                baseResultDto.setMessage(bodyFromRemote.getMessage());
            }

        } catch (Exception e) {
            log.error("调用海通托管失败：", e);
            errorMsg = e.getMessage();
        }
        mapReturn.put("result",false);
        if (StringUtils.isBlank(errorMsg)){
            errorMsg = JSONObject.toJSONString(baseResultDto);
        }
        //将错误的信息塞入错误表
        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, api, headers, "appId=" + tenant.getAppKey() , errorMsg));
        return mapReturn;
    }
}

