package com.ktg.iscs.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ktg.common.core.text.Convert;
import com.ktg.common.utils.DateUtils;
import com.ktg.iscs.domain.IsMaterials;
import com.ktg.iscs.domain.IsMaterialsCabinet;
import com.ktg.iscs.domain.IsMaterialsLoanException;
import com.ktg.iscs.domain.dto.materials.BindingMaterialsDTO;
import com.ktg.iscs.domain.vo.cabinet.IsMaterialsCabinetVO;
import com.ktg.iscs.mapper.IsMaterialsCabinetMapper;
import com.ktg.iscs.service.IIsMaterialsCabinetService;
import com.ktg.iscs.service.IIsMaterialsLoanExceptionService;
import com.ktg.iscs.service.IIsMaterialsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 物资柜Service业务层处理
 *
 * @author cgj
 * @date 2024-11-08
 */
@Service
public class IsMaterialsCabinetServiceImpl extends ServiceImpl<IsMaterialsCabinetMapper, IsMaterialsCabinet> implements IIsMaterialsCabinetService
{
    @Autowired
    private IsMaterialsCabinetMapper isMaterialsCabinetMapper;
    @Autowired
    private IIsMaterialsService iIsMaterialsService;
    @Autowired
    private IIsMaterialsLoanExceptionService isMaterialsLoanExceptionService;

    /**
     * 查询物资柜
     *
     * @param cabinetId 物资柜主键
     * @return 物资柜
     */
    @Override
    public IsMaterialsCabinet selectIsMaterialsCabinetByCabinetId(Long cabinetId)
    {
        return isMaterialsCabinetMapper.selectIsMaterialsCabinetByCabinetId(cabinetId);
    }

    /**
     * 查询物资柜列表
     *
     * @param isMaterialsCabinet 物资柜
     * @return 物资柜
     */
    @Override
    public List<IsMaterialsCabinet> selectIsMaterialsCabinetList(IsMaterialsCabinet isMaterialsCabinet)
    {
        return isMaterialsCabinetMapper.selectIsMaterialsCabinetList(isMaterialsCabinet);
    }

