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

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

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

import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.AgeCalculatorUtil;
import com.core.common.utils.DateUtils;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.*;
import com.openhis.administration.service.*;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.constant.PromptMsgConstant;
import com.openhis.common.enums.*;
import com.openhis.common.enums.ybenums.YbInvChgType;
import com.openhis.common.enums.ybenums.YbMdtrtCertType;
import com.openhis.common.enums.ybenums.YbRxFlag;
import com.openhis.common.utils.EnumUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.financial.domain.Contract;
import com.openhis.financial.domain.PaymentReconciliation;
import com.openhis.financial.service.IContractService;
import com.openhis.financial.service.IPaymentReconciliationService;
import com.openhis.medication.domain.MedicationDefinition;
import com.openhis.medication.domain.MedicationDispense;
import com.openhis.medication.service.IMedicationDefinitionService;
import com.openhis.medication.service.IMedicationDispenseService;
import com.openhis.web.inventorymanage.appservice.impl.ReceiptApprovalAppServiceImpl;
import com.openhis.web.inventorymanage.dto.SupplyItemDetailDto;
import com.openhis.web.pharmacymanage.appservice.IWesternMedicineDispenseAppService;
import com.openhis.web.pharmacymanage.dto.*;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.web.pharmacymanage.mapper.WesternMedicineDispenseMapper;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.service.IInventoryItemService;
import com.openhis.yb.domain.ClinicSettle;
import com.openhis.yb.dto.Medical3505Param;
import com.openhis.yb.service.IClinicSettleService;
import com.openhis.yb.service.YbManager;

import reactor.util.annotation.Nullable;

/**
 * 西药发放 应用实现类
 *
 * @author wangyang
 * @date 2025/3/14
 */
@Service
public class WesternMedicineDispenseAppServiceImpl implements IWesternMedicineDispenseAppService {

    @Resource
    private IOrganizationService organizationService;

    @Resource
    private IMedicationDispenseService medicationDispenseService;

    @Resource
    private IInventoryItemService inventoryItemService;

    @Resource
    private WesternMedicineDispenseMapper westernMedicineDispenseMapper;

    @Resource
    private ReturnMedicineMapper returnMedicineMapper;

    @Resource
    private YbManager ybService;

    @Resource
    private IChargeItemService chargeItemService;

    @Resource
    private IPaymentReconciliationService paymentReconciliationService;

    @Resource
    private IContractService contractService;

    @Resource
    private IAccountService accountService;

    @Resource
    private IClinicSettleService clinicSettleService;

    @Resource
    private IEncounterDiagnosisService encounterDiagnosisService;

    @Resource
    private ITraceNoManageService traceNoManageService;

    @Resource
    private ReceiptApprovalAppServiceImpl receiptApprovalAppService;

    @Resource
    private IMedicationDefinitionService medicationDefinitionService;

    /**
     * 获取页面初始化信息
     *
     * @return 初始化信息
     */
    @Override
    public R<?> init() {

        DispenseInitDto initDto = new DispenseInitDto();

        // 获取科室下拉选列表
        List<Organization> organizationList =
            organizationService.getList(OrganizationType.DEPARTMENT.getValue(), OrganizationClass.CLINIC.getValue());
        List<DispenseInitDto.DepartmentOption> organizationOptions = organizationList.stream()
            .map(organization -> new DispenseInitDto.DepartmentOption(organization.getId(), organization.getName()))
            .collect(Collectors.toList());

        // 获取配药人下拉选列表
        List<Practitioner> preparerDoctorList =
            westernMedicineDispenseMapper.getPreparerDoctorList(PractitionerRoles.PHARMACIST.getCode());
        List<DispenseInitDto.PreparerDoctorOption> preparerDoctorOptions = preparerDoctorList.stream()
            .map(practitioner -> new DispenseInitDto.PreparerDoctorOption(practitioner.getId(), practitioner.getName()))
            .collect(Collectors.toList());

        // 未发药原因下拉选列表
        List<DispenseInitDto.NotPerformedReasonOption> notPerformedReasonOptions =
            Stream.of(NotPerformedReasonEnum.values())
                .map(notPerformedReason -> new DispenseInitDto.NotPerformedReasonOption(notPerformedReason.getValue(),
                    notPerformedReason.getInfo()))
                .collect(Collectors.toList());

        // 患者类型
        List<DispenseInitDto.EncounterClassOption> encounterClassOptions = Stream.of(EncounterClass.values())
            .map(encounterClass -> new DispenseInitDto.EncounterClassOption(encounterClass.getValue(),
                encounterClass.getInfo()))
            .toList();

        // 发药状态
        List<DispenseInitDto.DispenseStatusOption> dispenseStatusOptions = new ArrayList<>();
        dispenseStatusOptions.add(new DispenseInitDto.DispenseStatusOption(DispenseStatus.IN_PROGRESS.getValue(),
            DispenseStatus.IN_PROGRESS.getInfo()));
        dispenseStatusOptions.add(new DispenseInitDto.DispenseStatusOption(DispenseStatus.COMPLETED.getValue(),
            DispenseStatus.COMPLETED.getInfo()));

        initDto.setDepartmentOptions(organizationOptions).setNotPerformedReasonOptions(notPerformedReasonOptions)
            .setDispenseStatusOptions(dispenseStatusOptions).setPreparerDoctorOptions(preparerDoctorOptions)
            .setEncounterClassOptions(encounterClassOptions);
        return R.ok(initDto);
    }

