package com.hys.app.service.erp.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hys.app.converter.erp.ProductConverter;
import com.hys.app.framework.context.user.AdminUserContext;
import com.hys.app.framework.database.WebPage;
import com.hys.app.framework.database.mybatisplus.base.BaseServiceImpl;
import com.hys.app.framework.exception.ServiceException;
import com.hys.app.framework.util.BeanUtils;
import com.hys.app.mapper.erp.ProductStockMapper;
import com.hys.app.mapper.goods.GoodsMapper;
import com.hys.app.mapper.goods.ProductMapper;
import com.hys.app.model.erp.dos.*;
import com.hys.app.model.erp.dto.*;
import com.hys.app.model.erp.vo.GoodsVO;
import com.hys.app.model.erp.vo.ProductStockVO;
import com.hys.app.model.erp.vo.ProductVO;
import com.hys.app.model.erp.vo.TransitVO;
import com.hys.app.model.goods.dos.GoodsGalleryDO;
import com.hys.app.service.erp.ProductGroupItemManager;
import com.hys.app.service.erp.ProductGroupManager;
import com.hys.app.service.erp.ProductManager;
import com.hys.app.service.erp.ProductStockManager;
import com.hys.app.service.goods.CategoryManager;
import com.hys.app.service.goods.GoodsGalleryManager;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.hys.app.framework.util.CollectionUtils.convertList;
import static com.hys.app.framework.util.CollectionUtils.convertMap;

/**
 * 产品业务层实现
 *
 * @author 张崧
 * 2023-11-30 16:06:44
 */
@Service
@AllArgsConstructor
public class ProductManagerImpl extends BaseServiceImpl<ProductMapper, ProductDO> implements ProductManager {

    private ProductConverter converter;
    private GoodsGalleryManager goodsGalleryManager;
    private ProductStockManager productStockManager;
    private ProductGroupManager productGroupManager;
    private ProductGroupItemManager productGroupItemManager;
    private GoodsMapper goodsMapper;
    private ProductStockMapper productStockMapper;

    @Override
    public WebPage<ProductVO> list(ProductQueryParams queryParams) {
        WebPage<ProductDO> webPage = baseMapper.selectPage(queryParams);
        WebPage<ProductVO> convert = converter.convert(webPage);
        for (ProductVO datum : convert.getData()) {
            datum.setGoodsVo(BeanUtil.copyProperties(goodsMapper.selectById(datum.getGoodsId()), GoodsVO.class));
        }
        return convert;
    }

    @Override
    public ProductVO getDetail(String id) {
        return converter.convert(getById(id));
    }

    @Override
    public void add(Long goodsId) {
    }

    @Override
    public void edit(GoodsDO goodsDO, List<ProductDTO> productDTOList) {
        // 查询之前的数据，构建规格与SKU的映射关系
        Map<String, Long> oldProductMap = convertMap(listByGoodsId(goodsDO.getId()), productDO -> buildSpecKey(productDO.getSpecList()), ProductDO::getId);

        // 拆分三个集合，新插入的、需要更新的、需要删除的（oldProductMap）
        List<ProductDTO> insertDTOList = new ArrayList<>();
        List<ProductDTO> updateDTOList = new ArrayList<>();

        for (ProductDTO productDTO : productDTOList) {

            // 从旧sku中查找，未找到则新增，否则进行更新
        }

        // 执行最终的批量操作
        if (CollUtil.isNotEmpty(insertDTOList)) {
//            this.add(goodsDO, insertDTOList);
        }
        if (CollUtil.isNotEmpty(updateDTOList)) {
            List<ProductDO> updateList = converter.convertList(updateDTOList, goodsDO);
            super.updateBatchById(updateList);
        }
        if (CollUtil.isNotEmpty(oldProductMap)) {
            super.removeBatchByIds(oldProductMap.values());
        }
    }

    @Override
    public List<ProductDO> listByGoodsId(Long goodsId) {
        return lambdaQuery().eq(ProductDO::getGoodsId, goodsId).list();
    }