    /**
     * 新增物资柜
     *
     * @param isMaterialsCabinet 物资柜
     * @return 结果
     */
    @Override
    public int insertIsMaterialsCabinet(IsMaterialsCabinet isMaterialsCabinet)
    {
        Assert.notBlank(isMaterialsCabinet.getCabinetCode(), "编码不能为空！");
        // 判断编码重复
        List<IsMaterialsCabinet> list = list(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, isMaterialsCabinet.getCabinetCode()));
        Assert.isTrue(list.isEmpty(), "该编码已被使用，请重新填写！");
        // 判断名称重复
        List<IsMaterialsCabinet> list1 = list(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetName, isMaterialsCabinet.getCabinetName()));
        Assert.isTrue(list1.isEmpty(), "该物资柜名称已被使用，请重新填写！");
        isMaterialsCabinet.setCreateTime(DateUtils.getNowDate());
        return isMaterialsCabinetMapper.insertIsMaterialsCabinet(isMaterialsCabinet);
    }

    /**
     * 修改物资柜
     *
     * @param isMaterialsCabinet 物资柜
     * @return 结果
     */
    @Override
    public int updateIsMaterialsCabinet(IsMaterialsCabinet isMaterialsCabinet)
    {
        Assert.notNull(isMaterialsCabinet.getCabinetId(), "主键不能为空！");
        // 判断编码重复
        List<IsMaterialsCabinet> list = list(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, isMaterialsCabinet.getCabinetCode())
                .ne(IsMaterialsCabinet::getCabinetId, isMaterialsCabinet.getCabinetId()));
        Assert.isTrue(list.isEmpty(), "该编码已被使用，请重新填写！");
        // 判断名称重复
        List<IsMaterialsCabinet> list1 = list(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetName, isMaterialsCabinet.getCabinetName())
                .ne(IsMaterialsCabinet::getCabinetId, isMaterialsCabinet.getCabinetId()));
        Assert.isTrue(list1.isEmpty(), "该物资柜名称已被使用，请重新填写！");
        isMaterialsCabinet.setUpdateTime(DateUtils.getNowDate());
        return isMaterialsCabinetMapper.updateIsMaterialsCabinet(isMaterialsCabinet);
    }

    /**
     * 批量删除物资柜
     *
     * @param cabinetIds 需要删除的物资柜主键
     * @return 结果
     */
    @Override
    public int deleteIsMaterialsCabinetByCabinetIds(String cabinetIds)
    {
        Assert.notBlank(cabinetIds, "请选择需要删除的数据!");
        Long[] longIds = Convert.toLongArray(cabinetIds);
        // 检查物资柜下面有没有物资，有物资就不可以删除
        List<IsMaterials> list = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                .in(IsMaterials::getMaterialsCabinetId, longIds));
        Assert.isFalse(!list.isEmpty(), "物资柜下存在所属物资，请先清理物资！");
        return isMaterialsCabinetMapper.deleteIsMaterialsCabinetByCabinetIds(longIds);
    }

    /**
     * 删除物资柜信息
     *
     * @param cabinetId 物资柜主键
     * @return 结果
     */
    @Override
    public int deleteIsMaterialsCabinetByCabinetId(Long cabinetId)
    {
        return isMaterialsCabinetMapper.deleteIsMaterialsCabinetByCabinetId(cabinetId);
    }

    @Override
    public Page<IsMaterialsCabinetVO> getIsMaterialsCabinetPage(Page<IsMaterialsCabinet> page, IsMaterialsCabinet isMaterialsCabinet) {
        Page<IsMaterialsCabinetVO> isMaterialsCabinetPage = isMaterialsCabinetMapper.getIsMaterialsCabinetPage(page, isMaterialsCabinet);
        // 1.如果有柜子，则获取所有物资进行判断
        if (!isMaterialsCabinetPage.getRecords().isEmpty()) {
            List<Long> cabinetIds = isMaterialsCabinetPage.getRecords().stream().map(IsMaterialsCabinetVO::getCabinetId).collect(Collectors.toList());
            // 2.开始获取所有柜子的借出或异常的物资
            List<IsMaterials> materials = iIsMaterialsService.list(Wrappers.<IsMaterials>lambdaQuery()
                    .in(IsMaterials::getMaterialsCabinetId, cabinetIds)
                    .and(o -> o.eq(IsMaterials::getLoanState, "0").or().ne(IsMaterials::getStatus, "0")));
            for (IsMaterialsCabinetVO record : isMaterialsCabinetPage.getRecords()) {
                record.setStatus("0");
                record.setExReason("0");
                // 2.1判断是否异常,取物资的异常放入其中
                List<IsMaterials> exMaterial = materials.stream().filter(o -> o.getMaterialsCabinetId().equals(record.getCabinetId())
                        // 把当前物资柜借出去的数据去掉，因为不属于我的异常，只能属于我借出去了，如果还到别的柜子，别的柜子应该报异常
                        && !"3".equals(o.getStatus()) && !"0".equals(o.getStatus()))
                        .sorted(Comparator.comparing(IsMaterials::getStatus).reversed())
                        .collect(Collectors.toList());
                // 把柜子中物资的异常体现出来
                if (!exMaterial.isEmpty()) {
                    record.setStatus("2");
                    record.setExReason(exMaterial.get(0).getStatus());
                    continue;
                }
                // 2.2检查有没有错还进来的物资
                List<IsMaterialsLoanException> exLoan = isMaterialsLoanExceptionService.list(Wrappers.<IsMaterialsLoanException>lambdaQuery()
                        .eq(IsMaterialsLoanException::getRestitutionToId, record.getCabinetId())
                        .eq(IsMaterialsLoanException::getStatus, "0")
                        .eq(IsMaterialsLoanException::getExceptionType, "0")
                );
                if (!exLoan.isEmpty()) {
                    record.setStatus("2");
                    record.setExReason("3");
                    continue;
                }
                // 2.3判断是否存在开门超时的情况
                List<IsMaterialsLoanException> openEx = isMaterialsLoanExceptionService.list(Wrappers.<IsMaterialsLoanException>lambdaQuery()
                        .eq(IsMaterialsLoanException::getLoanFromId, record.getCabinetId())
                        .eq(IsMaterialsLoanException::getStatus, "0")
                        .eq(IsMaterialsLoanException::getExceptionType, "1")
                );
                if (!openEx.isEmpty()) {
                    record.setStatus("2");
                    record.setExReason("5");
                    continue;
                }
                // 2.4判断是否借出
                List<IsMaterials> loanMaterial = materials.stream().filter(o -> o.getMaterialsCabinetId().equals(record.getCabinetId())
                        && "0".equals(o.getLoanState())).collect(Collectors.toList());
                if (!loanMaterial.isEmpty()) {
                    record.setStatus("1");
                    record.setExReason("4");
                }
            }
        }
        return isMaterialsCabinetPage;
    }

    @Override
    public Boolean updateMaterialsBindingRemove(BindingMaterialsDTO dto) {
        Assert.notNull(dto.getCabinetId(), "物资柜不能为空!");
        // 1.开始解绑
        if (!dto.getUnbindMaterialIds().isEmpty()) {
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsId, dto.getUnbindMaterialIds())
                    .set(IsMaterials::getMaterialsCabinetId, null)
                    .set(IsMaterials::getLoanState, "0"));
        }
        // 2.开始绑定
        if (!dto.getBindingMaterialIds().isEmpty()) {
            iIsMaterialsService.update(Wrappers.<IsMaterials>lambdaUpdate()
                    .in(IsMaterials::getMaterialsId, dto.getBindingMaterialIds())
                    .set(IsMaterials::getMaterialsCabinetId, dto.getCabinetId())
                    .set(IsMaterials::getLoanState, "1")
                    .set(IsMaterials::getStatus, "0"));
        }
        return true;
    }

    @Override
    public IsMaterialsCabinet getCabinetByCode(String cabinetCode) {
        Assert.notBlank(cabinetCode, "物资柜CODE不能为空！");
        IsMaterialsCabinet one = getOne(Wrappers.<IsMaterialsCabinet>lambdaQuery()
                .eq(IsMaterialsCabinet::getCabinetCode, cabinetCode));
        Assert.isFalse(one == null, "该物资柜不存在！");
        return one;
    }
}
