package com.fjhx.service.stock.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.entity.product.ProductCombination;
import com.fjhx.entity.product.ProductInfo;
import com.fjhx.entity.stock.Stock;
import com.fjhx.entity.stock.StockCombination;
import com.fjhx.enums.stock.InTypeEnum;
import com.fjhx.enums.stock.OutTypeEnum;
import com.fjhx.mapper.stock.StockCombinationMapper;
import com.fjhx.params.stock.*;
import com.fjhx.service.product.ProductCombinationService;
import com.fjhx.service.stock.StockCombinationService;
import com.fjhx.service.stock.StockService;
import com.fjhx.utils.Assert;
import com.fjhx.utils.UserClientUtil;
import com.fjhx.utils.wrapperUtil.IWrapper;
import com.fjhx.utils.wrapperUtil.KeywordData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 产品组合记录 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2023-02-16
 */
@Service
public class StockCombinationServiceImpl extends ServiceImpl<StockCombinationMapper, StockCombination> implements StockCombinationService {

    @Autowired
    private ProductCombinationService productCombinationService;

    @Autowired
    private StockService stockService;


    @Override
    public Page<StockCombinationPageVo> getPage(StockCombinationPageDto dto) {

        // 拼接查询条件
        IWrapper<Object> wrapper = IWrapper.getWrapper(dto)
                .keyword(
                        new KeywordData("pi", ProductInfo::getCode),
                        new KeywordData("pi", ProductInfo::getName)
                )
                .orderByDesc("sc", StockCombination::getCreateTime);

        // 查询产品组合记录分页
        Page<StockCombinationPageVo> page = baseMapper.getPage(dto.getPage(), wrapper);

        // 赋值创作人名称
        List<StockCombinationPageVo> records = page.getRecords();
        if (records.size() == 0) {
            return page;
        }

        Map<Long, String> userNameMap = UserClientUtil.getUserNameMap(records, StockCombinationPageVo::getCreateUser);
        for (StockCombinationPageVo stockCombinationPageVo : records) {
            stockCombinationPageVo.setCreateUserName(userNameMap.get(stockCombinationPageVo.getCreateUser()));
        }

        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(StockCombination stockCombination) {

        // 赋值产品组合记录id
        stockCombination.setId(IdWorker.getId());

        // 查询组合包涵产品id以和所需数量
        List<ProductCombination> productCombinationList = getCombinationListByProductId(stockCombination.getProductId());

        // 产品出库
        productDelivery(stockCombination, productCombinationList);

        // 组合入库
        combinedStorage(stockCombination);

        // 保存入库明细
        save(stockCombination);

    }

    @Override
    public int getQuantityByWarehouseId(GetQuantityByWarehouseIdDto dto) {

        // 查询组合包涵产品id以和所需数量
        List<ProductCombination> productCombinationList = getCombinationListByProductId(dto.getProductId());

        // 获取关联产品id
        List<Long> linkProductIdList = productCombinationList.stream()
                .map(ProductCombination::getLinkProductId).collect(Collectors.toList());

        // 获取指定仓库指定产品库存数量
        Map<Long, BigDecimal> kv = stockService.getKV(Stock::getGoodsId, Stock::getQuantity, q -> q
                .eq(Stock::getWarehouseId, dto.getSourceWarehouseId())
                .in(Stock::getGoodsId, linkProductIdList));

        Integer quantity = null;

        for (ProductCombination productCombination : productCombinationList) {

            // 产品库存数量
            BigDecimal stockQuantity = kv.get(productCombination.getLinkProductId());
            if (Objects.isNull(stockQuantity)) {
                return 0;
            }

            // 最多组合几份
            int max = stockQuantity.divide(productCombination.getLinkQuantity(), 0, RoundingMode.FLOOR).intValue();
            if (max == 0) {
                return 0;
            }
            if (quantity == null || max < quantity) {
                quantity = max;
            }

        }

        return ObjectUtil.defaultIfNull(quantity, 0);
    }

    /**
     * 查询组合包涵产品id以和数量
     */
    private List<ProductCombination> getCombinationListByProductId(Long productId) {
        List<ProductCombination> list = productCombinationService.list(q -> q
                .select(ProductCombination::getLinkProductId, ProductCombination::getLinkQuantity)
                .eq(ProductCombination::getProductId, productId));
        Assert.gtZero(list.size(), "没有找到产品组合");
        return list;
    }

    /**
     * 产品出库
     */
    private void productDelivery(StockCombination stockCombination, List<ProductCombination> productCombinationList) {
        // 赋值变更明细
        List<StockChangeDetailsDto> stockChangeDetailsDtoList = productCombinationList.stream().map(item -> {
            BigDecimal changeQuantity = item.getLinkQuantity().multiply(BigDecimal.valueOf(stockCombination.getCombinationQuantity()));

            StockChangeDetailsDto stockChangeDetailsDto = new StockChangeDetailsDto();
            stockChangeDetailsDto.setGoodsId(item.getLinkProductId());
            stockChangeDetailsDto.setChangeQuantity(changeQuantity);
            return stockChangeDetailsDto;

        }).collect(Collectors.toList());

        // 赋值库存变更参数
        StockChangeDto stockChangeDto = new StockChangeDto();
        stockChangeDto.setDefaultBusinessId(stockCombination.getId());
        stockChangeDto.setDefaultWarehouseId(stockCombination.getSourceWarehouseId());
        stockChangeDto.setTypeEnum(OutTypeEnum.COMBINATION);
        stockChangeDto.setChangeDetailsList(stockChangeDetailsDtoList);

        // 保存变更明细
        stockService.changeQuantity(stockChangeDto);
    }

    /**
     * 组合入库
     */
    private void combinedStorage(StockCombination stockCombination) {

        // 赋值变更明细
        StockChangeDetailsDto stockChangeDetailsDto = new StockChangeDetailsDto();
        stockChangeDetailsDto.setGoodsId(stockCombination.getProductId());
        stockChangeDetailsDto.setChangeQuantity(BigDecimal.valueOf(stockCombination.getCombinationQuantity()));

        // 赋值库存变更参数
        StockChangeDto stockChangeDto = new StockChangeDto();
        stockChangeDto.setDefaultBusinessId(stockCombination.getId());
        stockChangeDto.setDefaultWarehouseId(stockCombination.getCombinationWarehouseId());
        stockChangeDto.setTypeEnum(InTypeEnum.COMBINATION);
        stockChangeDto.setChangeDetailsList(Collections.singletonList(stockChangeDetailsDto));

        // 保存变更明细
        stockService.changeQuantity(stockChangeDto);

    }

}
