package com.neusoft.smart.pos.inventory.service;

import com.neusoft.smart.pos.dto.inventory.request.SellAndWarehouseOutRequest;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.utils.SpringUtils;
import com.neusoft.smart.pos.inventory.constants.GoodsErrorCode;
import com.neusoft.smart.pos.inventory.persistent.domain.InventoryGoodsInfo;
import com.neusoft.smart.pos.inventory.persistent.domain.InventoryGoodsLimit;
import com.neusoft.smart.pos.inventory.persistent.domain.InventoryGoodsLimitBean;
import com.neusoft.smart.pos.inventory.persistent.domain.InventoryGoodsLimitBeanExample;
import com.neusoft.smart.pos.inventory.persistent.domain.InventoryGoodsLimitExample;
import com.neusoft.smart.pos.inventory.persistent.mapper.InventoryGoodsInfoMapper;
import com.neusoft.smart.pos.inventory.persistent.mapper.InventoryGoodsLimitBeanMapper;
import com.neusoft.smart.pos.inventory.persistent.mapper.InventoryGoodsLimitMapper;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 出库限制 前置通知
 */
@Aspect
@Component
public class WarehouseOutLimitAspect {
    
    @Autowired
    private InventoryGoodsLimitBeanMapper inventoryGoodsLimitBeanMapper;
    
    @Autowired
    private InventoryGoodsLimitMapper inventoryGoodsLimitMapper;
    
    @Autowired
    private InventoryGoodsInfoMapper inventoryGoodsInfoMapper;
    
    @Before("execution(* com.neusoft.smart.pos.inventory.service.*.warehouseOut(..)) && args(sellAndWarehouseOutRequest)")
    public void check(SellAndWarehouseOutRequest sellAndWarehouseOutRequest) {
        List<String> messages = new ArrayList<>();
        Map<Integer, WarehouseOutLimitInterface> limitBeanMap = this.getAllLimitBean();
        for (SellAndWarehouseOutRequest.OrderItem orderItem : sellAndWarehouseOutRequest.getOrderItems()) {
            List<InventoryGoodsLimit> limits = this.getByGoodsId(orderItem.getGoodsId());
            InventoryGoodsInfo inventoryGoodsInfo = inventoryGoodsInfoMapper.selectByPrimaryKey(orderItem.getGoodsId());
            limits.forEach(limit -> {
                WarehouseOutLimitInterface warehouseOutLimit = limitBeanMap.get(limit.getBeanId());
                Pair<Boolean, String> result = warehouseOutLimit.checkLimit(limit, inventoryGoodsInfo, orderItem);
                if (!result.getFirst()) {
                    messages.add(result.getSecond());
                }
            });
        }
        if (!messages.isEmpty()) {
            throw new BusinessCommonException(GoodsErrorCode.LIMIT_CHECK_ERROR, StringUtils.collectionToDelimitedString(messages, ","));
        }
    }
    
    private List<InventoryGoodsLimit> getByGoodsId(Integer goodsId) {
        InventoryGoodsLimitExample example = new InventoryGoodsLimitExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId);
        return inventoryGoodsLimitMapper.selectByExample(example);
    }
    
    private Map<Integer, WarehouseOutLimitInterface> getAllLimitBean() {
        List<InventoryGoodsLimitBean> beans = inventoryGoodsLimitBeanMapper.selectByExample(new InventoryGoodsLimitBeanExample());
        Map<Integer, WarehouseOutLimitInterface> limitImpls = beans.stream().collect(Collectors.toMap(InventoryGoodsLimitBean::getId, bean -> (WarehouseOutLimitInterface) SpringUtils.getBean(bean.getBeanName())));
        return limitImpls;
    }
}
