package cn.iocoder.yudao.module.member.service.storegoods;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.member.controller.admin.storegoods.vo.StoreGoodsPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoods.vo.StoreGoodsSaveReqVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoods.vo.StoreSaleGoodsPageVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoodsinventory.vo.AddReqVO;
import cn.iocoder.yudao.module.member.controller.admin.storegoodsinventory.vo.GoodsInfoReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.storegoods.StoreGoodsDO;
import cn.iocoder.yudao.module.member.dal.dataobject.storesalegoods.StoreSaleGoodsDO;
import cn.iocoder.yudao.module.member.dal.mysql.storegoods.StoreGoodsMapper;
import cn.iocoder.yudao.module.member.dal.mysql.storesalegoods.StoreSaleGoodsMapper;
import cn.iocoder.yudao.module.member.enums.InventoryTypeEnum;
import cn.iocoder.yudao.module.member.enums.OutTypeEnum;
import cn.iocoder.yudao.module.member.service.storegoodsinventory.StoreGoodsInventoryService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.STORE_GOODS_IS_SALE;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.STORE_GOODS_NOT_EXISTS;

/**
 * 商品 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class StoreGoodsServiceImpl implements StoreGoodsService {

    @Resource
    private StoreGoodsMapper storeGoodsMapper;
    @Resource
    private StoreSaleGoodsMapper storeSaleGoodsMapper;
    @Resource
    private StoreGoodsInventoryService storeGoodsInventoryService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer createStoreGoods(StoreGoodsSaveReqVO createReqVO) {
        // 插入
        StoreGoodsDO storeGoods = BeanUtils.toBean(createReqVO, StoreGoodsDO.class);
        storeGoodsMapper.insert(storeGoods);
        Integer goodsId = storeGoods.getGoodsId();
        //给店添加库存
        List<GoodsInfoReqVO>  list = new ArrayList<>();
        AddReqVO addReqVO = new AddReqVO();
        GoodsInfoReqVO vo = new GoodsInfoReqVO();
        vo.setGoodsId(goodsId);
        vo.setNumber(0);
        vo.setWeight(0d);
        vo.setCarteenId(createReqVO.getCarteenId());
        list.add(vo);
        //库存
        addReqVO.setList(list);
        addReqVO.setType(InventoryTypeEnum.IN.getCode());
        addReqVO.setOutType(OutTypeEnum.SYSTEM_ADD.getCode());
        storeGoodsInventoryService.createStoreGoodsInventoryBySale(addReqVO);
        // 返回
        return goodsId;
    }

    @Override
    public void updateStoreGoods(StoreGoodsSaveReqVO updateReqVO) {
        // 校验存在
        validateStoreGoodsExists(updateReqVO.getGoodsId());
        // 更新
        StoreGoodsDO updateObj = BeanUtils.toBean(updateReqVO, StoreGoodsDO.class);
        storeGoodsMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteStoreGoods(Integer id) {
        // 校验存在
        validateStoreGoodsExists(id);
        // 校验是否售卖商品
        List<StoreSaleGoodsDO> storeSaleGoodsDOS = storeSaleGoodsMapper.selectList(Wrappers.<StoreSaleGoodsDO>lambdaQuery().eq(StoreSaleGoodsDO::getGoodsId, id));
        if(CollectionUtil.isNotEmpty(storeSaleGoodsDOS)){
            throw exception(STORE_GOODS_IS_SALE);
        }
        StoreGoodsDO storeGoodsDO = storeGoodsMapper.selectById(id);
        storeGoodsInventoryService.deleteByGoodsId(storeGoodsDO.getGoodsId(), storeGoodsDO.getCarteenId());
        // 删除
        storeGoodsMapper.deleteById(id);
    }

    private void validateStoreGoodsExists(Integer id) {
        if (storeGoodsMapper.selectById(id) == null) {
            throw exception(STORE_GOODS_NOT_EXISTS);
        }
    }

    @Override
    public StoreGoodsDO getStoreGoods(Integer id) {
        return storeGoodsMapper.selectById(id);
    }

    @Override
    public PageResult<StoreGoodsDO> getStoreGoodsPage(StoreGoodsPageReqVO pageReqVO) {
        return storeGoodsMapper.selectPage(pageReqVO);
    }

    @Override
    public List<StoreGoodsDO> getAll(List<Integer> goodsIds) {
        if (CollectionUtil.isEmpty(goodsIds)) {
            return storeGoodsMapper.selectList();
        }else {
            return storeGoodsMapper.selectList(new LambdaQueryWrapper<StoreGoodsDO>().in(StoreGoodsDO::getGoodsId, goodsIds));
        }

    }

    @Override
    public List<StoreGoodsDO> getByCarteenId(Long carteenId) {
        return storeGoodsMapper.selectList(new LambdaQueryWrapper<StoreGoodsDO>().eq(StoreGoodsDO::getCarteenId, carteenId));
    }

    @Override
    public PageResult<StoreSaleGoodsPageVO> getSaleGoodsPage(StoreSaleGoodsPageVO pageReqVO) {

        Page<StoreSaleGoodsPageVO> page = Page.of(pageReqVO.getPageNo(), pageReqVO.getPageSize());

        IPage<StoreSaleGoodsPageVO> saleGoodsPage = storeSaleGoodsMapper.getSaleGoodsPage(page, pageReqVO);

        return new PageResult<>(saleGoodsPage.getRecords(), saleGoodsPage.getTotal());
    }

    @Override
    public Map<Integer, StoreGoodsDO> getPrice(List<Integer> goodsIds) {
        List<StoreGoodsDO> goodsDOS = storeGoodsMapper.selectList(new LambdaQueryWrapper<StoreGoodsDO>().in(StoreGoodsDO::getGoodsId, goodsIds));
        Map<Integer, StoreGoodsDO> map = goodsDOS.stream().collect(Collectors.toMap(StoreGoodsDO::getGoodsId, vo->vo));
        return map;
    }

}