package com.ningdatech.kqapi.irs.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.StopWatch;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.ningdatech.http.HttpClientService;
import com.ningdatech.http.HttpResponseContent;
import com.ningdatech.kqapi.common.model.PageVo;
import com.ningdatech.kqapi.common.util.NdDateUtils;
import com.ningdatech.kqapi.irs.model.ItemBasicInfoListQueryDTO;
import com.ningdatech.kqapi.zzsfw.model.entity.DscSxAdsShareItemQltQlsxCommonIDVKq;
import com.ningdatech.kqapi.zzsfw.service.IDscSxAdsShareItemQltQlsxCommonIDVKqService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.parser.ParserConfig;
import com.ningdatech.basic.exception.BizException;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author CMM
 * @author CMM
 * @date 2024/8/19 11:27
 * /
 * /**
 * @since 2024/08/19 11:27
 */
@Component
@Slf4j
@RequiredArgsConstructor
public class IrsManage {

    @Value("${irs.item-basic-info.appKey}")
    private String appKey;

    @Value("${irs.item-basic-info.appSecret}")
    private String appSecret;

    @Value("${irs.item-basic-info.listUrl}")
    private String itemBasicInfoListUrl;

    @Value("${irs.item-basic-info.detailUrl}")
    private String itemBasicInfoDetailUrl;

    private final HttpClientService httpClient;

    private final IDscSxAdsShareItemQltQlsxCommonIDVKqService kqService;
    String transmitListUrl = "https://qyxspt.kq.gov.cn:33060/kq/api/v1/irs/item-basic-info-list";
    String transmitDetailUrl = "https://qyxspt.kq.gov.cn:33060/kq/api/v1/irs/item-basic-info-detail";

    public Object itemBasicInfoList(String startDate, String endDate, Integer pageSize, Integer pageNum) {
        long timestamp = System.currentTimeMillis();
        String sign = MD5.create().digestHex(appKey + appSecret + timestamp);
        // 设置读取和连接超时时间为60秒
        HttpRequest request = HttpUtil.createPost(itemBasicInfoListUrl).timeout(60000);
        request.header("requestTime", String.valueOf(timestamp));
        request.header("sign", sign);
        request.header("appKey", appKey);
        request.contentType(ContentType.FORM_URLENCODED.getValue());

        ItemBasicInfoListQueryDTO queryDTO = new ItemBasicInfoListQueryDTO();
        queryDTO.setStartDate(startDate);
        queryDTO.setEndDate(endDate);
        queryDTO.setPageNum(pageNum);
        queryDTO.setPageSize(pageSize);
        queryDTO.setParamStr("update_date");
        queryDTO.setViewName("v_dsc_sx_ads_share_item_qlt_qlsx_common_i_d_v_kq_insensitive");
        String queryStr = JSON.toJSONString(queryDTO);
        request.form("parameter", queryStr);
        log.info("request headers: {}", request.headers());
        log.info("request form: {}", request.form());
        String responseBody;
        try (HttpResponse response = request.execute()) {
            if (response == null || StrUtil.isEmpty(responseBody = response.body())) {
                throw BizException.wrap("事项基本信息列表接口调用失败!");
            }
            log.info("content: {}", responseBody);
            // 如果请求是请求超时 增加重试机制
            responseBody = retryAndGetResponseBody(responseBody, request);
        }
        ParserConfig config = new ParserConfig();
        config.propertyNamingStrategy = PropertyNamingStrategy.PascalCase;
        try {
            JSONObject contentObj = JSONObject.parseObject(responseBody, JSONObject.class, config);
            JSONObject data = contentObj.getJSONObject("data");
            return data.getJSONArray("data");
        } catch (Exception e) {
            log.error("解析事项基本信息列表接口返回数据异常:{}", e.getMessage());
        }
        return responseBody;
    }

