package digital.laboratory.platform.imr.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import digital.laboratory.platform.common.core.exception.ValidateCodeException;
import digital.laboratory.platform.common.mybatis.security.service.DLPUser;
import digital.laboratory.platform.common.security.util.SecurityUtils;
import digital.laboratory.platform.imr.convert.DrugUsageRecordConvert;
import digital.laboratory.platform.imr.dto.DrugUsageRecordDTO;
import digital.laboratory.platform.imr.entity.*;
import digital.laboratory.platform.imr.enums.DrugMaterialStatus;
import digital.laboratory.platform.imr.enums.DrugUsageStatus;
import digital.laboratory.platform.imr.enums.OutboundType;
import digital.laboratory.platform.imr.mapper.DrugUsageRecordMapper;
import digital.laboratory.platform.imr.service.*;
import digital.laboratory.platform.imr.vo.DrugMaterialInfoVO;
import digital.laboratory.platform.sys.entity.Drug;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author ChenJiangBao
* @description 针对表【b_drug_usage_record(毒品检材的领用归还记录表)】的数据库操作Service实现
* @createDate 2024-11-11 11:40:42
*/
@Service
public class DrugUsageRecordServiceImpl extends ServiceImpl<DrugUsageRecordMapper, DrugUsageRecord>
    implements DrugUsageRecordService{

    @Resource
    private DrugMaterialInfoService drugMaterialInfoService;

    @Resource
    private SampleStorageService sampleStorageService;

    @Resource
    private CommonFeignService commonFeignService;

    @Resource
    private SampleOutboundRecordService sampleOutboundRecordService;

    @Resource
    private SampleInboundAndOutboundTableService sampleInboundAndOutboundTableService;

    /**
     * 毒品检材领用出库
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean outbound(DrugUsageRecordDTO dto) {
        List<String> drugIds = dto.getDrugIds();
        String usagePurpose = dto.getUsagePurpose();
        LocalDateTime usageDate = dto.getUsageDate();
        // 判断当前需要领用的检材是否都可以出库
        List<DrugMaterialInfo> drugMaterialInfos = drugMaterialInfoService.list(Wrappers.<DrugMaterialInfo>lambdaQuery().in(DrugMaterialInfo::getId, drugIds));
        for (DrugMaterialInfo drugMaterialInfo : drugMaterialInfos) {
            if (!drugMaterialInfo.getStatus().equals(DrugMaterialStatus.FINISH_INBOUND.getStatus())) {
                throw new ValidateCodeException(String.format("毒品检材编号为 %s 的检材不在可以出库的状态！", drugMaterialInfo.getDrugNo()));
            }
        }
        // 校验通过，保存领用出库记录
        DLPUser user = SecurityUtils.getUser();
        DrugUsageRecord drugUsageRecord = DrugUsageRecordConvert.dtoToEntity(dto);
        drugUsageRecord.setApplicant(user.getId());
        drugUsageRecord.setApplicantName(user.getName());
        drugUsageRecord.setUsageName(drugMaterialInfos.stream().map(DrugMaterialInfo::getDrugName).collect(Collectors.joining(",")));
        if (super.save(drugUsageRecord)) {
            // 移除柜子系统中关联的id, 获取格子id
            List<SampleStorage> sampleStorageList = sampleStorageService.list(Wrappers.<SampleStorage>lambdaQuery().in(SampleStorage::getSampleId, drugIds));
            // 更新样本仓库状态为已出库
            sampleStorageService.update(Wrappers.<SampleStorage>lambdaUpdate()
                    .in(SampleStorage::getSampleId, drugIds)
                    .set(SampleStorage::getStatus, 3)
                    .set(SampleStorage::getReturnTime, null)
                    .set(SampleStorage::getIsReturn, 1)
                    .set(SampleStorage::getRecipientId, user.getId())
                    .set(SampleStorage::getOutRepositoryDate, usageDate)
                    .set(SampleStorage::getPurpose, usagePurpose)
            );
            // 修改样本出入库登记表
            sampleInboundAndOutboundTableService.update(Wrappers.<SampleInboundAndOutboundTable>lambdaUpdate()
                    .in(SampleInboundAndOutboundTable::getSampleId, drugIds)
                    .isNull(SampleInboundAndOutboundTable::getAppraiserId)
                    .set(SampleInboundAndOutboundTable::getAppraiserId, user.getId())
                    .set(SampleInboundAndOutboundTable::getOutWarehouseDate, usageDate)
                    .set(SampleInboundAndOutboundTable::getRemarks, usagePurpose)
                    .set(SampleInboundAndOutboundTable::getReturnTime, null)
                    .set(SampleInboundAndOutboundTable::getOutboundSupervisor, null)
            );

            //添加样本出库记录
//            List<SampleOutboundRecord> sampleOutboundRecordList = sampleStorageList.parallelStream().map(sampleStorage -> {
//                SampleOutboundRecord sampleOutboundRecord = new SampleOutboundRecord();
//                sampleOutboundRecord.setSampleId(sampleStorage.getSampleId());
//                sampleOutboundRecord.setOutboundType(OutboundType.USE);//领用出库
//                sampleOutboundRecord.setRecipientId(user.getId());//领取人
//                sampleOutboundRecord.setName(sampleStorage.getName());//样本名称--方便搜索
//                sampleOutboundRecord.setReason(usagePurpose);//把出库原因设置为备注
//                sampleOutboundRecord.setOutboundDate(usageDate);//出库时间
//
//                // 从格子中出库
//                commonFeignService.remoteCabinetOutbound(sampleStorage.getStorageCellId(), sampleStorage.getSampleId());
//                return sampleOutboundRecord;
//            }).collect(Collectors.toList());
//            sampleOutboundRecordService.saveBatch(sampleOutboundRecordList);
            sampleStorageList.parallelStream().forEach(sampleStorage -> {
                // 从格子中出库
                commonFeignService.remoteCabinetOutbound(sampleStorage.getStorageCellId(), sampleStorage.getSampleId());
            });

            // 更新毒品检材状态为已经出库
            drugMaterialInfoService.update(Wrappers.<DrugMaterialInfo>lambdaUpdate()
                    .in(DrugMaterialInfo::getId, drugIds)
                    .set(DrugMaterialInfo::getStatus, DrugMaterialStatus.OUTBOUND.getStatus())
            );
            return true;
        }
        return false;
    }
}




