package com.openhis.web.outpatientmanage.appservice.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.core.common.core.domain.R;
import com.core.common.exception.ServiceException;
import com.core.common.utils.*;
import com.openhis.administration.domain.ChargeItem;
import com.openhis.administration.service.IChargeItemService;
import com.openhis.clinical.domain.Procedure;
import com.openhis.clinical.service.IProcedureService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.medication.domain.MedicationRequest;
import com.openhis.medication.service.IMedicationRequestService;
import com.openhis.web.common.dto.PerformInfoDto;
import com.openhis.web.common.dto.PerformRecordDto;
import com.openhis.web.outpatientmanage.appservice.IOutpatientTreatmentAppService;
import com.openhis.web.outpatientmanage.dto.BloodTransfusionPatchDto;
import com.openhis.web.outpatientmanage.dto.OutpatientStationInitDto;
import com.openhis.web.outpatientmanage.dto.OutpatientTreatmentEncounterDto;
import com.openhis.web.outpatientmanage.dto.OutpatientTreatmentInfoDto;
import com.openhis.web.outpatientmanage.mapper.OutpatientTreatmentAppMapper;
import com.openhis.web.pharmacymanage.appservice.impl.ReturnMedicineAppServiceImpl;
import com.openhis.web.pharmacymanage.appservice.impl.WesternMedicineDispenseAppServiceImpl;
import com.openhis.web.pharmacymanage.dto.UnDispenseInventoryDto;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.workflow.domain.DeviceDispense;
import com.openhis.workflow.domain.DeviceRequest;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.domain.ServiceRequest;
import com.openhis.workflow.service.IDeviceDispenseService;
import com.openhis.workflow.service.IDeviceRequestService;
import com.openhis.workflow.service.IInventoryItemService;
import com.openhis.workflow.service.IServiceRequestService;

import cn.hutool.core.lang.Pair;

/**
 * 门诊处置
 *
 * @author yuxj
 * @date 2025/4/10
 */
@Service
public class OutpatientTreatmentAppServiceImpl implements IOutpatientTreatmentAppService {

    @Resource
    private OutpatientTreatmentAppMapper outpatientTreatmentAppMapper;

    @Resource
    private IServiceRequestService serviceRequestService;

    @Resource
    private IMedicationRequestService medicationRequestService;

    @Resource
    private IDeviceDispenseService deviceDispenseService;

    @Resource
    private IDeviceRequestService deviceRequestService;

    @Resource
    private IInventoryItemService inventoryItemService;

    @Resource
    private IProcedureService procedureService;

    @Resource
    private ReturnMedicineMapper returnMedicineMapper;

    @Resource
    private WesternMedicineDispenseAppServiceImpl westernMedicineDispenseAppServiceImpl;

    @Resource
    private ReturnMedicineAppServiceImpl returnedMedicineAppServiceImpl;

    @Resource
    private IChargeItemService chargeItemService;

    @Resource
    private AssignSeqUtil assignSeqUtil;

    /**
     * 获取门诊处置初期数据列表
     *
     * @return 获取门诊处置初期数据列表
     */
    @Override
    public R<?> init() {
        OutpatientStationInitDto initDto = new OutpatientStationInitDto();
        // 执行状态
        List<OutpatientStationInitDto.ServiceStatus> serviceStatusOptions = new ArrayList<>();
        // serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.COMPLETED.getValue(),
        // RequestStatus.COMPLETED.getInfo()));
        // serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.IN_PROGRESS.getValue(),
        // RequestStatus.IN_PROGRESS.getInfo()));
        // serviceStatusOptions.add(new OutpatientStationInitDto.ServiceStatus(RequestStatus.CANCELLED.getValue(),
        // RequestStatus.CANCELLED.getInfo()));
        initDto.setServiceStatusOptions(serviceStatusOptions);
        return R.ok(initDto);
    }