    private String retryAndGetResponseBody(String responseBody, HttpRequest request) {
        if (responseBody.contains("Read timed out")){
            int retries = 3;
            for (int i = 0; i < retries; i++) {
                log.info("第{}次重试中......", i + 1);
                // 重新设置签名和时间戳
                long timestamp = System.currentTimeMillis();
                String sign = MD5.create().digestHex(appKey + appSecret + timestamp);
                request.header("requestTime", String.valueOf(timestamp));
                request.header("sign", sign);
                responseBody = request.execute().body();
                ParserConfig config = new ParserConfig();
                config.propertyNamingStrategy = PropertyNamingStrategy.PascalCase;
                JSONObject contentObj = JSONObject.parseObject(responseBody, JSONObject.class, config);
                JSONObject data = contentObj.getJSONObject("data");
                Object object = data.get("data");
                if (object instanceof JSONArray){
                    break;
                }
                // 如果最后一次重试仍无法获取到数据，抛出异常
                if (i == retries - 1){
                    throw BizException.wrap("事项基本信息列表接口调用失败!");
                }
                // 等待一段时间后再次尝试
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return responseBody;
    }

    public Object itemBasicInfoDetail(String rowGuid) {
        long timestamp = System.currentTimeMillis();
        String sign = MD5.create().digestHex(appKey + appSecret + timestamp);
        // 设置读取和连接超时时间为60秒
        HttpRequest request = HttpUtil.createPost(itemBasicInfoDetailUrl).timeout(60000);
        request.header("requestTime", String.valueOf(timestamp));
        request.header("sign", sign);
        request.header("appKey", appKey);
        request.contentType(ContentType.FORM_URLENCODED.getValue());

        DscSxAdsShareItemQltQlsxCommonIDVKq dsc = new DscSxAdsShareItemQltQlsxCommonIDVKq();
        dsc.setRowguid(rowGuid);
        String paramStr = JSON.toJSONString(dsc);
        ItemBasicInfoListQueryDTO queryDTO = new ItemBasicInfoListQueryDTO();
        queryDTO.setViewName("v_dsc_sx_ads_share_item_qlt_qlsx_common_i_d_v_kq_insensitive");
        queryDTO.setParamStr(paramStr);
        String parameter = JSON.toJSONString(queryDTO);
        request.form("parameter",parameter);
        String responseBody;
        try (HttpResponse response = request.execute()) {
            if (response == null || StrUtil.isEmpty(responseBody = response.body())) {
                throw BizException.wrap("事项基本信息列表接口调用失败!");
            }
            log.info("content: {}", responseBody);
            // 如果请求是请求超时 增加重试机制
            responseBody = retryAndGetResponseBody(responseBody, request);
        }
        ParserConfig config = new ParserConfig();
        config.propertyNamingStrategy = PropertyNamingStrategy.PascalCase;
        try {
            JSONObject contentObj = JSONObject.parseObject(responseBody, JSONObject.class, config);
            JSONObject data = contentObj.getJSONObject("data");
            JSONArray dataArray = data.getJSONArray("data");
            if (CollUtil.isNotEmpty(dataArray)) {
                return dataArray;
            }
        } catch (Exception e) {
            log.error("解析事项基本信息详情接口返回数据异常:{}", e.getMessage());
        }
        return responseBody;
    }

    public PageVo<DscSxAdsShareItemQltQlsxCommonIDVKq> transferRequest(LocalDate startDate, LocalDate endDate, Integer pageSize, Integer pageNum) {
        String transmitListUrl = "https://qyxspt.kq.gov.cn:33060/kq/api/v1/irs/item-basic-info-list";
        String transmitDetailUrl = "https://qyxspt.kq.gov.cn:33060/kq/api/v1/irs/item-basic-info-detail";

        List<DscSxAdsShareItemQltQlsxCommonIDVKq> records = Lists.newArrayList();
        // for循环，从开始日期更新到结束日期
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            String listUrl = transmitListUrl + "?startDate=" + date + "&endDate=" + date.plusDays(1) +
                    "&pageSize=" + pageSize + "&pageNum=" + pageNum;
            log.info("listUrl :{}", listUrl);

            try {
                HttpResponseContent listContent = httpClient.doGet(listUrl, null, null);
                log.info("列表接口返回值：{}", JSONUtil.toJsonStr(listContent));
                String listObject = listContent.getStringBody();
                if (listObject == null || StringUtils.isBlank(listObject)) {
                    throw new BizException("列表接口转发调用失败!" );
                }
                JSONObject listJsonObject = null;
                try {
                    listJsonObject = JSONObject.parseObject(listObject);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                JSONArray listJsonArray = null;

                Object object = listJsonObject.get("data");
                if (object instanceof JSONArray){
                    listJsonArray = listJsonObject.getJSONArray("data");
                }else {
                    JSONObject listData = listJsonObject.getJSONObject("data");
                    JSONObject listJsonData = listData.getJSONObject("data");
                    listJsonArray = listJsonData.getJSONArray("data");
                }
                if (CollUtil.isNotEmpty(listJsonArray)) {
                    log.info("事项列表数量为：{}", listJsonArray.size());
                    List<DscSxAdsShareItemQltQlsxCommonIDVKq> dataList = Lists.newArrayList();
                    for (Object item : listJsonArray) {
                        JSONObject itemJsonObject = (JSONObject) item;
                        DscSxAdsShareItemQltQlsxCommonIDVKq itemData = null;
                        // 先将列表中返回的非敏感信息进行赋值
                        itemData = JSON.parseObject(itemJsonObject.toJSONString(), DscSxAdsShareItemQltQlsxCommonIDVKq.class);
                        String rowGuid = itemJsonObject.getString("rowguid" );
                        if (StringUtils.isNotBlank(rowGuid)) {
                            String detailUrl = transmitDetailUrl + "?rowGuid=" + rowGuid;
                            log.info("detailUrl :{}", detailUrl);

                            HttpResponseContent detailContent = httpClient.doGet(detailUrl, null, null);
                            log.info("详情接口返回值：{}", JSONUtil.toJsonStr(detailContent));
                            String detailObject = detailContent.getStringBody();
                            if (detailObject == null || StringUtils.isBlank(detailObject)) {
                                throw new BizException("列表接口转发调用失败!" );
                            }
                            JSONObject detailJsonObject = null;
                            try {
                                detailJsonObject = JSONObject.parseObject(detailObject);
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }

                            JSONArray detailJsonArray = null;

                            if (detailJsonObject.get("data") instanceof JSONArray){
                                detailJsonArray = detailJsonObject.getJSONArray("data");
                            }else {
                                JSONObject detailData = detailJsonObject.getJSONObject("data" );
                                JSONObject detailJsonData = detailData.getJSONObject("data");
                                detailJsonArray = detailJsonData.getJSONArray("data");
                            }

                            List<DscSxAdsShareItemQltQlsxCommonIDVKq> idvKqList = detailJsonArray.toJavaList(DscSxAdsShareItemQltQlsxCommonIDVKq.class);
                            if (CollUtil.isNotEmpty(idvKqList)) {
                                // 如果列表不为空，则取最新的一条数据
                                idvKqList.sort((o1, o2) -> o2.getUpdateDate().compareTo(o1.getUpdateDate()));
                                DscSxAdsShareItemQltQlsxCommonIDVKq detailItemData = idvKqList.get(0);
                                // 将敏感数据进行赋值
                                CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true);
                                BeanUtil.copyProperties(detailItemData, itemData,copyOptions);
                            }
                        }
                        if (Objects.nonNull(itemData)) {
                            dataList.add(itemData);
                        }
                    }
                    // 保存数据
                    if (CollUtil.isNotEmpty(dataList)) {
                        log.info("{} 数据列表数量为：{}", date, dataList.size());
                        kqService.saveBatch(dataList);
                        records.addAll(dataList);
                    }
                }

            } catch (RestClientException e) {
                throw new BizException("接口转发调用失败!" );
            }
        }
        PageVo<DscSxAdsShareItemQltQlsxCommonIDVKq> pageVo = new PageVo<>();
        pageVo.setRecords(records);
        pageVo.setTotal((long) records.size());
        return pageVo;
    }

    public String testTask(String startDateStr, String endDateStr) {
        log.info("事项数据 ===================== 同步开始");
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 每天凌晨5点同步前一天新更新的数据
        // 默认一页返回
        int pageNum = 1;
        // irs接口最大返回数据量1000条
        int pageSize = 1000;

        List<DscSxAdsShareItemQltQlsxCommonIDVKq> records = Lists.newArrayList();
        // 循环拉取较前一天已同步数据 新更新的数据
        // 根据事项表中最后更新日期 循环更新至前一天的事项数据
        String start = kqService.getNewestUpdateDate();
        String end = NdDateUtils.format(LocalDateTime.now().minusDays(1), NdDateUtils.DEFAULT_DATE_FORMAT);
        LocalDate startDate = LocalDate.parse(start).plusDays(1);
        LocalDate endDate = LocalDate.parse(end);

        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            boolean flag = true;
            while (flag) {
                //Object listObject = irsManage.itemBasicInfoList(startDateStr, endDateStr, pageSize, pageNum);

                String listUrl = transmitListUrl + "?startDate=" + date + "&endDate=" + date.plusDays(1) +
                        "&pageSize=" + pageSize + "&pageNum=" + pageNum;
                log.info("listUrl :{}", listUrl);
                HttpResponseContent listContent = httpClient.doGet(listUrl, null, null);
                log.info("列表接口返回值：{}", JSONUtil.toJsonStr(listContent));
                String listObject = listContent.getStringBody();
                if (listObject == null || StringUtils.isBlank(listObject)) {
                    throw new BizException("列表接口转发调用失败!");
                }
                JSONObject listJsonObject = null;
                try {
                    listJsonObject = JSONObject.parseObject(listObject);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }

                Object object = listJsonObject.get("data");
                // 如果数据正常返回
                if (object instanceof JSONArray) {
                    //JSONArray listJsonArray = (JSONArray)listObject;
                    JSONArray listJsonArray = listJsonObject.getJSONArray("data");
                    log.info("事项列表数量为：{}", listJsonArray.size());
                    getSaveRecords(listJsonArray, records);
                    // 如果listJsonArray数据量等于1000 需要继续拉取数据
                    if (listJsonArray.size() == pageSize) {
                        pageNum++;
                    } else {
                        flag = false;
                    }
                } else {
                    log.error("事项列表数据异常：{}", listObject);
                    return "同步失败";
                }
            }
        }
        log.info("{} - {} 数据列表数量为：{}", startDate, endDate, records.size());
        //kqService.saveBatch(records);
        log.info("事项同步成功，更新时间：{}", endDate);
        stopWatch.stop();
        log.info("事项数据 ===================== 同步总共耗时 :{} s", stopWatch.getTotalTimeSeconds());
        return "同步成功";
    }

