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

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.friday.custody.dto.TenantEscrowAuthorizationInfoDto;
import com.friday.custody.dto.ZhongxinAppSecretDTO;
import com.friday.custody.entity.InvokeFrequencyEntity;
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.basicService.impl.InvokeFrequencyServiceImpl;
import com.friday.custody.service.trustService.citicZhongXin.common.ZhongXinConstants;
import com.friday.custody.service.trustService.citicZhongXin.dto.ZhongXinBaseDto;
import com.friday.custody.service.trustService.citicZhongXin.dto.ZhongXinDataDto;
import com.friday.custody.utils.PullDataFailureUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Description
 * @Author wulifeng
 * @Date: 2022/3/29
 */
@Slf4j
@Service("zhongXinHttpUtil")
public class ZhongXinHttpUtil {
    @Autowired
    InvokeFrequencyServiceImpl invokeFrequencyService;

    private RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private InvokeRecordService invokeRecordService;

    @Autowired
    private PullDataFailureLogService pullDataFailureLogService;

    @Autowired
    FrequencyUtil frequencyUtil;

    @Value("${custody.remote.url.zhongxin.zhongxinUrlPrefix}")
    private String preffixUrl;

    public static void main(String[] args) {
        int pageSize = 100;
        int pageNo = 1;
        HashMap<String, Object> params = new HashMap<>();
        params.put("pageSize",pageSize);
        params.put("pageNum",pageNo);
        String jsonString = JSON.toJSONString(params);
        TenantEscrowAuthorizationInfoDto tenant = new TenantEscrowAuthorizationInfoDto();
        tenant.setTrustNo("21");
        String token = "eyJhbGciOiJIUzI1NiJ9.eyJpbnN0SWQiOiIxMzQ3MSIsIm5iZiI6MTY0OTc0NDkxMiwiY2hhbm5lbCI6ImdhdGV3YXkiLCJjdXN0VHlwZSI6IjIiLCJleHAiOjE2NDk4MzQ5MTJ9.HBZZlZfFWOauPt7_UXeHcgQzmXDiUme6Y0rdDmGEORI";
//        sendMessage(jsonString,ZhongXinConstants.FUND_INFO,tenant,tenant.getTrustNo(),token,1);
    }

//    public static Map<String, Object> sendMessage(String json0, String api, TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token,int iii) {
    public  Map<String, Object> sendMessage(String json0, String api, TenantEscrowAuthorizationInfoDto tenant, String trustNo, String token) {
        boolean canInvoke = frequencyUtil.judgeFrequency(api, tenant);
        String tenantAppSecret = tenant.getAppSecret();
        if(StringUtils.isBlank(tenantAppSecret)){
            log.error("租户授权信息有误！");
            HashMap<String, Object> objectObjectHashMap = new HashMap<>();
            objectObjectHashMap.put("result",false);
            return objectObjectHashMap;
        }
        ZhongxinAppSecretDTO appSecretDTO = getAppSecretDTO(tenant);
        String consumerAuth = appSecretDTO.getConsumerAuth();

        if(!canInvoke){
            Map map = new HashMap();
            log.error("api为{}时，今日已达到调用上线",api);
            map.put("result",false);
            return map;
        }
        Map<String,Object> map = JSON.parseObject(json0,Map.class);


        try {
            TimeUnit.SECONDS.sleep(1L);
        } catch (InterruptedException e) {
            log.error("ZhongXinHttpUtil_sendMessage 睡眠被打断了!");
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }
        log.info("中信ZhongXinHttpUtil的sendMessage入参情况为json0={},api={},tenant={},trustNo={},token={}",json0,api,tenant,trustNo,token);
        HttpHeaders headers = new HttpHeaders();
        List<JSONObject> result;
        Map mapReturn =new HashMap();
        String resultStr = null;
        String errorMsg = null;
        try {
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            headers.setContentType(type);
            headers.add("Accept", MediaType.APPLICATION_JSON.toString());
            headers.set("consumerAuth",consumerAuth);
            headers.set("Authorization","Bearer "+token);

            StringBuilder urlWithParam = new StringBuilder(preffixUrl + api);
            urlWithParam.append("?");
            for (Map.Entry<String, Object> stringStringEntry : map.entrySet()) {
                urlWithParam.append(stringStringEntry.getKey()).append("=").append(stringStringEntry.getValue()).append("&");
            }
            urlWithParam = urlWithParam.delete(urlWithParam.length() - 1, urlWithParam.length());

            log.info("urlWithParam = " + urlWithParam);

            RestTemplate restTemplate = new RestTemplate();
            HttpEntity<String> httpEntity = new HttpEntity<>(json0, headers);
            ResponseEntity<ZhongXinBaseDto> responseEntity = restTemplate.postForEntity(urlWithParam.toString(), httpEntity, ZhongXinBaseDto.class);
            log.info("responseEntity={}",JSON.toJSONString(responseEntity));
//
            ZhongXinBaseDto bodyFromRemote = responseEntity.getBody();


            log.info("bodyFromRemote={}",bodyFromRemote);
            resultStr = JSON.toJSONString(bodyFromRemote);
            if(bodyFromRemote == null){
                log.error("bodyFromRemote为空");
            }else if(bodyFromRemote.getSuccess()){
                JSONObject data = bodyFromRemote.getData();
                log.info("data"+JSON.toJSONString(data));
                ZhongXinDataDto zhongXinDataDto = JSON.parseObject(JSON.toJSONString(data), ZhongXinDataDto.class);
                result = zhongXinDataDto.getList();
                log.info("data_result"+JSON.toJSONString(result));

                Date now = new Date();
                InvokeRecordEntity invokeRecordEntity = InvokeRecordEntity.builder()
                        .trustNo(trustNo)
                        .admin(tenant.getTenantName())
                        .invokeType(api)
                        .reqHeader(JSON.toJSONString(headers))
                        .reqParam(json0)
                        .invokeTime(now)
                        .invokeResult(JSON.toJSONString(data))
                        .queryKey(tenant.getTenantName() + "::" + trustNo + "::" + api)
                        .createTime(now)
                        .updateTime(now)
                        .build();
                invokeRecordService.save(invokeRecordEntity);
                log.info("中信调用结果: " + JSON.toJSONString(result));
//
                mapReturn.put("result",true);
                mapReturn.put("totalCount",zhongXinDataDto.getTotal());
                mapReturn.put("data",result);
                return mapReturn;
            }else{
                log.error("返回的code不为200为{}，原信息为{}",bodyFromRemote.getCode(),JSON.toJSONString(bodyFromRemote));
            }

        } catch (HttpClientErrorException e){
            log.error("zhongxin the url = {}, the trustNo = {}, the admin = {}", api, trustNo, tenant.getTenantName(), e);
            errorMsg = e.getMessage();
        } catch (Exception e) {
            log.error("调用中信托管失败：", e);
            errorMsg = e.getMessage();
        }
        if (StringUtils.isBlank(errorMsg)) {
            errorMsg = resultStr;
        }
        pullDataFailureLogService.saveErrorData(tenant.getTenantName(), PullDataFailureUtil.createErrorMap(trustNo, api, headers, "appId=" + tenant.getAppKey() + "&params=" + json0 , errorMsg));
        mapReturn.put("result",false);

        return mapReturn;
    }



