package com.zksy.data.utils;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.zksy.common.domain.response.BaseResponse;
import com.zksy.common.domain.response.BaseResponse2;
import com.zksy.common.domain.response.BaseResponse3;
import com.zksy.common.exception.CommonException;
import com.zksy.common.utils.BeanUtils;
import com.zksy.data.config.XhConfigProperty;
import com.zksy.data.config.XinyonghuaihuaProperty;
import com.zksy.data.constant.RedisKeyConstant;
import com.zksy.data.domain.po.BasePo;
import com.zksy.data.schedule.RefreshTokenSchedule;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class XhRequestUtil {
    @Autowired
    private XhConfigProperty xhConfigProperty;
    @Autowired
    private XinyonghuaihuaProperty xinyonghuaihuaProperty;
    @Autowired
    private OkHttpClient okHttpClient;
    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public <T extends BaseResponse, K extends BasePo> List<K> httpRequestByUniCode(String uniCode, String address,
                                                                                   Class<T> responseClass,
                                                                                   Class<K> entityClass) {
        if(redisTemplate.opsForValue().get(address) !=null){
            throw new CommonException("停止并行流",5001);
        }
        //        log.info("正在同步:{}下的:{}", address, uniCode);
        ArrayList<K> resList = new ArrayList<>();
        if (StrUtil.isEmpty(uniCode)) {
            log.warn("统一社会信用代码为空");
        }
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xhConfigProperty.getHost())
                .port(Integer.valueOf(xhConfigProperty.getPort()))
                .addPathSegment(address)
                .addQueryParameter("UNISCID", uniCode)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("appKey", xhConfigProperty.getAppKey())
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                log.error("当前接口请求失败:{}", address);
            }
            if (ObjectUtil.isEmpty(response.body())) {
                log.error("当前接口请求数据出现问题:{}", address);
            }
            String s = response.body().string();
            T value = objectMapper.readValue(s, responseClass);
            if (value.getCode() != 200) {
                log.error("当前请求结果异常:{}", value.getMessage());
            } else {
                if (value.getData().isEmpty()) {
                    return null;
                }
                for (int i = 0; i < value.getData().size(); i++) {
                    K e = BeanUtils.copyBean(value.getData().get(i), entityClass);
                    e.setUniCode(uniCode);
                    resList.add(e);
                }
            }
            return resList;
        } catch (Exception e) {
            log.error("此次数据同步出现异常,接口是:{}", address);
            throw new RuntimeException(e);
        }
    }
    public <T extends BaseResponse, K extends BasePo> List<K> httpRequestByUniCode(String uniCode, String address,
                                                                                   Class<T> responseClass,
                                                                                   Class<K> entityClass,
                                                                                   String key) {
        if(redisTemplate.opsForValue().get(address) !=null){
            throw new CommonException("停止并行流",5001);
        }
//        log.info("正在同步:{}下的:{}", address, uniCode);
        ArrayList<K> resList = new ArrayList<>();
        if (StrUtil.isEmpty(uniCode)) {
            log.warn("统一社会信用代码为空");
        }
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xhConfigProperty.getHost())
                .port(Integer.valueOf(xhConfigProperty.getPort()))
                .addPathSegment(address)
                .addQueryParameter(key, uniCode)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("appKey", xhConfigProperty.getAppKey())
                .build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                log.error("当前接口请求失败:{}", address);
            }
            if (ObjectUtil.isEmpty(response.body())) {
                log.error("当前接口请求数据出现问题:{}", address);
            }
            String s = response.body().string();
            T value = objectMapper.readValue(s, responseClass);
            if (value.getCode() != 200) {
                log.error("当前请求结果异常:{}", value.getMessage());
                throw new CommonException("请求异常",5000);
            } else {
                if (value.getData().isEmpty()) {
                    return null;
                }
                for (int i = 0; i < value.getData().size(); i++) {
                    K e = BeanUtils.copyBean(value.getData().get(i), entityClass);
                    e.setUniCode(uniCode);
                    resList.add(e);
                }
            }
            return resList;
        } catch (Exception e) {
            log.error("此次数据同步出现异常,接口是:{}", address);
            throw new RuntimeException(e);
        }
    }

    private Boolean isEnd = false;

    public String testHttpRequest(String uniCode, String address, String paramsValue) {
        if (isEnd) {
            isEnd = false;
            throw new RuntimeException("已经找到请求结构,不用继续了");
        }
        if (StrUtil.isEmpty(uniCode)) {
            log.warn("统一社会信用代码为空");
        }
        log.info("正在找:{}", uniCode);
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xhConfigProperty.getHost())
                .port(Integer.valueOf(xhConfigProperty.getPort()))
                .addPathSegment(address)
                .addQueryParameter(paramsValue, uniCode)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("appKey", xhConfigProperty.getAppKey())
                .build();

        try {
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                log.error("当前接口请求失败:{}", address);
            }
            if (ObjectUtil.isEmpty(response.body())) {
                log.error("当前接口请求数据出现问题:{}", address);
            }
            String s = response.body().string();
            BaseResponse value = objectMapper.readValue(s, BaseResponse.class);
            if (!value.getData().isEmpty()) {
                isEnd = true;
                return s;
            }
        } catch (Exception e) {
            throw new RuntimeException("当次请求失败");
        }
        return null;
    }

    public String testHttpRequest(Map map, String address) {
        if (isEnd) {
            isEnd = false;
            throw new RuntimeException("已经找到请求结构,不用继续了");
        }
        if (map.get("entityCode") == null) {
            log.warn("统一社会信用代码为空");
        }
        log.info("正在找:{}", map.get("entityCode"));
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xinyonghuaihuaProperty.getHost())
                .addPathSegment(address)
                .build();
        String token = redisTemplate.opsForValue().get(RedisKeyConstant.HUAIHUA_TOKEN_KEY);
        String json;
        try {
            json = objectMapper.writeValueAsString(map);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
        Request request = new Request.Builder()
                .url(url)
                .header("Content-Type", "application/json")
                .header("Token", token)
                .post(requestBody)
                .build();

        try {
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful()) {
                log.error("当前接口请求失败:{}", address);
            }
            if (ObjectUtil.isEmpty(response.body())) {
                log.error("当前接口请求数据出现问题:{}", address);
            }
            String s = response.body().string();
            BaseResponse2 value = objectMapper.readValue(s, BaseResponse2.class);
            if (value.getData().getTotalElements() > 0) {
                isEnd = true;
                return s;
            }
        } catch (Exception e) {
            throw new RuntimeException("当次请求失败");
        }
        return null;
    }

    public <T extends BaseResponse2, K extends BasePo> List<K> requestXinyonghuanhuai(Map requestBodyMap, String address,
                                                                                      Class<T> entityResponseClass,
                                                                                      Class<K> entityClass) {
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xinyonghuaihuaProperty.getHost())
                .addPathSegment(address)
                .build();
        var resList = new ArrayList<K>();
        try {
            var json = objectMapper.writeValueAsString(requestBodyMap);
            RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
            while (redisTemplate.opsForValue().get(RedisKeyConstant.HUAIHUA_LOCK_KEY) != null) {
                System.out.println("当前锁住了");
                Thread.sleep(3000);
            }
            String token = redisTemplate.opsForValue().get(RedisKeyConstant.HUAIHUA_TOKEN_KEY);
            Request request = new Request.Builder()
                    .url(url)
                    .header("Content-Type", "application/json")
                    .header("Token", token)
                    .post(requestBody)
                    .build();
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful() || ObjectUtil.isEmpty(response.body())) {
                throw new CommonException("当前接口请求失败", 5000);
            }
            String s = response.body().string();
            T value = objectMapper.readValue(s, entityResponseClass);
            if (value.getStatus() != 0) {
                throw new CommonException("当前请求结果异常", 5000);
            }
            value.getData().getList().stream().forEach(q -> {
                K converted = objectMapper.convertValue(q, entityClass);
                converted.setUniCode(requestBodyMap.get("entityCode").toString());
                resList.add(converted);
            });
            if (value.getData().getTotalElements() > (Integer.valueOf(requestBodyMap.get("size").toString()) * (Integer.valueOf(requestBodyMap.get("page").toString())))) {
                //需要再次获取页数为+1的数据
                requestBodyMap.put("page", Integer.valueOf(requestBodyMap.get("page").toString()+1));
                List<K> list = requestXinyonghuanhuai(requestBodyMap, address, entityResponseClass, entityClass);
                resList.addAll(list);
            }
            log.info(s);
            return resList;
        }catch (InvalidFormatException e){
            refreshTokenSchedule.getToken();
            this.requestXinyonghuanhuai(requestBodyMap, address, entityResponseClass, entityClass);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return resList;
    }
    @Autowired
    private RefreshTokenSchedule refreshTokenSchedule;
    public <T extends BaseResponse3, K extends BasePo> List<K> requestXinyonghuanhuai2(Map requestBodyMap, String address,
                                                                                       Class<T> entityResponseClass,
                                                                                       Class<K> entityClass) {
        HttpUrl url = new HttpUrl.Builder()
                .scheme("http")
                .host(xinyonghuaihuaProperty.getHost())
                .addPathSegment(address)
                .build();
        var resList = new ArrayList<K>();
        try {

            var json = objectMapper.writeValueAsString(requestBodyMap);
            RequestBody requestBody = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
            while (redisTemplate.opsForValue().get(RedisKeyConstant.HUAIHUA_LOCK_KEY) != null) {
                System.out.println("当前锁住了");
                Thread.sleep(3000);
            }
            String token = redisTemplate.opsForValue().get(RedisKeyConstant.HUAIHUA_TOKEN_KEY);
            Request request = new Request.Builder()
                    .url(url)
                    .header("Content-Type", "application/json")
                    .header("Token", token)
                    .post(requestBody)
                    .build();
            Response response = okHttpClient.newCall(request).execute();
            if (!response.isSuccessful() || ObjectUtil.isEmpty(response.body())) {
                throw new CommonException("当前接口请求失败", 5000);
            }
            String s = response.body().string();
            T value = objectMapper.readValue(s, entityResponseClass);
            if (value.getStatus() != 0) {
                throw new CommonException("当前请求结果异常", 5000);
            }
            if (!value.getData().getItems().isEmpty()) {
                value.getData().getItems().stream().forEach(q -> {
                    K converted = objectMapper.convertValue(q, entityClass);
                    converted.setUniCode(requestBodyMap.get("entityCode").toString());
                    resList.add(converted);
                });
            }
            if (value.getData().getTotalElements() > (Integer.valueOf(requestBodyMap.get("size").toString()) * (Integer.valueOf(requestBodyMap.get("page").toString())))) {
                //需要再次获取页数为+1的数据
                requestBodyMap.put("page", Integer.valueOf(requestBodyMap.get("page").toString()+1));
                List<K> list = requestXinyonghuanhuai2(requestBodyMap, address, entityResponseClass, entityClass);
                resList.addAll(list);
            }
            log.info(requestBodyMap.get("entityCode")+s);
            return resList;
        }catch (InvalidFormatException e){
            refreshTokenSchedule.getToken();
            this.requestXinyonghuanhuai2(requestBodyMap, address, entityResponseClass, entityClass);
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
        return resList;
    }
}