    /**
     * 分页查询就诊病人列表
     *
     * @param outpatientTreatmentEncounterDto 查询条件
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param searchKey 模糊查询关键字
     * @param request 请求数据
     * @return 就诊病人列表
     */
    @Override
    public R<?> getEncounterInfoListPage(OutpatientTreatmentEncounterDto outpatientTreatmentEncounterDto,
        Integer pageNo, Integer pageSize, String searchKey, HttpServletRequest request) {

        // 设置模糊查询的字段名
        HashSet<String> searchFields = new HashSet<>();
        searchFields.add(CommonConstants.FieldName.PatientName);
        searchFields.add(CommonConstants.FieldName.PatientPyStr);
        searchFields.add(CommonConstants.FieldName.PatientWbStr);
        // 构建查询条件
        QueryWrapper<OutpatientTreatmentEncounterDto> queryWrapper =
            HisQueryUtils.buildQueryWrapper(outpatientTreatmentEncounterDto, searchKey, searchFields, request);

        // 查询就诊病人列表
        Page<OutpatientTreatmentEncounterDto> encounterInfoPageDto =
            outpatientTreatmentAppMapper.selectEncounterInfoListPage(new Page<>(pageNo, pageSize), queryWrapper,
                EncounterClass.AMB.getValue(), RequestStatus.COMPLETED.getValue(), RequestStatus.CANCELLED.getValue());
        encounterInfoPageDto.getRecords().forEach(prescriptionPatientInfoDto -> {
            // 性别
            prescriptionPatientInfoDto.setGenderEnum_enumText(
                EnumUtils.getInfoByValue(AdministrativeGender.class, prescriptionPatientInfoDto.getGenderEnum()));
            // 计算年龄
            prescriptionPatientInfoDto.setAge(prescriptionPatientInfoDto.getBirthDate() != null
                ? AgeCalculatorUtil.getAge(prescriptionPatientInfoDto.getBirthDate()) : "");
        });
        return R.ok(encounterInfoPageDto);
    }

    /**
     * 处置单查询
     *
     * @param outpatientTreatmentInfoDto 处置信息
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 处置单
     */
    @Override
    public R<?> getOutpatientTreatmentInfo(OutpatientTreatmentInfoDto outpatientTreatmentInfoDto, Integer pageNo,
        Integer pageSize) {
        // 构建查询条件
        QueryWrapper<OutpatientTreatmentInfoDto> queryWrapper =
            HisQueryUtils.buildQueryWrapper(outpatientTreatmentInfoDto, null, null, null);

        // 查询处置单
        IPage<OutpatientTreatmentInfoDto> treatmentInfo = outpatientTreatmentAppMapper.selectTreatmentInfoPage(
            new Page<>(pageNo, pageSize), queryWrapper, RequestStatus.COMPLETED.getValue(),
            DispenseStatus.DRAFT.getValue(), CommonConstants.TableName.WOR_SERVICE_REQUEST,
            CommonConstants.TableName.WOR_DEVICE_REQUEST, CommonConstants.TableName.MED_MEDICATION_REQUEST);
        List<OutpatientTreatmentInfoDto> treatmentList = treatmentInfo.getRecords();

        // 获取请求ids
        List<Long> reqIds =
            treatmentList.stream().map(OutpatientTreatmentInfoDto::getRequestId).collect(Collectors.toList());
        Map<Long, List<Procedure>> procedureRecordGroup = new HashMap<>();
        if (!reqIds.isEmpty()) {
            // 查询执行记录
            List<Procedure> procedureRecords = procedureService.getProcedureRecords(reqIds, null);

            if (procedureRecords != null && !procedureRecords.isEmpty()) {
                // 根据服务请求id分组
                procedureRecordGroup = procedureRecords.stream()
                    .collect(Collectors.groupingBy(Procedure::getRequestId, Collectors.toList()));
            }
        }

        // 为每个治疗项设置执行状态统计
        for (OutpatientTreatmentInfoDto treatment : treatmentList) {
            // 初始化计数器
            int performCount = 0;
            int cancelCount = 0;
            if (!procedureRecordGroup.isEmpty()) {
                // 安全获取执行记录
                List<Procedure> records = procedureRecordGroup.get(treatment.getRequestId());
                if (records != null && !records.isEmpty()) {
                    // 统计状态数量
                    for (Procedure record : records) {
                        if (EventStatus.COMPLETED.getValue().equals(record.getStatusEnum())) {
                            performCount++;
                        } else if (EventStatus.CANCEL.getValue().equals(record.getStatusEnum())) {
                            cancelCount++;
                        }
                    }
                }
            }
            // 设置统计结果
            treatment.setPerformCount(performCount);
            treatment.setCancelCount(cancelCount);

            // 发放状态
            if (treatment.getDispenseStatus() != null) {
                treatment.setDispenseStatus_enumText(
                    EnumUtils.getInfoByValue(DispenseStatus.class, treatment.getDispenseStatus()));
            }
            // 收费状态
            if (treatment.getChargeStatus() != null) {
                treatment.setChargeStatus_enumText(
                    EnumUtils.getInfoByValue(ChargeItemStatus.class, treatment.getChargeStatus()));
            }
        }
        return R.ok(treatmentInfo);
    }