    public String getToken(TenantEscrowAuthorizationInfoDto tenant){
        //先从数据库找今天的
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(FrequencyUtil.invoke_time_pattern);
        LocalDate now = LocalDate.now();
        String today = timeFormatter.format(now);
        String invokeType = ZhongXinConstants.GET_TOKEN;
        String uniqueKey = today + invokeType + tenant.getTenantName() + tenant.getTrustNo() +tenant.getAppKey();
        InvokeFrequencyEntity invokeFrequencyEntity = invokeFrequencyService.queryByUniqueKey(uniqueKey);
        if(invokeFrequencyEntity==null || StringUtils.isBlank(invokeFrequencyEntity.getRemark())){
            //访问中信尝试获得token
            boolean b = frequencyUtil.judgeFrequency(ZhongXinConstants.GET_TOKEN, tenant);
            if(!b){
                log.error("getToken_超出访问限制,停止访问!");
                return null;
            }
            String tokenByHttp = getTokenByHttp(tenant);
            Date nowDate = new Date();
            int invokeTimesInt = 1;
            InvokeFrequencyEntity build = InvokeFrequencyEntity.builder()
                    .invokeDate(today)
                    .invokeType(ZhongXinConstants.GET_TOKEN)
                    .invokeTimes(invokeTimesInt)
                    .remark(tokenByHttp)
                    .uniqueKey(uniqueKey)
                    .createTime(nowDate)
                    .updateTime(nowDate)
                    .trustNo(tenant.getTrustNo())
                    .admin(tenant.getTenantName())
                    .build();
            invokeFrequencyService.saveData(build);
            return tokenByHttp;
        }else{
            //从数据库得到今天获取的token
            String remark = invokeFrequencyEntity.getRemark();
            return remark;
        }
    }

