
package com.tmerclub.cloud.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.tmerclub.cloud.api.delivery.feign.StationFeignClient;
import com.tmerclub.cloud.api.delivery.vo.StationVO;
import com.tmerclub.cloud.common.order.vo.WarehouseVO;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.order.constant.StockModeEnum;
import com.tmerclub.cloud.common.product.constant.StockPointType;
import com.tmerclub.cloud.common.product.dto.StockPointSkuDTO;
import com.tmerclub.cloud.common.product.vo.StockPointSkuVO;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.product.mapper.StockPointSkuMapper;
import com.tmerclub.cloud.product.model.StockPointSku;
import com.tmerclub.cloud.product.service.StockPointSkuService;
import com.tmerclub.cloud.product.service.WarehouseService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

/**
 *
 *
 * @author tmerclub
 * @date 2023-11-09 18:00:43
 */
@Service
public class StockPointSkuServiceImpl implements StockPointSkuService {

    @Autowired
    private StockPointSkuMapper stockPointSkuMapper;
    @Autowired
    private WarehouseService warehouseService;
    @DubboReference
    private StationFeignClient stationFeignClient;

    @Override
    public PageVO<StockPointSku> page(PageDTO pageDTO) {
        return PageUtil.doPage(pageDTO, () -> stockPointSkuMapper.list());
    }

    @Override
    public StockPointSku getByStockPointSkuId(Long stockPointSkuId) {
        return stockPointSkuMapper.getByStockPointSkuId(stockPointSkuId);
    }

    @Override
    public void save(StockPointSku stockPointSku) {
        stockPointSku.setType(Objects.isNull(stockPointSku.getType()) ? 1 : stockPointSku.getType());
        stockPointSkuMapper.save(stockPointSku);
    }

    @Override
    public void update(StockPointSku stockPointSku) {
        stockPointSkuMapper.update(stockPointSku);
    }

    @Override
    public void deleteById(Long stockPointSkuId) {
        stockPointSkuMapper.deleteById(stockPointSkuId);
    }

    @Override
    public void deleteByIds(List<Long> stockPointSkuIds) {
        if (CollectionUtils.isEmpty(stockPointSkuIds)) {
            return;
        }
        stockPointSkuMapper.deleteByIds(stockPointSkuIds);
    }

    @Override
    public void deleteBySpuId(Long spuId) {
        stockPointSkuMapper.deleteBySpuId(spuId);
    }

    @Override
    public void batchDeleteByStockPointSkuIdList(List<Long> stockPointSkuIdList) {
        if (CollectionUtil.isEmpty(stockPointSkuIdList)) {
            return;
        }
        stockPointSkuMapper.batchDeleteByStockPointSkuIdList(stockPointSkuIdList);
    }

    @Override
    public void batchSave(List<StockPointSkuDTO> stockPointDTOList) {
        if (CollectionUtil.isEmpty(stockPointDTOList)) {
            return;
        }
//        if (CollectionUtil.isEmpty(stockPointDTOList)) {
//            throw new LuckException("库存不能为空");
//        }
        for (StockPointSkuDTO stockPointSkuDTO : stockPointDTOList) {
            stockPointSkuDTO.setType(Objects.isNull(stockPointSkuDTO.getType()) ? 1 : stockPointSkuDTO.getType());
        }
        stockPointSkuMapper.batchSave(stockPointDTOList);
    }

    @Override
    public List<StockPointSkuVO> listBySkuIds(List<Long> skuIds) {
        return stockPointSkuMapper.listBySkuIds(skuIds);
    }