    private void getSaveRecords(JSONArray listJsonArray, List<DscSxAdsShareItemQltQlsxCommonIDVKq> records) {
        if (CollUtil.isNotEmpty(listJsonArray)) {
            List<DscSxAdsShareItemQltQlsxCommonIDVKq> dataList = Lists.newArrayList();
            for (Object item : listJsonArray) {
                JSONObject itemJsonObject = (JSONObject) item;
                DscSxAdsShareItemQltQlsxCommonIDVKq itemData = null;
                // 先将列表中返回的非敏感信息进行赋值
                itemData = JSON.parseObject(itemJsonObject.toJSONString(), DscSxAdsShareItemQltQlsxCommonIDVKq.class);
                String rowGuid = itemJsonObject.getString("rowguid" );
                if (StringUtils.isNotBlank(rowGuid)) {
                    //Object detailObject = irsManage.itemBasicInfoDetail(rowGuid);
                    String detailUrl = transmitDetailUrl + "?rowGuid=" + rowGuid;
                    log.info("detailUrl :{}", detailUrl);

                    HttpResponseContent detailContent = httpClient.doGet(detailUrl, null, null);
                    log.info("详情接口返回值：{}", JSONUtil.toJsonStr(detailContent));
                    String detailObject = detailContent.getStringBody();
                    if (detailObject == null || StringUtils.isBlank(detailObject)) {
                        throw new BizException("列表接口转发调用失败!" );
                    }
                    JSONObject detailJsonObject = null;
                    try {
                        detailJsonObject = JSONObject.parseObject(detailObject);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }

                    Object object = detailJsonObject.get("data");

                    if (object instanceof JSONArray){
                        //JSONArray detailJsonArray = (JSONArray) detailObject;
                        JSONArray detailJsonArray = detailJsonObject.getJSONArray("data");
                        List<DscSxAdsShareItemQltQlsxCommonIDVKq> idvKqList = detailJsonArray.toJavaList(DscSxAdsShareItemQltQlsxCommonIDVKq.class);
                        if (CollUtil.isNotEmpty(idvKqList)) {
                            // 如果列表不为空，则取最新的一条数据
                            idvKqList.sort((o1, o2) -> o2.getUpdateDate().compareTo(o1.getUpdateDate()));
                            DscSxAdsShareItemQltQlsxCommonIDVKq detailItemData = idvKqList.get(0);
                            // 将敏感数据进行赋值
                            CopyOptions copyOptions = CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true);
                            BeanUtil.copyProperties(detailItemData, itemData,copyOptions);
                        }
                    }
                }
                if (Objects.nonNull(itemData)) {
                    dataList.add(itemData);
                }
            }
            // 保存数据
            if (CollUtil.isNotEmpty(dataList)) {
                records.addAll(dataList);
            }
        }
    }
}
