
package com.tmerclub.cloud.search.controller.platform;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.tmerclub.cloud.api.multishop.feign.WalletLogOperationFeignClient;
import com.tmerclub.cloud.api.order.constant.OrderStatus;
import com.tmerclub.cloud.api.supplier.feign.SupplierWalletLogOperationFeignClient;
import com.tmerclub.cloud.api.vo.EsPageVO;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.order.bo.EsOrderBO;
import com.tmerclub.cloud.common.order.dto.OrderSearchDTO;
import com.tmerclub.cloud.common.product.vo.search.SpuAdminVO;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.util.Json;
import com.tmerclub.cloud.search.manager.OrderSearchManager;
import com.tmerclub.cloud.search.util.EsSearchUtil;
import io.swagger.v3.oas.annotations.Operation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 恢复供应商结算和未结算记录用的，商城中不要调这个类下的接口
 *
 * @author tmerclub
 * @date 2020/11/16
 */
public class WalletLogOperationController {

    private static final Logger logger = LoggerFactory.getLogger(WalletLogOperationController.class);

    @Autowired
    private OrderSearchManager orderSearchManager;
    @DubboReference
    private WalletLogOperationFeignClient walletLogOperationFeignClient;
    @DubboReference
    private SupplierWalletLogOperationFeignClient supplierWalletLogOperationFeignClient;

    @GetMapping("/supplierLog")
    @Operation(summary = "恢复供应商待结算、已结算记录", description = "商品管理信息列表（平台端）")
    public ServerResponseEntity<EsPageVO<SpuAdminVO>> supplierLog() {
        OrderSearchDTO param = new OrderSearchDTO();
        param.setPageSize(50);
        List<Integer> mustNotStatusList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        mustNotStatusList.add(OrderStatus.CLOSE.value());
        mustNotStatusList.add(OrderStatus.WAIT_GROUP.value());
        mustNotStatusList.add(OrderStatus.WAIT_PURCHASE.value());
        mustNotStatusList.add(OrderStatus.WAIT_BALANCE.value());
        param.setMustNotStatusList(mustNotStatusList);
        String scrollId = null;
        //设置查询超时时间
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(5L));
        SearchRequest searchRequest = orderSearchManager.buildScrollSearchRequest(param, scroll);
        try {
            // 进行第一次滚动查询
            SearchResponse searchResponse = EsSearchUtil.search(searchRequest);
            scrollId = searchResponse.getScrollId();
            /*
             在这个位置已经读到了前一百条数据，可以在这先对这一百数据进行处理。下面滚动查询剩下的数据
             */
            addSupplierLog(searchResponse);
            //记录要滚动的ID
            //滚动查询部分，将从第101笔数据开始取
            SearchHit[] hitsScroll = searchResponse.getHits().getHits();
            while (hitsScroll != null && hitsScroll.length > 0) {
                //构造滚动查询条件
                SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
                searchScrollRequest.scroll(scroll);
                searchResponse = EsSearchUtil.scroll(searchScrollRequest);
                addSupplierLog(searchResponse);
                scrollId = searchResponse.getScrollId();
                hitsScroll = searchResponse.getHits().getHits();
            }
        } catch (Exception e) {
            logger.error("订单结算异常", e);
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        } finally {
            if (Objects.nonNull(scrollId)) {
                //清除滚动，否则影响下次查询
                EsSearchUtil.clearScroll(scrollId);
            }
        }
        return ServerResponseEntity.success();
    }

    /**
     * 删除供应商中未支付的待结算记录
     * 基本用不到，只有supplierLog()生成记录时没有过滤掉未支付和支付失败的订单时
     * 才会用这个接口来删除supplierLog()多生成的未支付和支付失败的订单的待结算记录
     *
     * @return
     */
    @GetMapping("/deleteSupplierLog")
    @Operation(summary = "删除供应商中未支付的待结算记录", description = "删除供应商待结算")
    public ServerResponseEntity<EsPageVO<SpuAdminVO>> deleteSupplierLog() {
        OrderSearchDTO param = new OrderSearchDTO();
        param.setPageSize(50);
        // 状态可以改为待支付（UNPAY）、交易失败（CLOSE）
        param.setStatus(OrderStatus.CLOSE.value());
        String scrollId = null;
        //设置查询超时时间
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(5L));
        SearchRequest searchRequest = orderSearchManager.buildScrollSearchRequest(param, scroll);
        try {
            // 进行第一次滚动查询
            SearchResponse searchResponse = EsSearchUtil.search(searchRequest);
            scrollId = searchResponse.getScrollId();
            /*
             在这个位置已经读到了前一百条数据，可以在这先对这一百数据进行处理。下面滚动查询剩下的数据
             */
            deleteSupplierLog(searchResponse);
            //记录要滚动的ID
            //滚动查询部分，将从第101笔数据开始取
            SearchHit[] hitsScroll = searchResponse.getHits().getHits();
            while (hitsScroll != null && hitsScroll.length > 0) {
                //构造滚动查询条件
                SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
                searchScrollRequest.scroll(scroll);
                searchResponse = EsSearchUtil.scroll(searchScrollRequest);
                deleteSupplierLog(searchResponse);
                scrollId = searchResponse.getScrollId();
                hitsScroll = searchResponse.getHits().getHits();
            }
        } catch (Exception e) {
            logger.error("订单结算异常", e);
            return ServerResponseEntity.fail(ResponseEnum.EXCEPTION);
        } finally {
            if (Objects.nonNull(scrollId)) {
                //清除滚动，否则影响下次查询
                EsSearchUtil.clearScroll(scrollId);
            }
        }
        return ServerResponseEntity.success();
    }

    private void addSupplierLog(SearchResponse searchResponse) {
        List<EsOrderBO> orderBOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            EsOrderBO esOrderBO = JSON.parseObject(hit.getSourceAsString(), EsOrderBO.class);
            if (Objects.equals(esOrderBO.getStatus(), OrderStatus.CLOSE.value())) {
                logger.info("订单关闭");
            }
            if (Objects.isNull(esOrderBO.getSupplierId()) || Objects.equals(esOrderBO.getSupplierId(), 0L)) {
                continue;
            }
            orderBOList.add(esOrderBO);
        }
        if (CollUtil.isEmpty(orderBOList)) {
            return;
        }
        walletLogOperationFeignClient.addSupplierLog(Json.toJsonString(orderBOList));
    }

    private void deleteSupplierLog(SearchResponse searchResponse) {
        List<EsOrderBO> orderBOList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            EsOrderBO esOrderBO = JSON.parseObject(hit.getSourceAsString(), EsOrderBO.class);
            if (!Objects.equals(esOrderBO.getStatus(), OrderStatus.CLOSE.value()) || Objects.equals(esOrderBO.getIsPayed(), 1)) {
                continue;
            }
            if (Objects.isNull(esOrderBO.getSupplierId()) || Objects.equals(esOrderBO.getSupplierId(), 0L)) {
                continue;
            }
            orderBOList.add(esOrderBO);
        }
        if (CollUtil.isEmpty(orderBOList)) {
            return;
        }
        supplierWalletLogOperationFeignClient.deleteSupplierLog(Json.toJsonString(orderBOList));
    }
}
