package com.fjhx.victoriatourist.service.jd.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fjhx.common.constant.SourceConstant;
import com.fjhx.item.entity.product.po.ProductInfo;
import com.fjhx.item.service.product.ProductInfoService;
import com.fjhx.tenant.entity.dict.dto.DictTenantDataDto;
import com.fjhx.tenant.entity.dict.dto.DictTenantTypeDto;
import com.fjhx.tenant.entity.dict.po.DictTenantData;
import com.fjhx.tenant.entity.dict.po.DictTenantType;
import com.fjhx.tenant.service.dict.DictTenantDataService;
import com.fjhx.tenant.service.dict.DictTenantTypeService;
import com.fjhx.victoriatourist.entity.jd.dto.JdInfoDto;
import com.fjhx.victoriatourist.entity.jd.po.*;
import com.fjhx.victoriatourist.entity.jd.vo.CommonDictData;
import com.fjhx.victoriatourist.entity.jd.vo.JdInfoVo;
import com.fjhx.victoriatourist.entity.jd.vo.TellBackOrderVO;
import com.fjhx.victoriatourist.service.jd.*;
import com.fjhx.victoriatourist.service.jd.constants.InitDictConstant;
import com.fjhx.victoriatourist.service.jd.constants.JdParamConstant;
import com.fjhx.victoriatourist.service.jd.constants.RunParamConstant;
import com.fjhx.victoriatourist.service.jd.factory.JdClientFactory;
import com.jd.open.api.sdk.DefaultJdClient;
import com.jd.open.api.sdk.JdClient;
import com.jd.open.api.sdk.domain.supplier.PoCommonForJosWebService.response.getcomponentlist.Component;
import com.jd.open.api.sdk.domain.supplier.PoCommonForJosWebService.response.getwaredeliverdistinctlist.WarehouseDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getdetailbyorderid.JOSDetailResultDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getdetailbyorderid.PurchaseAllocationDetailDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getpurchaseorderlist.JOSOrderResultDto;
import com.jd.open.api.sdk.domain.supplier.PoQueryForJosWebService.response.getpurchaseorderlist.PurchaseOrderDto;
import com.jd.open.api.sdk.domain.supplier.ReturnOrderForJosWebService.response.detail.DetailResultDto;
import com.jd.open.api.sdk.domain.supplier.ReturnOrderForJosWebService.response.get.RoDto;
import com.jd.open.api.sdk.domain.supplier.ReturnOrderForJosWebService.response.get.RoResultDto;
import com.jd.open.api.sdk.request.supplier.*;
import com.jd.open.api.sdk.response.AbstractResponse;
import com.jd.open.api.sdk.response.supplier.*;
import com.ruoyi.common.utils.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class JdApiServiceImpl implements JdApiService {

    @Autowired
    private JdOrderService jdOrderService;
    @Autowired
    private JdOrderDetailsService jdOrderDetailsService;
    @Autowired
    private JdBackService jdBackService;
    @Autowired
    private JdBackDetailsService jdBackDetailsService;
    @Resource
    private JdInfoService jdInfoService;
    @Resource
    private JdClientFactory jdClientFactory;
    @Resource
    private ProductInfoService productInfoService;
    @Resource
    private DictTenantTypeService dictTenantTypeService;
    @Resource
    private DictTenantDataService dictTenantDataService;

    /**
     * 通过code获取AccessToken
     */
    @Override
    public void getAccessTokenByCode(String code) {
        //获取AccessToken并存入数据库
        String path = RunParamConstant.JD_GET_ACCESS_TOKEN_URL;
        path = String.format(path, JdParamConstant.appKey, JdParamConstant.appSecret, code);
        try {
            JSONObject responseJson = getJSON(new HttpGet(path));
            System.out.println(responseJson);
            dealJdTokenResponse(responseJson);
        } catch (Exception e) {
            log.error("获取AccessToken出错：" + e.getMessage(), e);
        }
    }



    @Override
    public String build2LoginUrl() {
        String url = RunParamConstant.JD_LOGIN_URL;
        //redirect_uri需要加上项目的域名
        url = String.format(url, JdParamConstant.appKey, RunParamConstant.redirect_uri, DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        return url;
    }


    @Override
    public void tellBackOrer(TellBackOrderVO tellBackOrderVO) {
        JdClient client = jdClientFactory.getJdClient();
        VcConfirmpurchaseorderResponse response;
        try {
            VcConfirmpurchaseorderRequest request = buildConfirmpurchaseorderRequest(tellBackOrderVO);
            response = client.execute(request);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        String code = response.getCode();
        if(!"0".equals(code)){
            //失败
            log.error("回告失败：{}，{}",response.getZhDesc(), response.getMsg());
            throw new RuntimeException("回告失败");
        }else {
            Boolean successFlag = false;
            String msg = "回告失败";
            try{
                successFlag = JSONObject.parse(response.getMsg()).getJSONObject("jingdong_vc_confirmpurchaseorder_responce").getJSONObject("base_result").getBoolean("success");
                msg = msg + "：" + JSONObject.parse(response.getMsg()).getJSONObject("jingdong_vc_confirmpurchaseorder_responce").getJSONObject("base_result").getString("result_message");
            }catch (Exception e){
                log.error("回告返回解析异常：{}",response.getMsg());
            }
            if(!successFlag){
                //失败
                log.error("回告失败：{}，{}",response.getZhDesc(), response.getMsg());
                throw new RuntimeException(msg);
            }
        }
    }

    private VcConfirmpurchaseorderRequest buildConfirmpurchaseorderRequest(TellBackOrderVO tellBackOrderVO) {
        VcConfirmpurchaseorderRequest request = new VcConfirmpurchaseorderRequest();
        request.setOrderId(tellBackOrderVO.getOrderId());
        request.setDeliveryTime(tellBackOrderVO.getDeliveryTime());
        request.setWareId(tellBackOrderVO.getBackInfo().stream().map(o->StrUtil.toString(o.getWareId())).collect(Collectors.joining(",")));
        request.setConfirmNum(tellBackOrderVO.getBackInfo().stream().map(o->StrUtil.toString(o.getConfirmNum())).collect(Collectors.joining(",")));
        request.setBackExplanation(tellBackOrderVO.getBackInfo().stream().map(o->StrUtil.toString(o.getNonDeliveryReason())).collect(Collectors.joining(",")));
//        request.setBackExplanationType(tellBackOrderVO.getBackInfo().stream().map(o->StrUtil.toString(o.getBackExplanationType())).collect(Collectors.joining(",")));
        request.setDeliverCenterId(tellBackOrderVO.getBackInfo().stream().map(o->StrUtil.toString(o.getDeliverCenterId())).collect(Collectors.joining(",")));
        return request;
    }

    //每小时执行一次
    @Scheduled(cron = "0 0 0/1  * * ? ")
    //每分钟执行一次
//    @Scheduled(cron = "0 0/1 *  * * ? ")
    void refreshToken(){
        JdInfoVo jdInfoVo = jdInfoService.getOne();
        //如果过期时间减去当前时间小于90分钟，则要刷新token
        if(ObjectUtil.isNotNull(jdInfoVo.getExpireTime())){
            long between = DateUtil.between(DateUtil.date(), jdInfoVo.getExpireTime(), DateUnit.MINUTE, false);
            if(between <= 0){
                if(jdInfoVo.getOnline()>0){
                    jdInfoVo.setOnline(0);
                    jdInfoService.updateById(jdInfoVo);
                }
            }else if(90 >= between){
                refreshToken(jdInfoVo);
            }
        }
    }


    /**
     * 刷新Token
     */
    private void refreshToken(JdInfoVo jdInfoVo) {
        if (ObjectUtil.isEmpty(jdInfoVo.getAccessToken())) {
            log.error("accessToken为空无法刷新Token请检查");
            return;
        }
        if (ObjectUtil.isEmpty(jdInfoVo.getRefreshToken())) {
            log.error("refreshToken为空无法刷新Token请检查");
            return;
        }
        String path = RunParamConstant.JD_REFRESH_URL;
        path = String.format(path, JdParamConstant.appKey,JdParamConstant.appSecret, jdInfoVo.getRefreshToken());
        try {
            JSONObject responseJson = getJSON(new HttpGet(path));
            dealJdTokenResponse(responseJson);
        } catch (Exception e) {
            log.error("刷新AccessToken出错：" + e.getMessage(), e);
        }
    }

    /**
     * 开始京东订单采集
     * @author hj
     * @date 2023/12/13 22:30
     */
    @Async
    public void startJdOrder(){
        ThreadUtil.safeSleep(RunParamConstant.SLEEP_ONE_MINUTE);
        JdClient jdClient = jdClientFactory.getJdClient();
        while (true){
            JdInfoVo jdInfoVo = validJdInfo();
            if(ObjectUtil.isNull(jdInfoVo)){
                ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
                continue;
            }
            getJdOrderList(jdClient, jdInfoVo);
            log.info("京东订单采集完成");
            ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
        }
    }



    /**
     * 开始京东退货单采集
     * @author hj
     * @date 2023/12/13 22:30
     */
    @Async
    public void startJdBackOrder(){
        ThreadUtil.safeSleep(RunParamConstant.SLEEP_ONE_MINUTE);
        JdClient jdClient = jdClientFactory.getJdClient();
        while (true){
            JdInfoVo jdInfoVo = validJdInfo();
            if(ObjectUtil.isNull(jdInfoVo)){
                ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
                continue;
            }
            getJdBackOrder(jdClient, jdInfoVo);
            log.info("京东退货单采集完成");
            ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
        }
    }



    /**
     * 刷新京东状态
     * @param
     */
    @Async
    public void refreshJdState(){
        ThreadUtil.safeSleep(RunParamConstant.SLEEP_ONE_MINUTE);
        JdClient jdClient = jdClientFactory.getJdClient();
        while (true){
            JdInfoVo jdInfoVo = validJdInfo();
            if(ObjectUtil.isNull(jdInfoVo)){
                ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
                continue;
            }
            handleRefreshDate(jdClient);
            log.info("刷新京东状态完成");
            ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
        }
    }

    private static final Map<String, String> componentDictTypeMap = new HashMap<String, String>(){{
        put("confirmState", "回告状态");
        put("orderAttribute", "订单属性");
        put("Status", "删除状态");
        put("BackExplanationType", "图书回告不满足原因");
        put("OrderState", "订单状态");
    }};


    /**
     * 初始化租户字典表
     */
    @Async
    public void initTenantDict(){
        JdClient jdClient = jdClientFactory.getJdClient();
        handleDeliveryCenter(jdClient);
        handleComponent(jdClient);
        handleReturnStates();
        System.out.println("字典初始化完成");
    }

    /**
     * 补偿商品id为空
     */
    @Override
    @Async
    public void compensatingProductNon() {
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        DynamicDataSourceContextHolder.push(SourceConstant.ITEM);
        List<ProductInfo> productInfoList = productInfoService.list();
        Map<String, ProductInfo> productInfoMap = productInfoList.stream().collect(Collectors.toMap(ProductInfo::getCustomCode, o -> o, (v1, v2) -> v2));
        DynamicDataSourceContextHolder.poll();

        jdOrderDetailsService.lambdaQuery().isNull(JdOrderDetails::getProductId).list().forEach(jdOrderDetails -> {
            Long wareId = jdOrderDetails.getWareId();
            ProductInfo productInfo = productInfoMap.get(StrUtil.toString(wareId));
            if(ObjectUtil.isNotNull(productInfo)){
                jdOrderDetails.setProductId(productInfo.getId());
                jdOrderDetailsService.updateById(jdOrderDetails);
            }
        });
        SecurityUtils.clearTenantId();
        System.out.println("补偿商品id完成");
    }

    //订单状态：审核不通过/供应商驳回/已完成
    private static final ArrayList<String> notIn = new ArrayList<String>(){{
        add("7");
        add("20");
        add("3");
    }};


    /**
     * 处理刷新token数据
     * @author hj
     * @date 2023/12/21 9:01
     * @param jdClient 
     */
    public void handleRefreshDate(JdClient jdClient) {
        DynamicDataSourceContextHolder.push(SourceConstant.VICTORIATOURIST);
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        try {
            //1.查询列表订单状态不为审核不通过/供应商驳回/已完成
            int pageIndex = 1;
            long totalPage = 1;
            int pageSize = 30;
            Page<JdOrder> page = new Page<>(1, 30);
            do {
                Page<JdOrder> jdOrderPage = jdOrderService.lambdaQuery().notIn(JdOrder::getState, notIn).orderByAsc(JdOrder::getCreatedDate).page(page);
                //2.按每30个订单查询京东订单状态
                List<JdOrder> records = jdOrderPage.getRecords();
                totalPage = (jdOrderPage.getTotal() / pageSize) + (jdOrderPage.getTotal() % pageSize > 0 ? 1 : 0);
                List<Long> orderIds = records.stream().map(JdOrder::getOrderId).collect(Collectors.toList());
                JOSOrderResultDto josOrderResultDto = getJdOrderInfo(pageIndex, pageSize + 20, records.get(0).getCreatedDate(), DateUtil.offsetDay(records.get(0).getCreatedDate(), 90), jdClient, orderIds);
                List<PurchaseOrderDto> purchaseOrderList = josOrderResultDto.getPurchaseOrderList();
                List<JdOrder> jdOrderList = BeanUtil.copyToList(purchaseOrderList, JdOrder.class);
                Map<Long, JdOrder> collect = records.stream().collect(Collectors.toMap(JdOrder::getOrderId, o -> o));
                //3.更新订单信息
                for (JdOrder jdOrder : jdOrderList) {
                    Long id = collect.get(jdOrder.getOrderId()).getId();
                    jdOrder.setId(id);
                    jdOrderService.saveOrUpdate(jdOrder);
                }
                pageIndex++;
            } while (pageIndex <= totalPage);
        }catch (Exception e){
            log.error("刷新京东状态失败", e);
        }finally {
            DynamicDataSourceContextHolder.poll();
            SecurityUtils.clearTenantId();
        }
    }

    /**
     * 处理回告状态、订单属性、删除状态、图书回告不满足原因、订单状态
     * @author hj
     * @date 2023/12/13 21:56
     * @param jdClient 
     */
    private void handleComponent(JdClient jdClient) {
        componentDictTypeMap.forEach((k,v)->{
            VcGetcomponentlistRequest request=new VcGetcomponentlistRequest();
            DynamicDataSourceContextHolder.push(SourceConstant.BASE);
            SecurityUtils.setTenantId(RunParamConstant.tenantId);
            try {
                request.setType(k);
                VcGetcomponentlistResponse response=jdClient.execute(request);

                DictTenantType dictTenantType = handleDictType(k, v);

                List<CommonDictData> commonDictDataList = new ArrayList<>();
                List<Component> arg89 = response.getArg89();
                for (Component component : arg89) {
                    commonDictDataList.add(new CommonDictData(component.getKey(), component.getName()));
                }
                if ("orderAttribute".equals(k)){
                    System.out.println(123);
                }
                handleDictData(commonDictDataList, dictTenantType);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            SecurityUtils.clearTenantId();
            DynamicDataSourceContextHolder.poll();
        });
    }


    /**
     * 处理配送中心字典转换
     * @author hj
     * @date 2023/12/13 21:55
     * @param jdClient 
     */
    public void handleDeliveryCenter(JdClient jdClient){
        //获取京东仓库,并存入字典表
        VcGetwaredeliverdistinctlistRequest request=new VcGetwaredeliverdistinctlistRequest();
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        try {
            VcGetwaredeliverdistinctlistResponse response = jdClient.execute(request);

            DictTenantType dictTenantType = handleDictType(InitDictConstant.DELIVERY_CENTER, InitDictConstant.DELIVERY_CENTER_LABEL);
            //处理字典数据表
            List<WarehouseDto> warehouseList = response.getJosWarehouseResultDto().getWarehouseList();
            List<CommonDictData> commonDictDataList = new ArrayList<>();
            for (WarehouseDto warehouseDto : warehouseList) {
                commonDictDataList.add(new CommonDictData(StrUtil.toString(warehouseDto.getDeliverCenterId()), warehouseDto.getDeliverCenterName()));
            }
            handleDictData(commonDictDataList, dictTenantType);
        } catch (Exception e) {
            log.error("转换配送中心到字典出现异常",e);
        }
        SecurityUtils.clearTenantId();
        DynamicDataSourceContextHolder.poll();
    }


    private static final Map<String, String> returnStatesMap = new HashMap<String, String>(){{
        put("1", "初始退货单");
        put("2", "等待经理审核");
        put("3", "等待总监审核");
        put("4", "等待质控审核");
        put("5", "审核通过");
        put("9", "等待退货机构出库");
        put("10", "等待目的机构入库");
        put("11", "等待退货区收货");
        put("13", "等待供应商收货");
        put("17", "报废等待结算");
        put("18", "提货等待结算");
        put("20", "已完成");
        put("21", "等待删除确认");
        put("22", "已删除");
    }};

    /**
     * 处理jd退货状态字典
     * @author hj
     * @date 2023/12/20 22:27
     */
    private void handleReturnStates() {
        DynamicDataSourceContextHolder.push(SourceConstant.BASE);
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        try {
            DictTenantType dictTenantType = handleDictType(InitDictConstant.RETURN_STATES, InitDictConstant.RETURN_STATES_LABEL);
            List<CommonDictData> commonDictDataList = new ArrayList<>();
            returnStatesMap.forEach((k,v)->{
                commonDictDataList.add(new CommonDictData(k, v));
            });
            handleDictData(commonDictDataList, dictTenantType);
        } catch (Exception e) {
            log.error("处理jd退货状态字典出现异常",e);
        }
        SecurityUtils.clearTenantId();
        DynamicDataSourceContextHolder.poll();
    }
    
    /**
     * 处理字典表
     * @author hj
     * @date 2023/12/21 9:01
     */

    private void handleDictData(List<CommonDictData> commonDictDataList, DictTenantType dictTenantType) {
        //查出原来的字典
        List<DictTenantData> list = dictTenantDataService.lambdaQuery().eq(DictTenantData::getDictCode, dictTenantType.getCode()).orderByAsc(DictTenantData::getSort).list();
        Map<String, DictTenantData> dictDataMap = new HashMap<>();
        int sort = 10;
        if(CollectionUtil.isNotEmpty(list)) {
            dictDataMap = list.stream().collect(Collectors.toMap(DictTenantData::getDictKey, o -> o, (v1, v2) ->v2));
            sort = list.get(list.size()-1).getSort() + 10;
        }
        List<DictTenantData> dataList = new ArrayList<>();
        for (CommonDictData commonDictData : commonDictDataList) {
            DictTenantDataDto dictTenantDataDto = new DictTenantDataDto();
            DictTenantData dictTenantData = dictDataMap.get(commonDictData.getKey());
            if(ObjectUtil.isNotNull(dictTenantData)){
                BeanUtil.copyProperties(dictTenantData, dictTenantDataDto);
            }else{
                dictTenantDataDto.setDictCode(dictTenantType.getCode());
                dictTenantDataDto.setDictKey(StrUtil.toString(commonDictData.getKey()));
                dictTenantDataDto.setTenantId(RunParamConstant.tenantId);
                dictTenantDataDto.setSort(sort);
                sort = sort + 10;
            }
            dictTenantDataDto.setDictValue(commonDictData.getValue());
            dataList.add(dictTenantDataDto);
        }
        dictTenantDataService.saveOrUpdateBatch(dataList);
    }

    /**
     * 处理字典类型表
     * @author hj
     * @date 2023/12/13 22:03
     * @param code
     * @param name
     */
    private DictTenantType handleDictType(String code, String name){
        DictTenantType dictTenantType = new DictTenantType();
        List<DictTenantType> deliveryCenters = dictTenantTypeService.list(q -> q.eq(DictTenantType::getTenantId, RunParamConstant.tenantId).eq(DictTenantType::getCode, code));
        //处理字典类型表
        if(CollectionUtil.isNotEmpty(deliveryCenters)){
            dictTenantType = deliveryCenters.get(0);
        }else {
            dictTenantType.setCode(code);
            dictTenantType.setName(name);
            dictTenantType.setTenantId(RunParamConstant.tenantId);
            dictTenantType.setStatus(InitDictConstant.ENABLE);
            DictTenantTypeDto dictTenantTypeDto = BeanUtil.copyProperties(dictTenantType, DictTenantTypeDto.class);
            dictTenantTypeService.add(dictTenantTypeDto);
            dictTenantType.setId(dictTenantTypeDto.getId());
        }
        return dictTenantType;
    }

    /**
     * 获取京东订单
     */
    private void getJdOrderList(JdClient client, JdInfoVo jdInfoVo){
        DynamicDataSourceContextHolder.push(SourceConstant.VICTORIATOURIST);
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        try {
            int pageIndex = 1;
            int totalPage = 1;
            int pageSize = 50;
            do {
                //获取开始同步的时间
                Date startTime = jdInfoVo.getInitQueryDate();
                Date endTime = new Date();
                //根据下单时间获取数据库里最后一个订单
                JdOrder lastJdOrder = jdOrderService.lambdaQuery().isNotNull(JdOrder::getCreatedDate).orderByDesc(JdOrder::getCreatedDate).last("limit 1").oneOpt().orElse(null);
                if (ObjectUtil.isNotNull(lastJdOrder)) {
                    //将最后一个下单时间减1个小时设置为开始时间
                    startTime = DateUtil.offsetHour(lastJdOrder.getCreatedDate(), -1);
                }
                //计算总页数
                JOSOrderResultDto josOrderResultDto = getJdOrderInfo(pageIndex, pageSize, startTime, endTime, client, null);
                totalPage = (josOrderResultDto.getRecordCount() / pageSize) + (josOrderResultDto.getRecordCount() % pageSize > 0 ? 1 : 0);

                //数据返回订单是倒序反过来按正顺保存
                List<PurchaseOrderDto> purchaseOrderList = josOrderResultDto.getPurchaseOrderList();
                //京东回来的数据是按时间倒序的,使用reverse方法将list中的数据翻转为正序
                Collections.reverse(purchaseOrderList);

                //处理数据（过滤已存在的数据）
                List<Long> jdOrderIds = purchaseOrderList.stream().map(PurchaseOrderDto::getOrderId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(jdOrderIds)){
                    //获取已同步的京东订单id
                    List<Long> existOrderIds = jdOrderService.lambdaQuery().select(JdOrder::getOrderId).in(JdOrder::getOrderId, jdOrderIds).list().stream().map(JdOrder::getOrderId).collect(Collectors.toList());
                    //过滤出未同步的数据
                    List<PurchaseOrderDto> purchaseOrderListFilter = purchaseOrderList.stream().filter(item -> !existOrderIds.contains(item.getOrderId())).collect(Collectors.toList());
                    //转为系统自己的实体类
                    List<JdOrder> jdOrderList = BeanUtil.copyToList(purchaseOrderListFilter, JdOrder.class);
                    //赋值租户id
                    jdOrderList.forEach(item -> item.setTenantId(RunParamConstant.tenantId));
                    //将数据存储到库
                    jdOrderService.saveBatch(jdOrderList);
                    //获取明细
                    List<JdOrderDetails> jdOrderDetailsList = new ArrayList<>();
                    for (JdOrder jdOrder : jdOrderList) {
                        VcGetdetailbyorderidRequest request = new VcGetdetailbyorderidRequest();
                        request.setOrderId(jdOrder.getOrderId());
                        request.setIsPage(false);
                        VcGetdetailbyorderidResponse response = client.execute(request);
                        JOSDetailResultDto josDetailResultDto = response.getJosDetailResultDto();
                        List<PurchaseAllocationDetailDto> purchaseAllocationDetailList = josDetailResultDto.getPurchaseAllocationDetailList();
                        List<JdOrderDetails> jdOrderDetails = BeanUtil.copyToList(purchaseAllocationDetailList, JdOrderDetails.class);
                        DynamicDataSourceContextHolder.push(SourceConstant.ITEM);
                        jdOrderDetails.forEach(item -> {
                            item.setJdOrderId(jdOrder.getId());
                            //产品编码
                            Long wareId = item.getWareId();
                            List<ProductInfo> list = productInfoService.lambdaQuery().eq(ProductInfo::getCustomCode, wareId).list();
                            if (CollectionUtil.isEmpty(list)) {
                                //TODO 没有产品触发异常；
                            } else {
                                item.setProductId(list.get(0).getId());
                            }
                        });
                        jdOrderDetailsList.addAll(jdOrderDetails);
                    }
                    //            //赋值租户id
                    //            jdOrderList.forEach(item -> item.setTenantId(tenantId));
                    DynamicDataSourceContextHolder.push(SourceConstant.VICTORIATOURIST);
                    jdOrderDetailsService.saveOrUpdateBatch(jdOrderDetailsList);
                }
                pageIndex++;
            } while (pageIndex <= totalPage);
        } catch (Exception e){
            log.error("获取京东订单出错：" + e.getMessage(), e);
        }finally {
            SecurityUtils.clearTenantId();
            DynamicDataSourceContextHolder.poll();
        }
    }



    /**
     * 获取京东退货订单
     */
    private void getJdBackOrder(JdClient client, JdInfoVo jdInfoVo) {
        DynamicDataSourceContextHolder.push(SourceConstant.VICTORIATOURIST);
        SecurityUtils.setTenantId(RunParamConstant.tenantId);
        try {
            int pageIndex = 1;
            int totalPage = 1;
            int pageSize = 50;
            do {
                Date startTime = jdInfoVo.getInitQueryDate();
                Date endTime = new Date();
                //根据下单时间获取数据库里最后一个订单
                JdBack lastJdBack = jdBackService.lambdaQuery().isNotNull(JdBack::getCreateDate).orderByDesc(JdBack::getCreateDate).last("limit 1").oneOpt().orElse(null);
                if (ObjectUtil.isNotNull(lastJdBack)) {
                    //将最后一个下单时间减1个小时设置为开始时间
                    startTime = DateUtil.offsetHour(lastJdBack.getCreateDate(), -1);
                }
                //计算总页数
                RoResultDto jdBackOrderInfo = getJdBackInfo(pageIndex, pageSize, startTime, endTime, client);
                totalPage = (jdBackOrderInfo.getRecordCount() / pageSize) + (jdBackOrderInfo.getRecordCount() % pageSize > 0 ? 1 : 0);

                //京东回来的数据是按时间倒序的,使用reverse方法将list中的数据翻转为正序
                List<RoDto> roDtoList = jdBackOrderInfo.getRoDtoList();
                Collections.reverse(roDtoList);

                //过滤出不在数据库里的新数据
                List<Long> returnIds = roDtoList.stream().map(RoDto::getReturnId).collect(Collectors.toList());
                if(CollectionUtil.isNotEmpty(returnIds)){
                    List<Long> existReturnIds = jdBackService.lambdaQuery().select(JdBack::getReturnId).in(JdBack::getReturnId, returnIds).list().stream().map(JdBack::getReturnId).collect(Collectors.toList());
                    roDtoList = roDtoList.stream().filter(item -> !existReturnIds.contains(item.getReturnId())).collect(Collectors.toList());
                    //转成我们自己的实体类
                    List<JdBack> jdBackList = BeanUtil.copyToList(roDtoList, JdBack.class);
                    //赋值租户id
                    //jdBackList.forEach(item -> item.setTenantId(tenantId));
                    jdBackService.saveBatch(jdBackList);
                    //获取明细
                    List<JdBackDetails> JdBackDetailsList = new ArrayList<>();
                    for (JdBack jdBack : jdBackList) {
                        VcGetReturnOrderDetailRequest request = new VcGetReturnOrderDetailRequest();
                        request.setReturnId(jdBack.getReturnId());
                        VcGetReturnOrderDetailResponse response = client.execute(request);
                        DetailResultDto detailResultDto = response.getDetailResultDto();
                        List<JdBackDetails> jdBackDetails = BeanUtil.copyToList(detailResultDto.getDetailDtoList(), JdBackDetails.class);
                        DynamicDataSourceContextHolder.push(SourceConstant.ITEM);
                        jdBackDetails.forEach(item -> {
                            item.setJdBackId(jdBack.getId());
                            //产品编码
                            Long wareId = item.getWareId();
                            List<ProductInfo> list = productInfoService.lambdaQuery().eq(ProductInfo::getCustomCode, wareId).list();
                            if (CollectionUtil.isEmpty(list)) {
                                //TODO 没有产品触发异常；
                            } else {
                                item.setProductId(list.get(0).getId());
                            }
                        });
                        JdBackDetailsList.addAll(jdBackDetails);
                    }
                    DynamicDataSourceContextHolder.push(SourceConstant.VICTORIATOURIST);
                    jdBackDetailsService.saveBatch(JdBackDetailsList);
                }
                pageIndex++;
            } while (pageIndex <= totalPage);
        }catch (Exception e){
            log.error("获取京东退货订单出错：" + e.getMessage(), e);
        }finally {
            SecurityUtils.clearTenantId();
            DynamicDataSourceContextHolder.poll();
        }

    }



    public void startJdSalesReturns(){
        JdClient jdClient = jdClientFactory.getJdClient();
        while (true){
            JdInfoVo jdInfoVo = jdInfoService.getOne();
            boolean online = jdInfoVo.getOnline() > 0 ? true : false;
            if(!online){
                log.info("京东已经下线");
                ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
                continue;
            }
            //开始校验是否符合条件
            if (ObjectUtil.isNull(jdInfoVo.getInitQueryDate())) {
                log.error("请线配置京东初始化查询时间");
                ThreadUtil.safeSleep(RunParamConstant.SLEEP_TEN_SECOND);
                continue;
            }
            try {
                getJdBackOrder(jdClient, jdInfoVo);
            }catch (Exception e){
                log.error("获取京东订单列表出错：" + e.getMessage(), e);
            }
            ThreadUtil.safeSleep(30000);
        }
    }


    /**
     * 获取京东退货订单
     */
    /*private void getJdSalesReturns(JdClient client, JdInfoVo jdInfoVo) throws Exception {
        int pageIndex = 1;
        int totalPage = 1;
        int pageSize = 50;
        do {
            Date startTime = jdInfoVo.getInitQueryDate();
            Date endTime = new Date();
            //根据下单时间获取数据库里最后一个订单
            JdSalesReturns jdSalesReturns = jdSalesReturnsService.getOne(q -> q.isNotNull(JdSalesReturns::getCreateTime).orderByDesc(JdSalesReturns::getCreateTime));
            if (ObjectUtil.isNotEmpty(jdSalesReturns)) {
                //将最后一个下单时间减1个小时设置为开始时间
                startTime = DateUtil.offsetHour(jdSalesReturns.getCreateTime(), -1);
            }
            //计算总页数
            RoResultDto jdSalesReturnsInfo = getJdSalesReturnsInfo(pageIndex, pageSize, startTime, endTime, client);
            totalPage = (jdSalesReturnsInfo.getRecordCount()/pageSize)+(jdSalesReturnsInfo.getRecordCount()%pageSize>0?1:0);
            Integer recordCount = jdSalesReturnsInfo.getRecordCount();
            List<RoDto> roDtoList = jdSalesReturnsInfo.getRoDtoList();
            //京东回来的数据是按时间倒序的,使用reverse方法将list中的数据翻转为正序
            Collections.reverse(roDtoList);

            //过滤出不在数据库里的新数据
            List<Long> returnIds = roDtoList.stream().map(RoDto::getReturnId).collect(Collectors.toList());
            List<Long> existReturnIds = jdSalesReturnsService.listObject(JdSalesReturns::getRefundId, q -> q.in(JdSalesReturns::getRefundId, returnIds));
            roDtoList = roDtoList.stream().filter(item -> !existReturnIds.contains(item.getReturnId())).collect(Collectors.toList());
            //转成我们自己的实体类
            List<JdBack> jdBackList = BeanUtil.copyToList(roDtoList, JdBack.class);
            jdBackService.saveBatch(jdBackList);
//            //获取明细
            List<JdBackDetails> JdBackDetailsList = new ArrayList<>();
            for (JdBack jdBack : jdBackList) {
                VcGetReturnOrderDetailRequest request = new VcGetReturnOrderDetailRequest();
                request.setReturnId(jdBack.getReturnId());
                VcGetReturnOrderDetailResponse response = client.execute(request);
                DetailResultDto detailResultDto = response.getDetailResultDto();

                List<JdBackDetails> jdBackDetails = BeanUtil.copyToList(detailResultDto.getDetailDtoList(), JdBackDetails.class);
                jdBackDetails.forEach(item -> {
                    item.setJdBackId(jdBack.getId());
                    //产品编码
                    Long wareId = item.getWareId();
                    List<ProductInfo> list = productInfoService.lambdaQuery().eq(ProductInfo::getCustomCode, wareId).list();
                    if(CollectionUtil.isEmpty(list)){
                        //TODO 没有产品触发异常；
                    }else {
                        item.setProductId(list.get(0).getId());
                    }
                });
                JdBackDetailsList.addAll(jdBackDetails);
            }
            jdBackDetailsService.saveBatch(JdBackDetailsList);
            pageIndex++;
        } while (pageIndex <= totalPage);

    }*/


    /**
     * 请求API工具方法
     */
    private static JSONObject getJSON(HttpRequestBase httpRequestBase) throws IOException {
        HttpClient client = HttpClients.createDefault();
        httpRequestBase.setConfig(RequestConfig.custom().setConnectTimeout(3000).build());
        HttpResponse response = client.execute(httpRequestBase);
        int statusCode = response.getStatusLine().getStatusCode();
        HttpEntity entity = response.getEntity();
        String responseStr = IOUtils.toString(entity.getContent(), StandardCharsets.UTF_8);
        if (statusCode != 200) {
            log.error("请求失败 {} {} {}", statusCode, httpRequestBase.getURI(), responseStr);
        }
        return JSONObject.parseObject(responseStr);
    }


    /**
     * 将jd返回的json对象转换成jdInfoVo
     * @author hj
     * @date 2023/12/10 22:03
     * @param responseJson
     * @param jdInfoVo
     */
    private void convertJdInfoVO(JSONObject responseJson, JdInfoVo jdInfoVo) {
        jdInfoVo.setAccessToken(responseJson.getString(RunParamConstant.ACCESS_TOKEN));
        jdInfoVo.setRefreshToken(responseJson.getString(RunParamConstant.REFRESH_TOKEN));
        int expires_in = responseJson.getIntValue("expires_in", 0);
        int offsetHour = 24;
        if(expires_in>0){
            offsetHour = expires_in/60/60;
        }
        jdInfoVo.setExpireTime(DateUtil.offsetHour(new Date(), offsetHour));
        jdInfoVo.setLastRefreshTime(DateUtil.date());
        jdInfoVo.setOnline(1);
    }

    /**
     * 处理jd返回对象
     * @author hj
     * @date 2023/12/10 22:07
     * @param responseJson
     */
    private void dealJdTokenResponse(JSONObject responseJson) {
        if (ObjectUtil.isNotEmpty(responseJson.getString(RunParamConstant.ACCESS_TOKEN)) && ObjectUtil.isNotEmpty(responseJson.getString(RunParamConstant.REFRESH_TOKEN))) {
            log.info("成功获取AccessToken并保存" + responseJson);
            JdInfoVo jdInfoVo = jdInfoService.getOne();
            convertJdInfoVO(responseJson, jdInfoVo);
            JdInfoDto jdInfoDto = BeanUtil.copyProperties(jdInfoVo, JdInfoDto.class);
            jdInfoService.addOrUpdate(jdInfoDto);
        } else {
            log.error("获取AccessToken失败：" + responseJson);
        }
    }






    /**
     * 获取京东订单信息分页
     */
    private JOSOrderResultDto getJdOrderInfo(Integer pageIndex, Integer pageSize, Date startTime, Date endTime, JdClient client, List<Long> orderIds) throws Exception {
        VcGetpurchaseorderlistRequest request = new VcGetpurchaseorderlistRequest();
        request.setCreatedDateStart(startTime);
        request.setCreatedDateEnd(endTime);
        request.setPageIndex(pageIndex);
        request.setPageSize(pageSize);
        if(CollectionUtil.isNotEmpty(orderIds)){
            request.setOrderIds(orderIds.stream().map(o->StrUtil.toString(orderIds)).collect(Collectors.joining(",")));
        }
        VcGetpurchaseorderlistResponse response = client.execute(request);
        validSuccess(response, "获取京东订单信息分页");
        return response.getJosOrderResultDto();
    }

    /**
     * 获取京东退货单信息分页
     */
    private RoResultDto getJdBackInfo(Integer pageIndex, Integer pageSize, Date startTime, Date endTime, JdClient client) throws Exception {
        VcReturnOrderListPageGetRequest request = new VcReturnOrderListPageGetRequest();
        request.setCreateDateBegin(startTime);
        request.setCreateDateEnd(endTime);
        request.setPageSize(pageIndex);
        request.setPageIndex(pageSize);
        VcReturnOrderListPageGetResponse response = client.execute(request);
        validSuccess(response, "获取京东退货单信息分页");
        return response.getRoResultDto();
    }

    /**
     * 获取京东退货售后单信息分页
     */
/*    private RoResultDto getJdSalesReturnsInfo(Integer pageIndex, Integer pageSize, Date startTime, Date endTime, JdClient client) throws Exception {
        EdiwsRoRefundInfoListRequest request=new EdiwsRoRefundInfoListRequest();
        request.setCreateDateBegin(startTime);
        request.setCreateDateEnd(endTime);
        request.setPageSize(pageIndex);
        request.setPageIndex(pageSize);
        VcReturnOrderListPageGetResponse response = client.execute(request);
        validSuccess(response, "获取京东退货单信息分页");
        return response.getRoResultDto();
    }*/


    void validSuccess(AbstractResponse response, String method){
        String code = response.getCode();
        if(!"0".equals(code)){
            log.error("获取{}失败：{}", method ,response.getZhDesc());
            throw new RuntimeException("获取"+ method +"失败：" + response.getZhDesc());
        }
    }


    private JdInfoVo validJdInfo(){
        JdInfoVo jdInfoVo = jdInfoService.getOne();
        boolean online = jdInfoVo.getOnline() > 0 ? true : false;
        if(!online){
            log.info("京东已经下线");
            return null;
        }
        //开始校验是否符合条件
        if (ObjectUtil.isNull(jdInfoVo.getInitQueryDate())) {
            log.error("请线配置京东初始化查询时间");
            return null;
        }
        return jdInfoVo;
    }

    public static void main(String[] args) throws Exception {
//        JdClient client = new DefaultJdClient("http://api.jd.com/routerjson", "a1f79f4670fd43a28fa2de02abd86f03ytfm", JdParamConstant.appKey, JdParamConstant.appSecret);
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        String str = StrUtil.toString(list);
        System.out.println(str);
    }

}