    public String  getTokenByHttp(TenantEscrowAuthorizationInfoDto tenant){
        JSONObject jsonObject = null;
        try{
            String appSecret = tenant.getAppSecret();
            Map map = JSON.parseObject(appSecret, Map.class);
            String url =(String) map.get("url");
            String consumerauth = (String) map.get("consumerAuth");

            HttpHeaders headers = new HttpHeaders();
            headers.set("consumerAuth", consumerauth);

            log.info("中信获取token request headers "+JSON.toJSONString(headers));
            HttpEntity<JSONObject> httpEntity = new HttpEntity<>( headers);
            ResponseEntity<JSONObject> exchange = restTemplate.exchange(preffixUrl+ZhongXinConstants.GET_TOKEN, HttpMethod.GET, httpEntity, JSONObject.class);
            jsonObject = exchange.getBody();
            log.info("exchange="+JSON.toJSONString(exchange)+",jsonObject="+JSON.toJSONString(jsonObject));
            ZhongXinBaseDto zhongXinBaseDto = JSON.parseObject(JSON.toJSONString(jsonObject), ZhongXinBaseDto.class);
            log.info("zhongXinBaseDto"+JSON.toJSONString(zhongXinBaseDto));
            JSONObject data = zhongXinBaseDto.getData();
            String token = data.getString("token");
            log.info("token"+token);

            return token;
        }catch (Exception e){
            log.error("getTokenByHttpTest_jsonObject={},exception={}",jsonObject,e);
            return null;
        }
    }








    public static String  getTokenByHttpTest(TenantEscrowAuthorizationInfoDto tenant){
        JSONObject jsonObject = null;
        try{
            String appSecret = tenant.getAppSecret();
            Map map = JSON.parseObject(appSecret, Map.class);
            String url =(String) map.get("url");
            String consumerauth = (String) map.get("consumerauth");

            RestTemplate restTemplate = new RestTemplate();
            HttpHeaders headers = new HttpHeaders();
            headers.set("consumerAuth", consumerauth);

            System.out.println("tyccompstafflistUrl request headers "+JSON.toJSONString(headers));
            HttpEntity<JSONObject> httpEntity = new HttpEntity<>( headers);
            ResponseEntity<JSONObject> exchange = restTemplate.exchange(url+ZhongXinConstants.GET_TOKEN, HttpMethod.GET, httpEntity, JSONObject.class);
            jsonObject = exchange.getBody();
            System.out.println("exchange="+JSON.toJSONString(exchange)+",jsonObject="+JSON.toJSONString(jsonObject));
            ZhongXinBaseDto zhongXinBaseDto = JSON.parseObject(JSON.toJSONString(jsonObject), ZhongXinBaseDto.class);
            System.out.println("zhongXinBaseDto"+JSON.toJSONString(zhongXinBaseDto));
            JSONObject data = zhongXinBaseDto.getData();
            String token = data.getString("token");
            System.out.println("token"+token);

            return token;
        }catch (Exception e){
            log.error("getTokenByHttpTest_jsonObject={},exception={}",jsonObject,e);
            return null;
        }
    }

    private ObjectMapper objectMapper = new ObjectMapper();
    public ZhongxinAppSecretDTO getAppSecretDTO(TenantEscrowAuthorizationInfoDto tenant){
        String tenantAppSecret = tenant.getAppSecret();
        if (ObjectUtil.isEmpty(tenantAppSecret)){
            return null;
        }
        ZhongxinAppSecretDTO zhongxinAppSecretDTO = new ZhongxinAppSecretDTO();
        try {
            zhongxinAppSecretDTO = objectMapper.readValue(tenantAppSecret, ZhongxinAppSecretDTO.class);
        } catch (IOException e) {
            log.error("解析账密{}失败!{}", zhongxinAppSecretDTO,  e);
        }
        return zhongxinAppSecretDTO;
    }

//    public static void main(String[] args) {
//        System.err.println(getTokenByHttpTest());
//    }
}