package com.trade.admin.job;

import cn.hutool.core.collection.CollectionUtil;
import com.trade.service.thirdparty.xiaotu.dto.BusinessCommonRequest;
import com.trade.service.trade.filingdoc.service.FilingDocService;
import com.trade.service.trade.salesorder.domain.CustomsDeclaration;
import com.trade.service.trade.salesorder.domain.CustomsDeclarationGoods;
import com.trade.service.trade.salesorder.service.ICustomsDeclarationFileService;
import com.trade.service.trade.salesorder.service.ICustomsDeclarationGoodsService;
import com.trade.service.trade.salesorder.service.ICustomsDeclarationService;
import com.trade.service.thirdparty.xiaotu.dto.CustomsDeclarationRequest;
import com.trade.service.thirdparty.xiaotu.dto.CustomsDeclarationResponse;
import com.trade.service.thirdparty.xiaotu.service.XiaotuRequestService;
import com.trade.service.trade.salesorder.service.ISalesOrderService;
import com.trade.service.trade.salesorder.vo.SalesOrder4CustomsDeclarationVO;
import com.trade.service.trade.filingdoc.vo.SalesOrder4CustomsFileQueryVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Slf4j
public class CustomsDeclarationSchedule {

    @Resource
    private XiaotuRequestService xiaotuRequestService;
    @Resource
    private ICustomsDeclarationService customsDeclarationService;
    @Resource
    private ICustomsDeclarationGoodsService customsDeclarationGoodsService;
    @Resource
    private ISalesOrderService salesOrderService;
    @Resource
    private ICustomsDeclarationFileService customsDeclarationFileService;
    @Resource
    private FilingDocService filingDocService;

    /**
     * 定时拉取小图的报关单信息 - 未匹配的销售订单数据，并保存到数据库中<></br>
     * 只拉取代理订单
     */
    @Scheduled(cron = "0 0 1 * * ?")
    @Transactional
    public void batchProcessCustomsDeclaration4SalesOrder() {
        log.info("batchProcessCustomsDeclaration4SalesOrder execute start");
        List<SalesOrder4CustomsDeclarationVO> saleOrderNos = salesOrderService.queryOrderNo4GetCustomsDeclaration();
        dataProcess(saleOrderNos);
        log.info("batchProcessCustomsDeclaration4SalesOrder execute end");
    }

    /**
     * 定时更新小图的报关单信息 - 未结关的报关单数据
     */
    @Scheduled(cron = "0 0 2 * * ?")
    @Transactional
    public void batchProcessCustomsDeclarationUnFinish() {
        log.info("batchProcessCustomsDeclarationUnFinish execute start");
        List<SalesOrder4CustomsDeclarationVO> saleOrderNos = customsDeclarationService
                .queryOrderNo4UpdateCustomsDeclaration();
        dataProcess(saleOrderNos);
        log.info("batchProcessCustomsDeclarationUnFinish execute end");
    }

    /**
     * 定时下载报关单/报关协议文件
     */
    @Scheduled(cron = "0 0 3 * * ?")
    @Transactional
    public void batchDownloadCustomsDeclarationFile() {
        log.info("batchDownloadCustomsDeclarationFile execute start");
        List<SalesOrder4CustomsFileQueryVO> saleOrderNos = customsDeclarationService
                .queryData4DownloadCustomsDeclarationFile();
        for (SalesOrder4CustomsFileQueryVO queryVO : saleOrderNos) {
            try {
                customsDeclarationFileService.downloadCustomsDeclarationFile(queryVO);
            } catch (Exception e) {
                log.error("batchDownloadCustomsDeclarationFile execute error, queryNo=" + queryVO.getQueryNo(), e);
                e.printStackTrace();
            }
        }
        log.info("batchDownloadCustomsDeclarationFile execute end");
    }

