package cn.iocoder.yudao.module.system.service.rental;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.itemsrecord.RentalItemsCountReqVO;
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.itemsrecord.RentalItemsRecordPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.rental.vo.itemsrecord.RentalItemsRecordSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.rental.RentalItemsRecordDO;
import cn.iocoder.yudao.module.system.dal.mysql.rental.RentalItemsRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.RENTAL_ITEMS_NUMBER_EXCESS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.RENTAL_ITEMS_RECORD_NOT_EXISTS;

/**
 * 租赁物品记录 Service 实现类
 *
 * @author 符溶馨
 */
@Service
@Validated
@Slf4j
public class RentalItemsRecordServiceImpl implements RentalItemsRecordService{

    @Resource
    private RentalItemsRecordMapper rentalItemsRecordMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createRentalItemsRecord(RentalItemsRecordSaveReqVO createReqVO) {

        // 获取订单剩余租借数量 使用悲观锁
        List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.getOrderNo(), true);
        Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);

        // 如果数量为0 则跳过
        if (createReqVO.getNumber() == 0) {
            return 0L;
        }

        // 判断租借类型为归还时，检验归还数量是否大于剩余数量
        if (createReqVO.getType() == 2 && countMap.get(createReqVO.getRentalItemsType()).getNumber() < createReqVO.getNumber()) {
            throw exception(RENTAL_ITEMS_NUMBER_EXCESS);
        }

        RentalItemsRecordDO createDO = BeanUtils.toBean(createReqVO, RentalItemsRecordDO.class);
        rentalItemsRecordMapper.insert(createDO);

        return createDO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createRentalItemsRecordBath(List<RentalItemsRecordSaveReqVO> createReqVO) {

        // 获取订单剩余租借数量 使用悲观锁
        List<RentalItemsCountReqVO> reqVOS = getRentalItemsCount(createReqVO.get(0).getOrderNo(), true);
        Map<Integer, RentalItemsCountReqVO> countMap = convertMap(reqVOS, RentalItemsCountReqVO::getRentalItemsType);

        // 移除 数量为0的数据
        createReqVO.removeIf(vo -> vo.getNumber() == 0);
        for (RentalItemsRecordSaveReqVO vo : createReqVO) {

            // 判断租借类型为归还时，检验归还数量是否大于剩余数量
            if (vo.getType() == 2) {

                if (countMap.get(vo.getRentalItemsType()) != null &&
                        countMap.get(vo.getRentalItemsType()).getNumber() < vo.getNumber()) {
                    throw exception(RENTAL_ITEMS_NUMBER_EXCESS);
                }
            }
        }

        List<RentalItemsRecordDO> createReq = BeanUtils.toBean(createReqVO, RentalItemsRecordDO.class);
        rentalItemsRecordMapper.insertBatch(createReq);
    }

    @Override
    public void updateRentalItemsRecord(RentalItemsRecordSaveReqVO updateReqVO) {

         // 校验存在
        validateRentalItemsRecordExists(updateReqVO.getId());

        RentalItemsRecordDO updateObj = BeanUtils.toBean(updateReqVO, RentalItemsRecordDO.class);
        rentalItemsRecordMapper.updateById(updateObj);
    }

    @Override
    public RentalItemsRecordDO getRentalItemsRecord(Long id) {
        return rentalItemsRecordMapper.selectById(id);
    }

    @Override
    public PageResult<RentalItemsRecordDO> getRentalItemsRecordPage(RentalItemsRecordPageReqVO pageReqVO) {
        return rentalItemsRecordMapper.selectPage(pageReqVO);
    }

    @Override
    public List<RentalItemsCountReqVO> getRentalItemsCount(String orderNo, Boolean isUpdate) {

        return rentalItemsRecordMapper.selectRentalItemsCount(orderNo, isUpdate);
    }

    private void validateRentalItemsRecordExists(Long id) {
        if (rentalItemsRecordMapper.selectById(id) == null) {
            throw exception(RENTAL_ITEMS_RECORD_NOT_EXISTS);
        }
    }
}