    /**
     * 分页查询病人列表
     *
     * @param encounterInfoSearchParam 查询条件
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param request 请求数据
     * @return 病人列表
     */
    @Override
    public R<?> getEncounterInfoListPage(EncounterInfoSearchParam encounterInfoSearchParam, String searchKey,
        Integer pageNo, Integer pageSize, HttpServletRequest request) {
        // 发药状态初始化
        Integer statusEnum = encounterInfoSearchParam.getStatusEnum();
        encounterInfoSearchParam.setStatusEnum(null);
        // 构建查询条件
        QueryWrapper<EncounterInfoSearchParam> queryWrapper =
            HisQueryUtils.buildQueryWrapper(encounterInfoSearchParam, searchKey,
                new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientName, CommonConstants.FieldName.IdCard,
                    CommonConstants.FieldName.PatientPyStr, CommonConstants.FieldName.PatientWbStr)),
                request);
        // 查询就诊病人列表
        Page<EncounterInfoDto> encounterInfoPage =
            westernMedicineDispenseMapper.selectEncounterInfoListPage(new Page<>(pageNo, pageSize), queryWrapper,
                statusEnum, DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
                DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue());
        encounterInfoPage.getRecords().forEach(encounterInfo -> {
            // 性别
            encounterInfo.setGenderEnum_enumText(
                EnumUtils.getInfoByValue(AdministrativeGender.class, encounterInfo.getGenderEnum()));
            // 发药状态
            encounterInfo
                .setStatusEnum_enumText(EnumUtils.getInfoByValue(DispenseStatus.class, encounterInfo.getStatusEnum()));
            if (encounterInfo.getBirthDate() != null) {
                // 计算年龄
                encounterInfo.setAge(AgeCalculatorUtil.getAge(encounterInfo.getBirthDate()));
            }
        });
        return R.ok(encounterInfoPage);
    }

    /**
     * 处方单查询
     *
     * @param itemDispenseOrderDto 查询信息
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @return 处方单
     */
    @Override
    public R<?> getMedicineDispenseOrderList(ItemDispenseOrderDto itemDispenseOrderDto, Integer pageNo,
        Integer pageSize) {
        // 发药状态初始化
        Integer dispenseStatus = itemDispenseOrderDto.getStatusEnum();
        itemDispenseOrderDto.setStatusEnum(null);
        // 构建查询条件
        QueryWrapper<ItemDispenseOrderDto> queryWrapper =
            HisQueryUtils.buildQueryWrapper(itemDispenseOrderDto, null, null, null);
        // 处方单信息查询
        Page<ItemDispenseOrderDto> medicineDispenseOrderPage =
            westernMedicineDispenseMapper.selectMedicineDispenseOrderPage(new Page<>(pageNo, pageSize), queryWrapper,
                DispenseStatus.IN_PROGRESS.getValue(), DispenseStatus.COMPLETED.getValue(),
                DispenseStatus.PREPARATION.getValue(), DispenseStatus.PREPARED.getValue(), dispenseStatus);
        medicineDispenseOrderPage.getRecords().forEach(medicineDispenseOrder -> {
            // 发药状态
            medicineDispenseOrder.setStatusEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, medicineDispenseOrder.getStatusEnum()));
            // 设置所在表名
            medicineDispenseOrder.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
        });
        return R.ok(medicineDispenseOrderPage);
    }

    /**
     * 配药
     *
     * @param dispenseMedicineList 配药信息
     * @return 处理结果
     */
    @Override
    public R<?> medicinePrepare(List<DispenseItemDto> dispenseMedicineList) {
        // 配药人检查
        if (dispenseMedicineList.get(0).getPreparerId() == null
            || dispenseMedicineList.get(0).getPreparerId().equals(SecurityUtils.getLoginUser().getPractitionerId())) {
            return R.fail("请选择调配药师");
        }
        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());
        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList =
            returnMedicineMapper.selectInventoryInfoList(null, medDispenseIdList,
                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() + "库存已停供");
            }
        }
        if (!inventoryList.isEmpty()) {
            for (UnDispenseInventoryDto unDispenseInventoryDto : inventoryList) {
                if (PublicationStatus.ACTIVE.getValue().equals(unDispenseInventoryDto.getInventoryStatusEnum())) {
                    // 库存数量判定
                    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 {
                        // 当前库存数量(拆零单位)=当前库存数量(拆零单位)-拆零数量（拆零比×请求数量）
                        BigDecimal quantity = unDispenseInventoryDto.getInventoryQuantity().subtract(
                            unDispenseInventoryDto.getPartPercent().multiply(unDispenseInventoryDto.getQuantity()));
                        // 库存数量判定
                        if (quantity.compareTo(BigDecimal.ZERO) < 0) {
                            // 库存数量不足
                            return R.fail(unDispenseInventoryDto.getItemName() + "当前库存数量不足");
                        }
                    }
                }
            }
        }
        // 药品发药信息查询
        List<MedicationDispense> dispenseList = medicationDispenseService
            .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
        if (dispenseList != null) {
            if (dispenseList.stream().map(MedicationDispense::getStatusEnum)
                .anyMatch(x -> !x.equals(DispenseStatus.PREPARATION.getValue()))) {
                throw new ServiceException("配药失败，请检查发药单状态");
            } else {
                for (MedicationDispense medicationDispense : dispenseList) {
                    // 药品发放状态
                    medicationDispense.setStatusEnum(DispenseStatus.PREPARED.getValue());
                    // 状态变更时间
                    medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
                    // 配药人
                    medicationDispense.setPreparerId(dispenseMedicineList.get(0).getPreparerId());
                    // 配药时间
                    medicationDispense.setPrepareTime(DateUtils.getNowDate());
                    for (DispenseItemDto dispenseItemDto : dispenseMedicineList) {
                        if (medicationDispense.getId().equals(dispenseItemDto.getDispenseId()))
                            // 药品追溯码
                            medicationDispense.setTraceNo(dispenseItemDto.getTraceNo());
                    }
                }
                // 药品发放更新
                medicationDispenseService.updateBatchById(dispenseList);
            }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 处方单核对发药
     *
     * @param dispenseMedicineList 发药信息
     * @return 处理结果
     */
    @Override
    public R<?> medicineDispense(List<DispenseItemDto> dispenseMedicineList) {
        List<InventoryItem> inventoryItemList = new ArrayList<>();
        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());

        // 获取药品发放库存信息
        List<UnDispenseInventoryDto> inventoryList =
            returnMedicineMapper.selectInventoryInfoList(null, medDispenseIdList,
                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() + "库存已停供");
            }
        }
        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);
                }
            }
        }
        // 药品发药信息查询
        List<MedicationDispense> dispenseList = medicationDispenseService
            .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
        // 追溯码列表
        List<TraceNoManage> tracesNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (dispenseList != null) {
            if (dispenseList.stream().map(MedicationDispense::getStatusEnum)
                .anyMatch(x -> !x.equals(DispenseStatus.PREPARED.getValue()))) {
                throw new ServiceException("发药失败，请检查发药单状态");
            } else {
                for (MedicationDispense medicationDispense : dispenseList) {
                    // 药品发放状态
                    medicationDispense.setStatusEnum(DispenseStatus.COMPLETED.getValue());
                    // 状态变更时间
                    medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
                    // 发药数量
                    medicationDispense.setDispenseQuantity(medicationDispense.getQuantity());
                    // 发药时间
                    medicationDispense.setDispenseTime(DateUtils.getNowDate());
                    // 发药人
                    medicationDispense.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                    // 设置库存变更参数
                    supplyItemDetailList.add(new SupplyItemDetailDto().setItemId(medicationDispense.getMedicationId())
                        .setLotNumber(medicationDispense.getLotNumber())
                        .setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION));
                    // 使用逗号分割追溯码并转换为List
                    if (medicationDispense.getTraceNo() != null) {
                        String[] traceNoList = medicationDispense.getTraceNo().split(CommonConstants.Common.COMMA);
                        for (String item : traceNoList) {
                            traceNoManage = new TraceNoManage();
                            // 追溯码处理
                            traceNoManage.setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
                                // 项目id
                                .setItemId(medicationDispense.getMedicationId())
                                // 仓库类型
                                .setLocationTypeEnum(LocationForm.PHARMACY.getValue())
                                // 仓库
                                .setLocationId(medicationDispense.getLocationId())
                                // 产品批号
                                .setLotNumber(medicationDispense.getLotNumber())
                                // 追溯码
                                .setTraceNo(item)
                                // 追溯码状态
                                .setStatusEnum(TraceNoStatus.OUT.getValue())
                                // 追溯码单位
                                .setUnitCode(medicationDispense.getUnitCode())
                                // 操作类型
                                .setOperationType(SupplyType.DISPENSE_MEDICATION.getValue());
                            tracesNoManageList.add(traceNoManage);
                        }
                    }
                }
                // 药品发放更新
                medicationDispenseService.updateBatchById(dispenseList);
            }
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        // 库存更新
        inventoryItemService.updateBatchById(inventoryItemList);
        // 追溯码管理表数据追加
        traceNoManageService.saveBatch(tracesNoManageList);
        // 返回信息
        String returnMsg = null;
        List<String> uploadFailedNoList;
        // 调用医保商品销售接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            // 设置进销存参数
            List<MedicationDefinition> medicationDefinitions = medicationDefinitionService.listByIds(
                supplyItemDetailList.stream().map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            // 用itemId分组
            Map<Long, MedicationDefinition> medicationMap = medicationDefinitions.stream()
                .collect(Collectors.toMap(MedicationDefinition::getId, Function.identity()));
            // 设置库存变更参数
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dto.getItemTable())) {
                    MedicationDefinition med = medicationMap.get(dto.getItemId());
                    if (med != null) {
                        dto.setItemBusNo(med.getBusNo()).setPartPercent(med.getPartPercent()).setRxFlag(med.getRxFlag())
                            .setYbNo(med.getYbNo());
                    }
                }
            }
            uploadFailedNoList = this.ybMedicineIntegrated(medDispenseIdList, null);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3505商品销售上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3505商品销售上传成功";
            }
        }
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 作废
     *
     * @param dispenseMedicineList 作废信息
     * @return 处理结果
     */
    @Override
    public R<?> medicineCancel(List<DispenseItemDto> dispenseMedicineList) {
        // 获取发药单id列表
        List<Long> medDispenseIdList =
            dispenseMedicineList.stream().map(DispenseItemDto::getDispenseId).collect(Collectors.toList());
        // 药品发药信息查询
        List<MedicationDispense> dispenseList = medicationDispenseService
            .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
        if (dispenseList != null) {
            for (MedicationDispense medicationDispense : dispenseList) {
                // 药品发放状态
                medicationDispense.setStatusEnum(DispenseStatus.DECLINED.getValue());
                // 未发药原因
                medicationDispense.setNotPerformedReasonEnum(dispenseMedicineList.get(0).getNotPerformedReasonEnum());
                // 状态变更时间
                medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
            }
            // 药品发放更新
            medicationDispenseService.updateBatchById(dispenseList);
        } else {
            return R.fail(MessageUtils.createMessage(PromptMsgConstant.Common.M00007, null));
        }
        return R.ok(MessageUtils.createMessage(PromptMsgConstant.Common.M00004, null));
    }

    /**
     * 医保发药相关进销存接口
     *
     * @param medDispenseIdList 发药id列表
     * @param devDispenseIdList 发耗材id列表
     * @return 上传失败的编号集合
     */
    public List<String> ybMedicineIntegrated(@Nullable List<Long> medDispenseIdList,
        @Nullable List<Long> devDispenseIdList) {
        List<String> uploadFailedNoList = new ArrayList<>();
        R<?> result;
        if ((medDispenseIdList != null && !medDispenseIdList.isEmpty())
            || (devDispenseIdList != null && !devDispenseIdList.isEmpty())) {
            // 查询发药项目相关信息
            List<DispenseInventoryDto> dispenseInventoryList = returnMedicineMapper.selectReturnItemDetail(
                devDispenseIdList, medDispenseIdList, CommonConstants.TableName.MED_MEDICATION_DEFINITION,
                CommonConstants.TableName.ADM_DEVICE_DEFINITION);
            for (DispenseInventoryDto dispenseInventoryDto : dispenseInventoryList) {
                if (dispenseInventoryDto.getYbNo() == null) {
                    continue;
                }
                result = ybService.merchandise(getMedical3505Param(dispenseInventoryDto));
                if (result.getCode() != 200) {
                    uploadFailedNoList.add(dispenseInventoryDto.getDispenseNo());
                }
            }
        }
        return uploadFailedNoList;
    }

    private Medical3505Param getMedical3505Param(DispenseInventoryDto dispenseInventoryDto) {
        Medical3505Param medical3505Param = new Medical3505Param();
        ChargeItem chargeItem = null;
        if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            // 查询费用结算信息
            chargeItem = chargeItemService.getOne(new LambdaQueryWrapper<ChargeItem>()
                .eq(ChargeItem::getServiceTable, CommonConstants.TableName.MED_MEDICATION_REQUEST)
                .eq(ChargeItem::getServiceId, dispenseInventoryDto.getReqId())
                .eq(ChargeItem::getTenantId, SecurityUtils.getLoginUser().getTenantId()));
        } else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            chargeItem = chargeItemService.getOne(new LambdaQueryWrapper<ChargeItem>()
                .eq(ChargeItem::getServiceTable, CommonConstants.TableName.WOR_DEVICE_REQUEST)
                .eq(ChargeItem::getServiceId, dispenseInventoryDto.getReqId())
                .eq(ChargeItem::getTenantId, SecurityUtils.getLoginUser().getTenantId()));
        }

        if (chargeItem == null) {
            throw new ServiceException("未查找到收费项");
        }
        // 查询就诊诊断信息
        EncounterDiagnosis encounterDiagnosis = encounterDiagnosisService.getById(chargeItem.getEncounterDiagnosisId());
        if (encounterDiagnosis == null) {
            throw new ServiceException("未查找到就诊诊断信息");
        }
        // 查询付款信息
        List<PaymentReconciliation> paymentReconciliationList =
            paymentReconciliationService.list(new LambdaQueryWrapper<PaymentReconciliation>()
                .eq(PaymentReconciliation::getEncounterId, dispenseInventoryDto.getEncounterId())
                .eq(PaymentReconciliation::getTenantId, SecurityUtils.getLoginUser().getTenantId())
                .like(PaymentReconciliation::getChargeItemIds, chargeItem.getId())
                .eq(PaymentReconciliation::getStatusEnum, PaymentStatus.SUCCESS.getValue())
                .eq(PaymentReconciliation::getPatientId, dispenseInventoryDto.getPatientId())
                .eq(PaymentReconciliation::getPaymentEnum, PaymentType.PAY.getValue())
                .orderByDesc(PaymentReconciliation::getBillDate));
        if (paymentReconciliationList == null || paymentReconciliationList.isEmpty()) {
            throw new ServiceException("未查找到收费信息");
        }
        PaymentReconciliation paymentReconciliation = paymentReconciliationList.get(0);
        // 查询账户信息
        Account account = accountService
            .getOne(new LambdaQueryWrapper<Account>().eq(Account::getEncounterId, dispenseInventoryDto.getEncounterId())
                .eq(Account::getEncounterFlag, Whether.YES.getValue()));
        if (account == null) {
            throw new ServiceException("未查找到账户信息");
        }
        // 查询合同实体
        Contract contract =
            contractService.getOne(new LambdaQueryWrapper<Contract>().eq(Contract::getBusNo, account.getContractNo()));
        if (contract == null) {
            throw new ServiceException("未查找到合同信息");
        }
        YbMdtrtCertType mdtrtCertType;
        if (AccountType.PERSONAL_CASH_ACCOUNT.getCode().equals(account.getTypeCode())) {
            mdtrtCertType = YbMdtrtCertType.MDTRT_CERT_TYPE02;
        } else {
            mdtrtCertType = YbMdtrtCertType.getByValue(account.getTypeCode());// 2025/05/28 该值存01/02/03
        }
        if (mdtrtCertType == null) {
            throw new ServiceException("未查找到就诊凭证信息");
        }
        // 查询就诊id
        if (contract.getCategoryEnum().equals(Category.SELF.getValue())
            || contract.getCategoryEnum().equals(Category.PUBLIC.getValue())) {
            medical3505Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo()).setMdtrtSetlType("2");
        } else {
            // todo：虽然是医保挂号，但是用什么结算的暂时未知先不做修改
            ClinicSettle clinicSettle = clinicSettleService.getOne(new LambdaQueryWrapper<ClinicSettle>()
                .in(ClinicSettle::getSetlId, List.of(paymentReconciliation.getYbSettleIds()))
                .eq(ClinicSettle::getMedType, encounterDiagnosis.getMedTypeCode()).last(" LIMIT 1"));
            if (clinicSettle != null) {
                medical3505Param.setMdtrtSn(clinicSettle.getMdtrtId()).setMdtrtSetlType("1");
            } else {
                medical3505Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo()).setMdtrtSetlType("2");
            }
        }
        // // 查询发票信息
        // Invoice invoice = iInvoiceService.getById(paymentReconciliation.getInvoiceId());
        // if (invoice == null) {
        // throw new ServiceException("未查找到就诊发票信息");
        // }
        // 转换为JSON
        JSONArray medicalTraceNo = new JSONArray();
        // 获取追溯码信息
        if (dispenseInventoryDto.getTraceNo() != null) {
            List<String> traceNoList =
                Arrays.stream(dispenseInventoryDto.getTraceNo().split(CommonConstants.Common.COMMA)).map(String::trim)
                    .filter(s -> !s.isEmpty()).toList();
            for (String traceNo : traceNoList) {
                Map<String, String> traceNoMap = new HashMap<>();
                traceNoMap.put("drug_trac_codg", traceNo);
                medicalTraceNo.add(traceNoMap);
            }
        }
        medical3505Param.setMedListCodg(dispenseInventoryDto.getYbNo())
            .setFixmedinsBchno(dispenseInventoryDto.getLotNumber())
            .setFixmedinsHilistId(dispenseInventoryDto.getItemNo())
            .setPrscDrName(dispenseInventoryDto.getPractitionerName())
            .setPharName(dispenseInventoryDto.getDispenseName())
            .setPharPracCertNo(dispenseInventoryDto.getPharPracCertNo()).setPsnCertType(mdtrtCertType.getValue())
            .setManuLotnum(dispenseInventoryDto.getLotNumber()).setManuDate(dispenseInventoryDto.getProductionDate())
            .setRtalDocno(dispenseInventoryDto.getDispenseNo())
            .setSelRetnCnt(new BigDecimal(dispenseInventoryDto.getDispenseQuantity().toString()))
            .setSelRetnTime(dispenseInventoryDto.getDispenseTime()).setExpyEnd(dispenseInventoryDto.getExpirationDate())
            .setStooutNo(dispenseInventoryDto.getDispenseNo()).setDrugtracinfo(medicalTraceNo)
            .setCertno(dispenseInventoryDto.getIdCard()).setPsnName(dispenseInventoryDto.getPatientName());
        if (dispenseInventoryDto.getInventoryUnitCode().equals(dispenseInventoryDto.getDispenseUnitCode())) {
            medical3505Param.setTrdnFlag(Whether.YES.getCode());
        } else {
            medical3505Param.setTrdnFlag(Whether.NO.getCode());
        }
        // 查看所属医院
        String fixmedinsCode =
            SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
        if (dispenseInventoryDto.getPreparerName() == null && HospitalCodeEnum.CCU.getCode().equals(fixmedinsCode)) {
            medical3505Param.setSelRetnOpterName(CommonConstants.CCU.DisDeviceDoctorName);
        } else {
            medical3505Param.setSelRetnOpterName(dispenseInventoryDto.getPreparerName());
        }
        if (YbRxFlag.IMPORTANT_HERBAL_SLICES.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3505Param.setRxFlag(YbRxFlag.IMPORTANT_HERBAL_SLICES.getName());
        } else if (YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3505Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
        } else if (YbRxFlag.SELF_PREPARED_MEDICATION.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3505Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
        }
        if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            medical3505Param.setFixmedinsHilistName(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
        } else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            medical3505Param.setFixmedinsHilistName(CommonConstants.TableName.ADM_DEVICE_DEFINITION);
        }
        return medical3505Param;

    }
}
