
package com.tmerclub.cloud.order.manager;

import cn.hutool.core.collection.CollUtil;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.product.vo.SpuVO;
import com.tmerclub.cloud.order.bo.mongo.MongoPurchaseOrderBO;
import com.tmerclub.cloud.order.constant.PurchasesStatusEnum;
import com.tmerclub.cloud.order.dto.PurchaseOrderDTO;
import org.checkerframework.checker.units.qual.C;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单统计
 * @author tmerclub
 * @date 2020/12/07
 */
@Component
public class MongoPurchaseOrderManager {
    private static final Logger logger = LoggerFactory.getLogger(MongoPurchaseOrderManager.class);

    @Autowired
    private MongoTemplate mongoTemplate;

    public void save(MongoPurchaseOrderBO mongoPurchaseOrderBO) {
        mongoTemplate.save(mongoPurchaseOrderBO);
    }

    public List<Long> listSpuIdOfStockChange(Date beginTime, Date endTime) {
        List<AggregationOperation> aggregationOperations = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.nonNull(beginTime) && Objects.nonNull(endTime)) {
            aggregationOperations.add(Aggregation.match(Criteria.where("updateTime").gt(beginTime).lte(endTime)));
        }
        aggregationOperations.add(Aggregation.unwind("purchaseOrderItems"));

        aggregationOperations.add(Aggregation.group("purchaseOrderItems.spuId"));

        Aggregation aggregation = Aggregation.newAggregation(
                aggregationOperations
        );
        TypedAggregation<MongoPurchaseOrderBO> typedAggregation =
                Aggregation.newAggregation(
                        MongoPurchaseOrderBO.class,
                        aggregationOperations
                );
        logger.info("listSpuIdOfStockChange()的mongodb查询语句： {}", typedAggregation);
        AggregationResults<MongoPurchaseOrderBO> aggregationResults = mongoTemplate.aggregate(typedAggregation, MongoPurchaseOrderBO.class);
        List<MongoPurchaseOrderBO> spuList = aggregationResults.getMappedResults();
        if (CollUtil.isEmpty(spuList)) {
            return Collections.emptyList();
        }

        return spuList.stream().map(MongoPurchaseOrderBO::getPurchaseOrderId).collect(Collectors.toList());
    }

    /**
     * 统计未完成的采购订单数
     * @param warehouseId 仓库id
     * @return 未完成数
     */
    public Long countUnFinishPurchase(Long warehouseId) {
        Criteria criteria = new Criteria()
                .orOperator(Criteria.where("warehouseId").is(warehouseId),
                        Criteria.where("supplierWarehouseId").is(warehouseId))
                .and("status").nin(PurchasesStatusEnum.COMPLETION.value(), PurchasesStatusEnum.VOIDED.value());
        Query query = new Query(criteria);
        logger.info("countUnFinishPurchase()的mongodb查询语句： {}", query);
        return mongoTemplate.count(query, MongoPurchaseOrderBO.class);
    }

    /**
     * 获取采购订单列表
     * @param purchaseOrderDTO 采购订单dto
     * @return 采购订单列表
     */
    public List<MongoPurchaseOrderBO> listPurchaseOrder(PurchaseOrderDTO purchaseOrderDTO) {
        Query query = new Query(this.buildListCriteria(purchaseOrderDTO));
        logger.info("listPurchaseOrder()的mongodb查询语句： {}", query);
        return mongoTemplate.find(query, MongoPurchaseOrderBO.class);
    }

    /**
     * 构建获取列表查询语句
     * @param purchaseOrderDTO 采购订单dto
     * @return 查询语句
     */
    private Criteria buildListCriteria(PurchaseOrderDTO purchaseOrderDTO) {
        Criteria criteria = new Criteria();
        if (!Objects.isNull(purchaseOrderDTO.getWarehouseId())) {
            criteria.orOperator(Criteria.where("warehouseId").is(purchaseOrderDTO.getWarehouseId()),
                    Criteria.where("supplierWarehouseId").is(purchaseOrderDTO.getWarehouseId()));
        }
        if (!CollectionUtils.isEmpty(purchaseOrderDTO.getNotInStatuses())) {
            criteria.and("status").nin(purchaseOrderDTO.getNotInStatuses());
        }
        return criteria;
    }

}