    @Override
    public void deleteByGoodsId(List<Long> goodsIds) {
        lambdaUpdate().in(ProductDO::getGoodsId, goodsIds).remove();
    }

    private String buildSpecKey(List<ProductSpec> specList) {
        if (CollUtil.isEmpty(specList)) {
            return StrUtil.EMPTY;
        }
        List<ProductSpec> specValueList = new ArrayList<>(specList);
        specValueList.sort(Comparator.comparing(ProductSpec::getSpecValueId));
        return specValueList.stream().map(specValueVO -> String.valueOf(specValueVO.getSpecValueId())).collect(Collectors.joining());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void productGroup(ProductGroupDO productGroupDO) {
        ProductGroupDO one = productGroupManager.getOne(new LambdaQueryWrapper<ProductGroupDO>().eq(ProductGroupDO::getName, productGroupDO.getName()));
        if (ObjectUtil.isNotNull(one)) {
            throw new ServiceException("分组名称不能重复");
        }
        List<String> collect = productGroupDO.getItemDoList().stream().map(ProductGroupItemDO::getHireOrSail).collect(Collectors.toList());
        Set<String> set = new HashSet<>(collect);
        if (set.size()>1){
            throw new ServiceException("只能选择同一种商品类型");
        }else {
            if (!collect.get(0).equals(productGroupDO.getHireOrSail())){
                throw new ServiceException("所选商品和分组类型不符合");
            }
        }
        productGroupManager.save(productGroupDO);
        productGroupDO.getItemDoList().forEach(item ->item.setGroupId(productGroupDO.getId()));
        productGroupItemManager.saveBatch(productGroupDO.getItemDoList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeProductGroup(Long id) {
        productGroupManager.removeById(id);
        productGroupItemManager.remove(new LambdaQueryWrapper<ProductGroupItemDO>().eq(ProductGroupItemDO::getGroupId, id));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateProductGroup(Long id, ProductGroupDO productGroupDO) {
        ProductGroupDO byId = productGroupManager.getById(id);
        if (ObjectUtil.isNull(byId)) {
            throw new ServiceException("修改失败，未查询到数据");
        }
        BeanUtil.copyProperties(productGroupDO, byId);
        productGroupManager.updateById(byId);
        productGroupItemManager.remove(new LambdaQueryWrapper<ProductGroupItemDO>().eq(ProductGroupItemDO::getGroupId, id));
        productGroupDO.getItemDoList().forEach(item ->item.setGroupId(id));
        productGroupItemManager.saveBatch(productGroupDO.getItemDoList());
    }

    @Override
    public Page<ProductGroupDO> getGroupPage(ProductGroupQueryParams queryParams) {
        if (StrUtil.isNotBlank(queryParams.getOrderChooseType())){
            if ("TO_C".equals(queryParams.getOrderChooseType())){
                queryParams.setOrderChooseType("hire");
            }
            if ("TO_B".equals(queryParams.getOrderChooseType())){
                queryParams.setOrderChooseType("sail");
            }
        }
        Page<ProductGroupDO> page = productGroupManager.page(new Page<>(queryParams.getPageNo(), queryParams.getPageSize()),
                new LambdaQueryWrapper<ProductGroupDO>()
                        .eq(StrUtil.isNotBlank(queryParams.getOrderChooseType()),ProductGroupDO::getHireOrSail,queryParams.getOrderChooseType())
                        .eq(ObjectUtil.isNotNull(AdminUserContext.getCompanyId()),ProductGroupDO::getCompanyId,AdminUserContext.getCompanyId()));
        return page;
    }

    @Override
    public ProductGroupDO getGroupById(Long id) {
        ProductGroupDO byId = productGroupManager.getById(id);
        List<ProductGroupItemDO> list = productGroupItemManager.list(new LambdaQueryWrapper<ProductGroupItemDO>().eq(ProductGroupItemDO::getGroupId, id));
        for (ProductGroupItemDO aDo : list) {
            aDo.setProductVO(getById(aDo.getProductId()));
            aDo.setGoodsVO((goodsMapper.selectById(aDo.getGoodsId())));
        }
        byId.setItemDoList(list);
        return byId;
    }

    @Override
    public List<ProductStockVO> getProductByGroup(Long groupId,List<Long> warehouseId) {
        List<ProductGroupItemDO> list = productGroupItemManager.list(new LambdaQueryWrapper<ProductGroupItemDO>().eq(ProductGroupItemDO::getGroupId, groupId));
        List<Long> collect = list.stream().map(ProductGroupItemDO::getProductId).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect)) {
            throw new ServiceException("该分组没添加任何商品");
        }
        List<ProductStockDO> listed = productStockManager.list(new LambdaQueryWrapper<ProductStockDO>()
                .in(ProductStockDO::getWarehouseId, warehouseId).in(ProductStockDO::getProductId, collect));
        List<ProductStockVO> bean = BeanUtils.toBean(listed, ProductStockVO.class);
        for (ProductStockVO vo : bean) {
            GoodsVO goodsVO = BeanUtil.copyProperties(goodsMapper.selectById(vo.getGoodsId()), GoodsVO.class);
            vo.setGoodsVO(goodsVO);
            vo.setProductVO(BeanUtil.copyProperties(getById(vo.getProductId()), ProductVO.class));
        }
        return bean;
    }

    @Override
    public void updateWarnStock(Long stockId, Integer warnNum) {
        if (warnNum<0){
            throw new ServiceException("预警库存不能小于0");
        }
        ProductStockDO byId = productStockManager.getById(stockId);
        if (ObjectUtil.isNull(byId)){
            throw new ServiceException("未找到库存信息");
        }
        byId.setWarningStock(warnNum);
        productStockManager.updateById(byId);
    }

    @Override
    public List<ProductStockVO> getWarnStock(Long warehouseId) {
        LambdaQueryWrapper<ProductStockDO> queryWrapper = new LambdaQueryWrapper<ProductStockDO>().eq(ProductStockDO::getWarehouseId, warehouseId).last("and usable_stock <warning_stock limit 10 ");
        List<ProductStockDO> list = productStockManager.list(queryWrapper);
        List<ProductStockVO> bean = BeanUtils.toBean(list, ProductStockVO.class);
        bean.forEach(item ->{
            item.setProductVO(BeanUtil.copyProperties(getById(item.getProductId()),ProductVO.class));
            item.setGoodsVO(BeanUtil.copyProperties(goodsMapper.selectById(item.getGoodsId()),GoodsVO.class));
        });
        return bean;
    }

    @Override
    public List<TransitVO> transitDetail(Long stockId) {
        return productStockMapper.transitDetail(stockId);
    }

    @Override
    public void updateSort(List<SortItem>  sortItem) {
        if (sortItem.size() > 3 || sortItem.size() <2){
            throw new ServiceException("参数错误");
        }
        Long beforeSort=0L;
        Long afterSort=0L;
        Optional<SortItem> before = sortItem.stream().filter(item -> "before".equals(item.getPosition())).findFirst();
        Optional<SortItem> after = sortItem.stream().filter(item -> "after".equals(item.getPosition())).findFirst();
        Optional<SortItem> own = sortItem.stream().filter(item -> "own".equals(item.getPosition())).findFirst();
        if (before.isPresent()){
            beforeSort=before.get().getSort();
        }else {
            beforeSort=after.get().getSort()-500000;
        }
        if (after.isPresent()){
            afterSort=after.get().getSort();
        }else {
            afterSort=before.get().getSort()+500000;
        }
       Long randomNum= afterSort - beforeSort;
        Random random = new Random(randomNum);
        // 生成[min, max]范围内的随机数
        ProductDO aDo = getById(own.get().getProductId());
        aDo.setSort(beforeSort+random.nextInt());
        updateById(aDo);
    }
}