    @Override
    public List<StockPointSkuVO> listPointIdsBySkuIds(List<Long> skuIds) {
        List<StockPointSkuVO> stockPoints = stockPointSkuMapper.listBySkuIds(skuIds);
        return stockPoints;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeStockPoint(List<StockPointSkuDTO> stockPointDTOList, boolean isUpdate) {
        // 获取商品原来的关联数据
        List<Long> skuIds = stockPointDTOList.stream().map(StockPointSkuDTO::getSkuId).collect(Collectors.toList());
        List<StockPointSkuVO> stockPointSkuDb = stockPointSkuMapper.listBySkuIds(skuIds);
        Map<String, List<StockPointSkuVO>> pointMap = stockPointSkuDb.stream().collect(Collectors.groupingBy(stockPoint -> stockPoint.getStockPointId() + "_" + stockPoint.getSkuId()));
        // 需要添加的新库存点数据
        List<StockPointSkuDTO> insertSkuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 需要删除的关联库存点
        List<Long> deleteSkuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 需要修改的数据
        List<StockPointSkuDTO> updateSkuList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 转换成插入的数据
        Map<Long, List<StockPointSkuDTO>> skuStockMap = stockPointDTOList.stream().collect(Collectors.groupingBy(StockPointSkuDTO::getSkuId));

        for (StockPointSkuDTO stockPointSku : stockPointDTOList) {
            String key = stockPointSku.getStockPointId() + "_" + stockPointSku.getSkuId();
            if (pointMap.containsKey(key)) {
                List<StockPointSkuVO> pointSkuVOS = pointMap.get(key);
                for (StockPointSkuVO pointSkuVO : pointSkuVOS) {
                    if (stockPointSku.getStock() == 0 && !Objects.equals(pointSkuVO.getType(), 0)) {
                        deleteSkuIds.add(pointSkuVO.getStockPointSkuId());
                    }
                }
                pointMap.remove(key);
            } else {
                insertSkuList.add(stockPointSku);
            }
        }
        if (isUpdate) {
            for (Map.Entry<String, List<StockPointSkuVO>> map : pointMap.entrySet()) {
                // 修改需要删除掉没有的数据
                map.getValue().forEach(stockPointSkuVO -> deleteSkuIds.add(stockPointSkuVO.getStockPointSkuId()));
            }
        }
        if (CollectionUtil.isNotEmpty(insertSkuList)) {
            stockPointSkuMapper.batchSave(insertSkuList);
        }
        if (CollectionUtil.isNotEmpty(deleteSkuIds)) {
            stockPointSkuMapper.batchDeleteByStockPointSkuIdList(deleteSkuIds);
        }
    }

    @Override
    public List<StockPointSkuVO> listByPointId(Long stockPointId) {

        return stockPointSkuMapper.listByPointId(stockPointId);
    }

    @Override
    public void removeBySkuIdAndPointId(Long skuId, Long stockPointId) {
        stockPointSkuMapper.removeBySkuIdAndPointId(skuId, stockPointId);
    }

    @Override
    public List<StockPointSkuVO> listPointBySkuIds(List<Long> skuIds) {
        if (CollUtil.isEmpty(skuIds)) {
            return Collections.emptyList();
        }
        return stockPointSkuMapper.listPointBySkuIds(skuIds);
    }

    @Override
    public void updateStockMode(Long stockPointId, Integer stockMode) {
        stockPointSkuMapper.updateStockMode(stockPointId, stockMode);
    }

    @Override
    public List<StockPointSkuDTO> filtePoint(List<StockPointSkuDTO> stockPointSkuVOList) {
        List<StockPointSkuDTO> resultList = new ArrayList<>(stockPointSkuVOList.size());
        Long defaultId = warehouseService.getDefaultWarehouseByShopId(AuthUserContext.get().getTenantId(), AuthUserContext.get().getSysType()).getWarehouseId();
        // 获取所有仓库
        List<WarehouseVO> warehouseList = warehouseService.listWarehouseByShopId(AuthUserContext.get().getTenantId(), AuthUserContext.get().getSysType());
        Map<Long, WarehouseVO> warehouseDbMap = warehouseList.stream().collect(Collectors.toMap(WarehouseVO::getWarehouseId, s -> s));
        // 获取所有还存在的门店
        List<Long> stationIds = stockPointSkuVOList.stream().filter(stockPointSkuDTO -> stockPointSkuDTO.getStockPointType() == StockPointType.STATION.getValue()).map(StockPointSkuDTO::getStockPointId).toList();
        List<StationVO> stationVOS = stationFeignClient.listStationByIds(stationIds);
        Map<Long, StationVO> stationDbMap = stationVOS.stream().collect(Collectors.toMap(StationVO::getStationId, s -> s));

        Map<Long, List<StockPointSkuDTO>> skuStockPointMap = stockPointSkuVOList.stream().collect(Collectors.groupingBy(StockPointSkuDTO::getSkuId));
        for (Map.Entry<Long, List<StockPointSkuDTO>> map : skuStockPointMap.entrySet()) {
            List<Long> stockPointIds = map.getValue().stream().map(StockPointSkuDTO::getStockPointId).collect(Collectors.toList());
            // 先判断有没有默认仓库，没有就添加
            if (!stockPointIds.contains(defaultId)) {
                StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO(defaultId, StockPointType.WAREHOUSE.getValue(), map.getValue().get(0).getSpuId() , map.getKey(), map.getValue().get(0).getStatus(), 0, null);
                stockPointSkuDTO.setStock(0);
                resultList.add(stockPointSkuDTO);
            }
            Map<Integer, List<StockPointSkuDTO>> listMap = map.getValue().stream().collect(Collectors.groupingBy(StockPointSkuDTO::getStockPointType));
            int warehouseStock = 0;
            int stationStock = 0;
            // 1、过滤仓库集合
            if (listMap.containsKey(StockPointType.WAREHOUSE.getValue())) {
                List<StockPointSkuDTO> warehousePointList = listMap.get(StockPointType.WAREHOUSE.getValue());
                for (StockPointSkuDTO warehousePoint : warehousePointList) {
                    if (warehouseDbMap.containsKey(warehousePoint.getStockPointId())) {
                        resultList.add(warehousePoint);
                    } else {
                        // 没有的就将仓库库存补充到默认仓库
                        warehouseStock += warehousePoint.getStock();
                    }
                }
            }
            // 2、过滤门店集合
            if (listMap.containsKey(StockPointType.STATION.getValue())) {
                List<StockPointSkuDTO> stationList = listMap.get(StockPointType.STATION.getValue());
                for (StockPointSkuDTO stationPoint : stationList) {
                    if (stationDbMap.containsKey(stationPoint.getStockPointId())) {
                        StationVO stationVO = stationDbMap.get(stationPoint.getStockPointId());
                        if (stationVO.getStockMode().equals(StockModeEnum.SINGLE_STOCK.value())) {
                            resultList.add(stationPoint);
                        } else {
                            stationStock += stationPoint.getStock();
                        }
                    } else {
                        // 没有的就将仓库库存补充到默认仓库
                        stationStock += stationPoint.getStock();
                    }
                }
            }
            // 3、累加门店和仓库库存
            for (StockPointSkuDTO stockPointSkuDTO : resultList) {
                if (stockPointSkuDTO.getType() == 0 && stockPointSkuDTO.getSkuId().equals(map.getKey())){
                    stockPointSkuDTO.setStock(stockPointSkuDTO.getStock() + stationStock + warehouseStock);
                }
            }
        }
        resultList = resultList.stream().filter(stockPointSkuDTO -> stockPointSkuDTO.getStock() != 0).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public List<StockPointSkuVO> listStockPointSku(StockPointSkuDTO stockPointSkuDTO) {
        return stockPointSkuMapper.listStockPointSku(stockPointSkuDTO);
    }

    @Override
    public List<Long> checkStockPointContainSku(List<Long> stockPointIds, List<Long> skuIds) {
        StockPointSkuDTO stockPointSkuDTO = new StockPointSkuDTO();
        stockPointSkuDTO.setStockPointIds(stockPointIds);
        List<StockPointSkuVO> stockPointSkus = stockPointSkuMapper.listStockPointSku(stockPointSkuDTO);
        if (CollectionUtils.isEmpty(stockPointSkus)) {
            return new ArrayList<>();
        }
        // 获取库存点含有的skuId
        List<Long> containSkuIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        Set<Long> dbSkuIds = stockPointSkus.stream().map(StockPointSkuVO::getSkuId).collect(Collectors.toSet());
        for (Long skuId : skuIds) {
            if (!dbSkuIds.contains(skuId)) {
                continue;
            }
            containSkuIds.add(skuId);
        }
        return containSkuIds;
    }
}
