package jnpf.personnels.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.model.personnels.dto.goods.FtbPersonnelsGoodsFormDTO;
import jnpf.model.personnels.dto.goods.FtbPersonnelsGoodsFormQueryDTO;
import jnpf.model.personnels.dto.goods.FtbPersonnelsGoodsFormUpdateDTO;
import jnpf.model.personnels.po.FtbPersonnelsGoods;
import jnpf.model.personnels.po.FtbPersonnelsGoodsReceive;
import jnpf.model.personnels.vo.goods.FtbPersonnelsGoodsPageVO;
import jnpf.model.personnels.vo.goods.PersonnelsGoodsDistributedLock;
import jnpf.personnels.mapper.FtbPersonnelsGoodsMapper;
import jnpf.personnels.mapper.FtbPersonnelsGoodsReceiveMapper;
import jnpf.personnels.service.FtbPersonnelsGoodsService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 *
 *
 *@Author: peng.hao
 *@create: 2025/9/11
 *
 */
@Service
public class FtbPersonnelsGoodsServiceImpl implements FtbPersonnelsGoodsService {

    @Resource
    private FtbPersonnelsGoodsMapper ftbPersonnelsGoodsMapper;
    @Resource
    private FtbPersonnelsGoodsReceiveMapper ftbPersonnelsGoodsReceiveMapper;
    @Resource
    private Redisson redisson;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(FtbPersonnelsGoodsFormDTO form) {
        // 校验物品名称是否重复
        LambdaQueryWrapper<FtbPersonnelsGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FtbPersonnelsGoods::getGoodsName, form.getGoodsName());
        queryWrapper.eq(FtbPersonnelsGoods::getEnableMark, 0);
        if (ftbPersonnelsGoodsMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("物品名称已存在");
        }
        // 校验物品编号是否重复
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FtbPersonnelsGoods::getGoodsCode, form.getGoodsCode());
        queryWrapper.eq(FtbPersonnelsGoods::getEnableMark, 0);
        if (ftbPersonnelsGoodsMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("物品编号已存在");
        }
        FtbPersonnelsGoods ftbPersonnelsGoods = form.convert(form);
        ftbPersonnelsGoodsMapper.insert(ftbPersonnelsGoods);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(FtbPersonnelsGoodsFormUpdateDTO form) {
        // 校验物品名称是否重复
        LambdaQueryWrapper<FtbPersonnelsGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(SuperBaseEntity.SuperIBaseEntity::getId, form.getId());
        queryWrapper.eq(FtbPersonnelsGoods::getGoodsName, form.getGoodsName());
        queryWrapper.eq(FtbPersonnelsGoods::getEnableMark, 0);
        if (ftbPersonnelsGoodsMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("物品名称已存在");
        }
        String lockGoods = String.format(PersonnelsGoodsDistributedLock.LOCK_KEY_GOODS, form.getId());
        RLock rLock = redisson.getFairLock(lockGoods);
        try {
            // 尝试获取锁，最多等10秒，持有锁10秒后自动释放
            if (!rLock.tryLock(10, 10, java.util.concurrent.TimeUnit.SECONDS)) {
                throw new RuntimeException("当前操作该物品任务过多，请稍后再试");
            }
            // 查询当前物品信息
            queryWrapper.clear();
            queryWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, form.getId());
            FtbPersonnelsGoods ftbPersonnelsGoods = ftbPersonnelsGoodsMapper.selectOne(queryWrapper);
            // 检查物品是否存在
            if (ftbPersonnelsGoods == null) {
                throw new RuntimeException("物品信息不存在");
            }
            // 计算已使用的物品数量
            long usedQuantity = ftbPersonnelsGoods.getQuantity() - ftbPersonnelsGoods.getReturnedQuantity();
            // 物品数量不能小于已领用的数量总额
            if (form.getQuantity() < usedQuantity) {
                throw new RuntimeException("物品数量不能小于已领用的数量总额");
            }
            // 计算新的剩余数量
            long newReturnedQuantity = ftbPersonnelsGoods.getReturnedQuantity()
                    + (form.getQuantity() - ftbPersonnelsGoods.getQuantity());
            // 更新物品信息
            LambdaUpdateWrapper<FtbPersonnelsGoods> updateWrapper = form.convert(form);
            updateWrapper.set(FtbPersonnelsGoods::getReturnedQuantity, newReturnedQuantity);
            ftbPersonnelsGoodsMapper.update(new FtbPersonnelsGoods(), updateWrapper);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException("系统繁忙，请稍后重试", e);
        } finally {
            // 检查当前线程是否持有锁，避免解锁异常
            if (rLock.isHeldByCurrentThread() && rLock.isLocked()) {
                rLock.unlock();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String id) {
        LambdaUpdateWrapper<FtbPersonnelsGoods> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, id);
        updateWrapper.set(FtbPersonnelsGoods::getEnableMark, 1);
        ftbPersonnelsGoodsMapper.update(new FtbPersonnelsGoods(), updateWrapper);
    }

    @Override
    public Page<FtbPersonnelsGoodsPageVO> list(Page<FtbPersonnelsGoodsPageVO> page, FtbPersonnelsGoodsFormQueryDTO formQueryDTO) {
        page = ftbPersonnelsGoodsMapper.listPages(page, formQueryDTO);
        return page;
    }

    @Override
    public FtbPersonnelsGoodsPageVO details(String id) {
        LambdaQueryWrapper<FtbPersonnelsGoods> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SuperBaseEntity.SuperIBaseEntity::getId, id);
        FtbPersonnelsGoods ftbPersonnelsGoods = ftbPersonnelsGoodsMapper.selectOne(queryWrapper);
        return FtbPersonnelsGoodsPageVO.convert(ftbPersonnelsGoods);
    }

    @Override
    public Boolean deleteConfirm(String id) {
        LambdaQueryWrapper<FtbPersonnelsGoodsReceive> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FtbPersonnelsGoodsReceive::getGoodsId, id);
        queryWrapper.in(FtbPersonnelsGoodsReceive::getReturnStatus, 0, 1);
        queryWrapper.eq(FtbPersonnelsGoodsReceive::getEnableMark, 0);
        return ftbPersonnelsGoodsReceiveMapper.selectCount(queryWrapper) > 0;
    }
}