    /**
     * 诊疗执行记录查询
     *
     * @param reqId 请求项目id
     * @return 执行记录列表
     */
    @Override
    public R<?> getPerformRecord(Long reqId) {
        // 查询执行记录
        List<PerformRecordDto> performRecordList = outpatientTreatmentAppMapper.selectPerformRecordList(List.of(reqId));
        performRecordList.forEach(performRecordDto -> {
            // 获取执行状态
            performRecordDto
                .setStatusEnum_enumText(EnumUtils.getInfoByValue(EventStatus.class, performRecordDto.getStatusEnum()));
        });
        return R.ok(performRecordList);
    }

    /**
     * 诊疗执行
     *
     * @param performInfoList 执行信息列表
     * @return 执行结果
     */
    @Override
    public R<?> perform(List<PerformInfoDto> performInfoList) {

        // 分别创建两个列表来存储不同类型的请求
        List<PerformInfoDto> serviceMedPerformList = new ArrayList<>();
        List<PerformInfoDto> devicePerformList = new ArrayList<>();
        for (PerformInfoDto item : performInfoList) {
            if (CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(item.getRequestTable())
                || CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(item.getRequestTable())) {
                serviceMedPerformList.add(item);
            } else if (CommonConstants.TableName.WOR_DEVICE_REQUEST.equals(item.getRequestTable())) {
                devicePerformList.add(item);
            }
        }
        // 分别处理诊疗/药品执行和耗材发放
        if (!serviceMedPerformList.isEmpty()) {
            List<ChargeItem> chargeItemList = chargeItemService.getChargeItemInfoByReqId(
                serviceMedPerformList.stream().map(PerformInfoDto::getRequestId).collect(Collectors.toList()));
            if (chargeItemList == null || chargeItemList.isEmpty()) {
                throw new ServiceException("未找到对应的收费项,请联系管理员");
            }
            // 按requestId分组收费项
            Map<Long, List<ChargeItem>> chargeItemMap =
                chargeItemList.stream().collect(Collectors.groupingBy(ChargeItem::getServiceId));
            // 过滤出已收费的执行项目
            serviceMedPerformList = serviceMedPerformList.stream().filter(performInfo -> {
                List<ChargeItem> chargeItems = chargeItemMap.get(performInfo.getRequestId());
                return chargeItems != null && chargeItems.stream()
                    .anyMatch(chargeItem -> ChargeItemStatus.BILLED.getValue().equals(chargeItem.getStatusEnum()));
            }).toList();
            // 处理诊疗执行
            for (PerformInfoDto performInfoDto : serviceMedPerformList) {
                Long groupId = performInfoDto.getGroupId();
                Long encounterId = null;
                Long requestId = null;
                Long patientId = null;
                Integer exeCount = 0;
                if (CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(performInfoDto.getRequestTable())) {
                    ServiceRequest serviceRequest = serviceRequestService.getById(performInfoDto.getRequestId());
                    if (serviceRequest != null) {
                        encounterId = serviceRequest.getEncounterId();
                        requestId = serviceRequest.getId();
                        patientId = serviceRequest.getPatientId();
                        exeCount = serviceRequest.getQuantity().intValue();
                    }
                } else if (CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(performInfoDto.getRequestTable())) {
                    MedicationRequest medicationRequest =
                        medicationRequestService.getById(performInfoDto.getRequestId());
                    if (medicationRequest != null) {
                        encounterId = medicationRequest.getEncounterId();
                        requestId = medicationRequest.getId();
                        patientId = medicationRequest.getPatientId();
                        exeCount = medicationRequest.getExecuteNum();
                    }
                }
                // 根据请求id查询执行记录
                List<Procedure> procedureRecordList = procedureService
                    .getProcedureRecords(List.of(performInfoDto.getRequestId()), performInfoDto.getRequestTable());
                if (procedureRecordList != null && !procedureRecordList.isEmpty()) {
                    // 初始化计数器
                    int performCount = 0;
                    int cancelCount = 0;
                    // 统计状态数量
                    for (Procedure record : procedureRecordList) {
                        if (EventStatus.COMPLETED.getValue().equals(record.getStatusEnum())) {
                            performCount++;
                        } else if (EventStatus.CANCEL.getValue().equals(record.getStatusEnum())) {
                            cancelCount++;
                        }
                    }
                    // 判断该项目是否已经执行了
                    if (performCount - cancelCount < exeCount) {
                        // 未执行则新增执行记录
                        Long procedureId = procedureService.addProcedureRecord(encounterId, patientId, requestId,
                            performInfoDto.getRequestTable(), EventStatus.COMPLETED,
                            ProcedureCategory.OUTPATIENT_ADVICE, null, DateUtils.getNowDate(), groupId, null);
                        if (procedureId == null) {
                            throw new ServiceException("执行失败，请联系管理员");
                        }
                    }
                } else {
                    // 新增执行记录
                    Long procedureId = procedureService.addProcedureRecord(encounterId, patientId, requestId,
                        performInfoDto.getRequestTable(), EventStatus.COMPLETED, ProcedureCategory.OUTPATIENT_ADVICE,
                        null, DateUtils.getNowDate(), groupId, null);
                    if (procedureId == null) {
                        throw new ServiceException("执行失败，请联系管理员");
                    }
                }
            }
        }

        // 返回信息
        String returnMsg = null;
        if (!devicePerformList.isEmpty()) {
            // 耗材请求id列表
            List<Long> devRequestIdList = devicePerformList.stream().map(PerformInfoDto::getRequestId).toList();
            // 获取耗材发放id列表
            List<Long> devDispenseIdList = performInfoList.stream().map(PerformInfoDto::getDispenseId).toList();
            // 发耗材信息查询
            List<DeviceDispense> dispenseList = deviceDispenseService
                .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getId, devDispenseIdList));
            // 获取耗材待发放id列表
            List<Long> devUnDispenseIdList = new ArrayList<>();
            if (dispenseList != null) {
                List<DeviceDispense> unDispenseList = dispenseList.stream()
                    .filter(x -> DispenseStatus.PREPARATION.getValue().equals(x.getStatusEnum())).toList();
                for (DeviceDispense deviceDispense : unDispenseList) {
                    // 耗材发放状态
                    deviceDispense.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                    // 发药数量
                    deviceDispense.setDispenseQuantity(deviceDispense.getQuantity());
                    // 发药时间
                    deviceDispense.setDispenseTime(DateUtils.getNowDate());
                    // 发药人
                    deviceDispense.setPerformerId(SecurityUtils.getLoginUser().getPractitionerId());
                    // 根据数量设置追溯码
                    deviceDispense.setTraceNo(String.join(CommonConstants.Common.COMMA, Collections
                        .nCopies(deviceDispense.getQuantity().intValue(), CommonConstants.Common.DEV_TRACE_NO)));
                    devUnDispenseIdList.add(deviceDispense.getId());
                }
                // 药品发放更新
                deviceDispenseService.updateBatchById(dispenseList);
            } else {
                return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
            }
            // 获取库存信息
            List<UnDispenseInventoryDto> inventoryList = returnMedicineMapper.selectInventoryInfoList(
                devUnDispenseIdList, null, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION);
            // 按每个耗材分组
            Map<Long, List<UnDispenseInventoryDto>> groupedByItemId =
                inventoryList.stream().collect(Collectors.groupingBy(UnDispenseInventoryDto::getItemId));
            // 遍历每个分组校验库存状态
            for (Map.Entry<Long, List<UnDispenseInventoryDto>> entry : groupedByItemId.entrySet()) {
                List<UnDispenseInventoryDto> groupItems = entry.getValue();
                if (groupItems.stream().map(UnDispenseInventoryDto::getInventoryStatusEnum)
                    .allMatch(x -> x.equals(PublicationStatus.RETIRED.getValue()))) {
                    // 库存停供校验
                    return R.fail(groupItems.get(0).getItemName() + "库存已停供");
                }
            }
            List<InventoryItem> inventoryItemList = new ArrayList<>();
            if (!inventoryList.isEmpty()) {
                for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
                    if (PublicationStatus.ACTIVE.getValue().equals(unDispenseInventoryDto.getInventoryStatusEnum())) {
                        InventoryItem inventoryItem = new InventoryItem();
                        // 库存数量判定
                        if (unDispenseInventoryDto.getDispenseUnit()
                            .equals(unDispenseInventoryDto.getInventoryUnitCode())) {
                            // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-请求数量
                            BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity()
                                .subtract(unDispenseInventoryDto.getQuantity());
                            // 库存数量判定
                            if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                                // 库存数量不足
                                return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                            } else {
                                inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                            }
                        } else {
                            // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-拆零数量（拆零比×请求数量）
                            BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity().subtract(
                                unDispenseInventoryDto.getPartPercent().multiply(unDispenseInventoryDto.getQuantity()));
                            // 库存数量判定
                            if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                                // 库存数量不足
                                return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                            } else {
                                inventoryItem.setId(unDispenseInventoryDto.getInventoryId()).setQuantity(quantity);
                            }
                        }
                        inventoryItemList.add(inventoryItem);
                    }
                }
            }
            // 库存更新
            inventoryItemService.updateBatchById(inventoryItemList);
            // 更新请求状态为已完成
            deviceRequestService.updateCompletedStatusBatch(devRequestIdList);

            // 调用医保商品销售接口
            String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH);
            // 医保开关
            if (Whether.YES.getCode().equals(ybSwitch)) {
                List<String> uploadFailedNoList =
                    westernMedicineDispenseAppServiceImpl.ybMedicineIntegrated(null, devDispenseIdList);
                if (uploadFailedNoList != null) {
                    returnMsg = "3505商品销售上传错误，错误项目编码" + uploadFailedNoList;
                } else {
                    returnMsg = "3505商品销售上传成功";
                }
            }
        }
        return R.ok("执行成功");
    }

    /**
     * 取消执行
     *
     * @param performInfoList 执行信息列表
     * @return 取消结果
     */
    @Override
    public R<?> cancelPerform(List<PerformInfoDto> performInfoList) {
        // 分别创建两个列表来存储不同类型的请求
        List<PerformInfoDto> serviceMedCancelList = new ArrayList<>();
        List<PerformInfoDto> deviceCancelList = new ArrayList<>();
        for (PerformInfoDto item : performInfoList) {
            if (CommonConstants.TableName.WOR_SERVICE_REQUEST.equals(item.getRequestTable())
                || CommonConstants.TableName.MED_MEDICATION_REQUEST.equals(item.getRequestTable())) {
                serviceMedCancelList.add(item);
            } else if (CommonConstants.TableName.WOR_DEVICE_REQUEST.equals(item.getRequestTable())) {
                deviceCancelList.add(item);
            }
        }
        // 分别处理诊疗执行和耗材发放
        if (!serviceMedCancelList.isEmpty()) {
            // 处理诊疗取消执行
            for (PerformInfoDto performInfoDto : serviceMedCancelList) {
                // 根据请求id查询执行记录
                List<Procedure> procedureRecordList = procedureService
                    .getProcedureRecords(List.of(performInfoDto.getRequestId()), performInfoDto.getRequestTable());
                if (procedureRecordList != null && !procedureRecordList.isEmpty()) {
                    Procedure procedure = procedureRecordList.get(0);
                    // 初始化计数器
                    int performCount = 0;
                    int cancelCount = 0;
                    // 统计状态数量
                    for (Procedure record : procedureRecordList) {
                        if (EventStatus.COMPLETED.getValue().equals(record.getStatusEnum())) {
                            performCount++;
                        } else if (EventStatus.CANCEL.getValue().equals(record.getStatusEnum())) {
                            cancelCount++;
                        }
                    }
                    // 判断该项目是否已经执行了
                    if (performCount - cancelCount > 0) {
                        // 已执行则新增取消执行记录
                        Long procedureId = procedureService.addProcedureRecord(procedure.getEncounterId(),
                            procedure.getPatientId(), procedure.getRequestId(), procedure.getRequestTable(),
                            EventStatus.CANCEL, ProcedureCategory.OUTPATIENT_ADVICE, performInfoDto.getLocationId(),
                            DateUtils.getNowDate(), performInfoDto.getGroupId(), null);
                        if (procedureId == null) {
                            throw new ServiceException("取消执行失败，请联系管理员");
                        }
                    }
                }
            }
        }

        // 返回信息
        String returnMsg = null;
        if (!deviceCancelList.isEmpty()) {
            // 待退的耗材请求id列表
            List<Long> devRefundRequestIdList = new ArrayList<>();
            // 耗材请求id和待退的耗材请求id
            List<Pair<Long, Long>> devRequestIdPairList = new ArrayList<>();
            // 耗材发放id列表
            List<Long> devDispenseIdList = deviceCancelList.stream().map(PerformInfoDto::getDispenseId).toList();
            for (PerformInfoDto performInfoDto : deviceCancelList) {
                // 查询耗材请求
                DeviceRequest deviceRequest = deviceRequestService.getById(performInfoDto.getRequestId());
                Long requestId = deviceRequest.getId();
                // 查询待退的耗材请求
                DeviceRequest deviceRefundRequest = deviceRequestService.getOne(new LambdaQueryWrapper<DeviceRequest>()
                    .eq(DeviceRequest::getRefundDeviceId, performInfoDto.getRequestId())
                    .eq(DeviceRequest::getDeleteFlag, DelFlag.NO.getCode()));
                if (deviceRefundRequest != null) {
                    if (deviceRefundRequest.getStatusEnum().equals(RequestStatus.CANCELLED.getValue())) {
                        // 获取待退的耗材请求id
                        devRefundRequestIdList.add(deviceRefundRequest.getId());
                        devRequestIdPairList.add(new Pair<>(requestId, deviceRefundRequest.getId()));
                    }
                } else {
                    // 生成退耗材请求
                    deviceRequest.setId(null); // 耗材请求id
                    deviceRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.DEVICE_RES_NO.getPrefix(), 4)); // 耗材请求编码
                    deviceRequest.setQuantity(deviceRequest.getQuantity().multiply(new BigDecimal("-1"))); // 请求数量
                    deviceRequest.setStatusEnum(RequestStatus.CANCELLED.getValue()); // 请求状态
                    deviceRequest.setRefundDeviceId(deviceRequest.getId()); // 退药id
                    deviceRequestService.save(deviceRequest);
                    // 获取生成的退耗材请求的id
                    devRefundRequestIdList.add(deviceRequest.getId());
                    devRequestIdPairList.add(new Pair<>(requestId, deviceRequest.getId()));
                }
            }
            // 退耗材处理
            // 退耗材单列表
            List<DeviceDispense> devRefundList = new ArrayList<>();
            if (!devDispenseIdList.isEmpty()) {
                // 耗材已发放信息查询
                List<DeviceDispense> deviceDispenseList = deviceDispenseService
                    .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getId, devDispenseIdList));
                // 根据发药单对应生成退药单
                for (DeviceDispense deviceDispense : deviceDispenseList) {
                    // 耗材发放编码
                    deviceDispense.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.DEVICE_DIS_NO.getPrefix(), 4));
                    // 退耗材的耗材请求id
                    for (Pair<Long, Long> pair : devRequestIdPairList) {
                        if (deviceDispense.getDeviceReqId().equals(pair.getKey())) {
                            deviceDispense.setDeviceReqId(pair.getValue());
                        }
                    }
                    // 退药时间
                    deviceDispense.setDispenseTime(DateUtils.getNowDate());
                    // 退药状态
                    deviceDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                    deviceDispense.setId(null);
                    devRefundList.add(deviceDispense);
                }
                deviceDispenseService.saveBatch(devRefundList);
                // 药品退药请求状态变更(待退药→已完成)
                deviceRequestService.updateCompletedStatusBatch(devRefundRequestIdList);
            }

            List<InventoryItem> inventoryItemList = new ArrayList<>();
            // 获取库存信息
            List<UnDispenseInventoryDto> inventoryList = returnMedicineMapper.selectInventoryInfoList(devDispenseIdList,
                null, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION);
            if (inventoryList != null && !inventoryList.isEmpty()) {
                // 设置库存数量
                for (UnDispenseInventoryDto inventory : inventoryList) {
                    // 库存表项目设定
                    InventoryItem inventoryItem = new InventoryItem();
                    // id
                    inventoryItem.setId(inventory.getInventoryId());
                    // 库存数量
                    if (inventory.getDispenseUnit().equals(inventory.getInventoryUnitCode())) {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)+待退数量
                        inventoryItem
                            .setQuantity(inventory.getInventoryQuantity().add(inventory.getDispenseQuantity()));
                    } else {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)+退药数量（拆零比×待退数量）
                        inventoryItem.setQuantity(inventory.getInventoryQuantity()
                            .add(inventory.getPartPercent().multiply(inventory.getDispenseQuantity())));
                    }
                    inventoryItemList.add(inventoryItem);
                }
            }
            // 库存更新
            inventoryItemService.updateBatchById(inventoryItemList);
            // 调用医保商品销售退货接口
            String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
            if (Whether.YES.getCode().equals(ybSwitch)) {
                if (!devRefundList.isEmpty()) {
                    List<String> uploadFailedNoList =
                        returnedMedicineAppServiceImpl.ybReturnIntegrated(new ArrayList<>(), devDispenseIdList);
                    if (uploadFailedNoList != null) {
                        returnMsg = "3506商品销售退货上传错误，错误项目编码" + uploadFailedNoList;
                    } else {
                        returnMsg = "3506商品销售退货上传成功";
                    }
                }
            }
        }
        return R.ok(returnMsg, "取消执行成功");
    }

    /**
     * 输血贴查询
     *
     * @param requestId 请求id
     * @return 输血贴
     */
    @Override
    public R<?> getBloodTransfusionPatch(Long requestId) {
        BloodTransfusionPatchDto bloodTransfusionPatch =
            outpatientTreatmentAppMapper.getBloodTransfusionPatch(requestId);
        // 性别枚举
        bloodTransfusionPatch.setGenderEnum_enumText(
            EnumUtils.getInfoByValue(AdministrativeGender.class, bloodTransfusionPatch.getGenderEnum()));
        // 计算年龄
        if (bloodTransfusionPatch.getBirthDate() != null) {
            bloodTransfusionPatch.setAge(AgeCalculatorUtil.getAge(bloodTransfusionPatch.getBirthDate()));
        }
        return R.ok(bloodTransfusionPatch);
    }
}