    /**
     * 小图定时写入任务，每小时执行一次
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void writeFilingDocWithCron() {
        log.info("writeFilingDocWithCron execute start");
        filingDocService.writeFilingDoc();
        log.info("writeFilingDocWithCron execute end");
    }

    private void dataProcess(List<SalesOrder4CustomsDeclarationVO> saleOrderNos) {
        if (CollectionUtil.isEmpty(saleOrderNos)) {
            log.info("需要处理的订单为空, dataProcess execute end");
            return;
        }
        Map<String, List<SalesOrder4CustomsDeclarationVO>> groupBy = saleOrderNos.stream()
                .collect(Collectors.groupingBy(e -> e.getXtEid() + "_" + e.getXtUserId()));
        groupBy.forEach((k, v) -> {
            BusinessCommonRequest businessCommonRequest = new BusinessCommonRequest();
            businessCommonRequest.setXtEid(k.split("_")[0]);
            businessCommonRequest.setXtUid(k.split("_")[1]);
            CustomsDeclarationRequest request = new CustomsDeclarationRequest();
            try {
                request.setCkhths(
                        v.stream().map(SalesOrder4CustomsDeclarationVO::getQueryNo).collect(Collectors.toList()));
                request.setPage(1);
                request.setPageSize(100);
                List<CustomsDeclarationResponse> customsDeclarationResponses = xiaotuRequestService
                        .customsDeclarationInquiry(request, businessCommonRequest);
                while (CollectionUtil.isNotEmpty(customsDeclarationResponses)) {
                    dataHandle(customsDeclarationResponses);
                    if (customsDeclarationResponses.size() < request.getPageSize()) {
                        break;
                    }
                    request.setPage(request.getPage() + 1);
                    customsDeclarationResponses = xiaotuRequestService.customsDeclarationInquiry(request,
                            businessCommonRequest);
                }
            } catch (Exception e) {
                log.error("CustomsDeclarationSchedule execute error", e);
                e.printStackTrace();
            }
        });
    }

    /**
     * 数据处理 1. 根据报关单海关编号分组<></br>
     * 2. 遍历分组，查询数据库中是否存在该订单，如果存在，则更新，如果不存在，则新增<></br>
     * 3. 订单的总运费、总保费、总杂费、总件数、总净重、集装箱号做汇总，其他数据取第一个订单的<></br>
     * 4. 小图反馈，订单号和报关单编号通常是一对一关系</br>
     * 
     * @param customsDeclarationResponses 订单列表
     */
    private void dataHandle(List<CustomsDeclarationResponse> customsDeclarationResponses) {
        Map<String, List<CustomsDeclarationResponse>> groupBy = customsDeclarationResponses.stream()
                .collect(Collectors.groupingBy(CustomsDeclarationResponse::getBgdhgbh));
        groupBy.forEach((k, v) -> {
            CustomsDeclaration customsDeclaration = customsDeclarationService.getByBgdh(k);
            CustomsDeclaration saveObj = new CustomsDeclaration(v.get(0));
            if (customsDeclaration != null) {
                saveObj.setId(customsDeclaration.getId());
                for (CustomsDeclarationResponse customsDeclarationResponse : v) {
                    CustomsDeclarationGoods customsDeclarationGoods = customsDeclarationGoodsService
                            .getByCkbgdh(customsDeclarationResponse.getCkbgdh());
                    if (null == customsDeclarationGoods) {
                        customsDeclarationGoodsService.addCustomsDeclarationGoods(customsDeclarationResponse);
                    } else {
                        customsDeclarationGoodsService.updateCustomsDeclarationGoods(customsDeclarationResponse,
                                customsDeclarationGoods.getId());
                    }
                }
            } else {
                // 保存报关单明细
                v.forEach(customsDeclarationGoodsService::addCustomsDeclarationGoods);
                // 更新订单-报关单状态
                salesOrderService.updateCustomsDeclarationStatusFinishedByOrderNo(v.get(0).getCkhth());
            }
            saveCustomsDeclaration(saveObj);
        });
    }

    private void saveCustomsDeclaration(CustomsDeclaration customsDeclaration) {
        List<CustomsDeclarationGoods> customsDeclarationGoodsList = customsDeclarationGoodsService
                .getByBgdh(customsDeclaration.getBgdhgbh());
        // 运费金额合计
        customsDeclaration.setYfje(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getYfje)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 保费金额合计
        customsDeclaration.setBfje(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getBfje)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 杂费金额合计
        customsDeclaration.setZfje1(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getZfje1)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 件数合计
        customsDeclaration.setJs1(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getJs1)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 毛重合计
        customsDeclaration.setMz2(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getMz2)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 净重
        customsDeclaration.setJz(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getJz)
                .reduce(BigDecimal.ZERO, BigDecimal::add));
        // 集装箱号
        customsDeclaration.setJzxh(customsDeclarationGoodsList.stream().map(CustomsDeclarationGoods::getJzxh)
                .collect(Collectors.joining(",")));
        if (null != customsDeclaration.getId()) {
            customsDeclarationService.updateCustomsDeclaration(customsDeclaration);
        } else {
            customsDeclarationService.addCustomsDeclaration(customsDeclaration);
        }
    }
}
