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 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.*;
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.medication.service.IMedicationRequestService;
import com.openhis.web.inventorymanage.appservice.impl.ReceiptApprovalAppServiceImpl;
import com.openhis.web.inventorymanage.dto.SupplyItemDetailDto;
import com.openhis.web.pharmacymanage.appservice.IReturnMedicineAppService;
import com.openhis.web.pharmacymanage.dto.*;
import com.openhis.web.pharmacymanage.mapper.ReturnMedicineMapper;
import com.openhis.workflow.domain.DeviceDispense;
import com.openhis.workflow.domain.InventoryItem;
import com.openhis.workflow.service.IDeviceDispenseService;
import com.openhis.workflow.service.IDeviceRequestService;
import com.openhis.workflow.service.IInventoryItemService;
import com.openhis.yb.domain.ClinicSettle;
import com.openhis.yb.dto.Medical3506Param;
import com.openhis.yb.dto.MedicalInventory3511Param;
import com.openhis.yb.service.IClinicSettleService;
import com.openhis.yb.service.YbHttpUtils;
import com.openhis.yb.service.YbManager;

/**
 * 退药管理 应用实现类
 *
 * @author yangmo
 * @date 2025/4/4
 */
@Service
public class ReturnMedicineAppServiceImpl implements IReturnMedicineAppService {

    @Resource
    private ITraceNoManageService traceNoManageService;

    @Resource
    private IOrganizationService iOrganizationService;

    @Resource
    private IInventoryItemService iInventoryItemService;

    @Resource
    private ReturnMedicineMapper returnMedicineMapper;

    @Resource
    private IMedicationRequestService medicationRequestService;

    @Resource
    private IMedicationDispenseService medicationDispenseService;

    @Resource
    private IDeviceDispenseService deviceDispenseService;

    @Resource
    private IDeviceRequestService deviceRequestService;

    @Resource
    private AssignSeqUtil assignSeqUtil;

    @Resource
    private YbManager ybService;

    @Resource
    private IChargeItemService iChargeItemService;

    @Resource
    private IPaymentReconciliationService iPaymentReconciliationService;

    @Resource
    private IContractService iContractService;

    @Resource
    private IClinicSettleService clinicSettleService;

    @Resource
    private IEncounterDiagnosisService encounterDiagnosisService;

    @Resource
    private IAccountService accountService;

    @Resource
    private IDeviceDefinitionService deviceDefinitionService;

    @Resource
    private IMedicationDefinitionService medicationDefinitionService;

    @Resource
    private ReceiptApprovalAppServiceImpl receiptApprovalAppService;

    @Resource
    private YbHttpUtils ybHttpUtils;

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

        ReturnMedicineInitDto initDto = new ReturnMedicineInitDto();

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

        // 发药状态
        List<ReturnMedicineInitDto.RefundStatusOption> refundStatusOptions = new ArrayList<>();
        refundStatusOptions.add(new ReturnMedicineInitDto.RefundStatusOption(RequestStatus.CANCELLED.getValue(),
            RequestStatus.CANCELLED.getInfo()));
        refundStatusOptions.add(new ReturnMedicineInitDto.RefundStatusOption(RequestStatus.COMPLETED.getValue(),
            RequestStatus.COMPLETED.getInfo()));
        initDto.setDepartmentOptions(organizationOptions).setRefundStatusOptions(refundStatusOptions);
        return R.ok(initDto);
    }

    /**
     * 查询退药患者分页列表
     *
     * @param encounterInfoDto 查询条件
     * @param searchKey 模糊查询关键字
     * @param pageNo 当前页码
     * @param pageSize 查询条数
     * @param request 请求数据
     * @return 退药患者分页列表
     */
    @Override
    public R<?> getReturnMedicinePatientPage(EncounterInfoDto encounterInfoDto, String searchKey, Integer pageNo,
        Integer pageSize, HttpServletRequest request) {
        // 构建查询条件
        QueryWrapper<EncounterInfoDto> queryWrapper = HisQueryUtils.buildQueryWrapper(encounterInfoDto, searchKey,
            new HashSet<>(Arrays.asList(CommonConstants.FieldName.PatientName, CommonConstants.FieldName.IdCard,
                CommonConstants.FieldName.PatientPyStr, CommonConstants.FieldName.PatientWbStr)),
            request);
        // 查询退药患者分页列表
        Page<EncounterInfoDto> encounterInfoPage = returnMedicineMapper
            .selectEncounterInfoListPage(new Page<>(pageNo, pageSize), queryWrapper, EncounterClass.AMB.getValue());
        encounterInfoPage.getRecords().forEach(encounterInfo -> {
            // 性别
            encounterInfo.setGenderEnum_enumText(
                EnumUtils.getInfoByValue(AdministrativeGender.class, encounterInfo.getGenderEnum()));
            // 年龄
            encounterInfo.setAge(AgeCalculatorUtil.getAge(encounterInfo.getBirthDate()));
            // 退药状态
            encounterInfo
                .setRefundEnum_enumText(EnumUtils.getInfoByValue(RequestStatus.class, encounterInfo.getRefundEnum()));
        });
        return R.ok(encounterInfoPage);
    }

    /**
     * 查询退药信息
     *
     * @param encounterId 就诊ID
     * @param refundStatus 退药id
     * @return 退药信息
     */
    @Override
    public R<?> getReturnMedicineInfo(Long encounterId, Integer refundStatus) {
        // 获取退药信息
        List<ReturnMedicineInfoDto> returnMedicineInfoList = returnMedicineMapper.selectReturnMedicineInfo(encounterId,
            CommonConstants.TableName.WOR_DEVICE_REQUEST, CommonConstants.TableName.MED_MEDICATION_REQUEST,
            ItemType.MEDICINE.getValue(), ItemType.DEVICE.getValue(), refundStatus, RequestStatus.CANCELLED.getValue(),
            RequestStatus.COMPLETED.getValue());
        returnMedicineInfoList.forEach(returnMedicineInfoDto -> {
            // 退药状态
            returnMedicineInfoDto.setRefundEnum_enumText(
                EnumUtils.getInfoByValue(DispenseStatus.class, returnMedicineInfoDto.getRefundEnum()));
            // 退药请求状态
            returnMedicineInfoDto.setReqStatus_enumText(
                EnumUtils.getInfoByValue(RequestStatus.class, returnMedicineInfoDto.getReqStatus()));
        });
        return R.ok(returnMedicineInfoList);
    }

    /**
     * 退药处理
     *
     * @param medicineReturnList 退药清单
     * @return 处理结果
     */
    @Override
    public R<?> medicineReturn(List<ReturnMedicineDto> medicineReturnList) {
        if (medicineReturnList == null || medicineReturnList.isEmpty()) {
            return R.ok();
        }
        // 分别处理退药与退耗材的请求
        List<ReturnMedicineDto> returnMedicineList = new ArrayList<>();
        List<ReturnMedicineDto> returnDeviceList = new ArrayList<>();
        // 追溯码列表
        List<TraceNoManage> traceNoManageList = new ArrayList<>();
        TraceNoManage traceNoManage;

        medicineReturnList.forEach(item -> {
            switch (item.getTableName()) {
                case CommonConstants.TableName.MED_MEDICATION_REQUEST -> returnMedicineList
                    .add(new ReturnMedicineDto().setDispenseId(item.getDispenseId()).setRequestId(item.getRequestId()));
                case CommonConstants.TableName.WOR_DEVICE_REQUEST -> returnDeviceList
                    .add(new ReturnMedicineDto().setDispenseId(item.getDispenseId()).setRequestId(item.getRequestId()));
            }
        });
        // 获取药品发放id列表
        List<Long> medDispenseIdList =
            returnMedicineList.stream().map(ReturnMedicineDto::getDispenseId).collect(Collectors.toList());
        // 获取药品退药请求id列表
        List<Long> medRequestIdList =
            returnMedicineList.stream().map(ReturnMedicineDto::getRequestId).collect(Collectors.toList());

        if (!medRequestIdList.isEmpty()) {
            // 药品已退药信息查询
            List<MedicationDispense> refundList = medicationDispenseService.list(
                new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getMedReqId, medRequestIdList));
            if (refundList != null) {
                if (refundList.stream().map(MedicationDispense::getStatusEnum)
                    .anyMatch(x -> x.equals(DispenseStatus.REFUNDED.getValue()))) {
                    throw new ServiceException("药品已退药，请勿重复退药");
                }
            }
        }
        // 退药单列表
        List<MedicationDispense> medicationRefundList = new ArrayList<>();
        List<SupplyItemDetailDto> supplyItemDetailList = new ArrayList<>();
        if (!medDispenseIdList.isEmpty()) {
            // 药品已发放信息查询
            List<MedicationDispense> medicationDispenseList = medicationDispenseService
                .list(new LambdaQueryWrapper<MedicationDispense>().in(MedicationDispense::getId, medDispenseIdList));
            // 根据发药单对应生成退药单
            for (MedicationDispense medicationDispense : medicationDispenseList) {
                // 退药的药品请求id
                for (ReturnMedicineDto returnMedicineDto : returnMedicineList) {
                    if (returnMedicineDto.getDispenseId().equals(medicationDispense.getId())) {
                        medicationDispense.setMedReqId(returnMedicineDto.getRequestId());
                    }
                }
                // 药品发放编码
                medicationDispense.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_DIS_NO.getPrefix(), 4));
                // 退药状态
                medicationDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                // 状态变更时间
                medicationDispense.setStatusChangedTime(DateUtils.getNowDate());
                // 退药时间
                medicationDispense.setDispenseTime(DateUtils.getNowDate());
                // 退药人
                medicationDispense.setPractitionerId(SecurityUtils.getLoginUser().getPractitionerId());
                medicationDispense.setId(null);
                medicationRefundList.add(medicationDispense);
                // 设置库存变更参数
                supplyItemDetailList.add(new SupplyItemDetailDto()
                    .setItemTable(CommonConstants.TableName.MED_MEDICATION_DEFINITION)
                    .setItemId(medicationDispense.getMedicationId()).setLotNumber(medicationDispense.getLotNumber()));
                if (medicationDispense.getTraceNo() != null) {
                    // 使用逗号分割追溯码并转换为List
                    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(null)
                            // 仓库
                            .setLocationId(medicationDispense.getLocationId())
                            // 仓位
                            .setLocationStoreId(null)
                            // 产品批号
                            .setLotNumber(medicationDispense.getLotNumber())
                            // 追溯码
                            .setTraceNo(item)
                            // 追溯码状态
                            .setStatusEnum(TraceNoStatus.IN.getValue())
                            // 追溯码单位
                            .setUnitCode(medicationDispense.getUnitCode())
                            // 操作类型
                            .setOperationType(SupplyType.RETURN_MEDICATION.getValue());
                        traceNoManageList.add(traceNoManage);
                    }
                }
            }
            medicationDispenseService.saveBatch(medicationRefundList);
            // 药品退药请求状态变更(待退药→已完成)
            medicationRequestService.updateCompletedStatusBatch(medRequestIdList, null, null);
        }
        // 获取耗材发放id列表
        List<Long> devDispenseIdList =
            returnDeviceList.stream().map(ReturnMedicineDto::getDispenseId).collect(Collectors.toList());
        // 获取退耗材请求id列表
        List<Long> devRequestIdList =
            returnDeviceList.stream().map(ReturnMedicineDto::getRequestId).collect(Collectors.toList());
        if (!devRequestIdList.isEmpty()) {
            // 药品已退药信息查询
            List<DeviceDispense> refundList = deviceDispenseService
                .list(new LambdaQueryWrapper<DeviceDispense>().in(DeviceDispense::getDeviceReqId, devRequestIdList));
            if (refundList != null) {
                if (refundList.stream().map(DeviceDispense::getStatusEnum)
                    .anyMatch(x -> x.equals(DispenseStatus.REFUNDED.getValue()))) {
                    throw new ServiceException("耗材已退，请勿重复操作");
                }
            }
        }
        // 退耗材单列表
        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 (ReturnMedicineDto returnDeviceDto : returnDeviceList) {
                    if (returnDeviceDto.getDispenseId().equals(deviceDispense.getId())) {
                        deviceDispense.setDeviceReqId(returnDeviceDto.getRequestId());
                        // 根据数量设置追溯码
                        deviceDispense.setTraceNo(String.join(CommonConstants.Common.COMMA, Collections
                            .nCopies(deviceDispense.getQuantity().intValue(), CommonConstants.Common.DEV_TRACE_NO)));
                    }
                }
                // 退药时间
                deviceDispense.setDispenseTime(DateUtils.getNowDate());
                // 退药状态
                deviceDispense.setStatusEnum(DispenseStatus.REFUNDED.getValue());
                deviceDispense.setId(null);
                devRefundList.add(deviceDispense);
                // 设置库存变更参数
                supplyItemDetailList
                    .add(new SupplyItemDetailDto().setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
                        .setItemId(deviceDispense.getDeviceDefId()).setLotNumber(deviceDispense.getLotNumber()));
                // // 使用逗号分割追溯码并转换为List
                // String[] traceNoList = deviceDispense.getTraceNo().split(CommonConstants.Common.COMMA);
                // for (String item : traceNoList) {
                // traceNoManage = new TraceNoManage();
                // // 追溯码处理
                // traceNoManage.setItemTable(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
                // // 项目id
                // .setItemId(deviceDispense.getDeviceDefId())
                // // 仓库类型
                // .setLocationTypeEnum(LocationForm.PHARMACY.getValue())
                // // 仓库
                // .setLocationId(deviceDispense.getLocationId())
                // // 产品批号
                // .setLotNumber(deviceDispense.getLotNumber())
                // // 追溯码
                // .setTraceNo(item)
                // // 追溯码状态
                // .setStatusEnum(TraceNoStatus.IN.getValue())
                // // 追溯码单位
                // .setUnitCode(deviceDispense.getUnitCode())
                // // 操作类型
                // .setOperationType(SupplyType.RETURN_MEDICATION.getValue());
                // traceNoManageList.add(traceNoManage);
                // }
            }
            deviceDispenseService.saveBatch(devRefundList);
            // 药品退药请求状态变更(待退药→已完成)
            deviceRequestService.updateCompletedStatusBatch(devRequestIdList);
        }

        List<InventoryItem> inventoryItemList = new ArrayList<>();
        // 获取库存信息
        List<UnDispenseInventoryDto> inventoryList =
            returnMedicineMapper.selectInventoryInfoList(devDispenseIdList, medDispenseIdList,
                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);
            }
            // 库存更新
            iInventoryItemService.updateBatchById(inventoryItemList);
            // 追溯码管理表数据追加
            traceNoManageService.saveBatch(traceNoManageList);
        }
        // 返回信息
        String returnMsg = null;
        List<String> uploadFailedNoList;
        // 调用医保商品销售退货接口
        String ybSwitch = SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.YB_SWITCH); // 医保开关
        if (Whether.YES.getCode().equals(ybSwitch)) {
            List<DeviceDefinition> deviceDefinitions = new ArrayList<>();
            List<MedicationDefinition> medicationDefinitions = new ArrayList<>();
            if (!medicationRefundList.isEmpty()) {
                // 设置进销存参数
                medicationDefinitions = medicationDefinitionService.listByIds(supplyItemDetailList.stream()
                    .filter(x -> x.getItemTable().equals(CommonConstants.TableName.MED_MEDICATION_DEFINITION))
                    .map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            }
            if (!devRefundList.isEmpty()) {
                deviceDefinitions = deviceDefinitionService.listByIds(supplyItemDetailList.stream()
                    .filter(x -> x.getItemTable().equals(CommonConstants.TableName.ADM_DEVICE_DEFINITION))
                    .map(SupplyItemDetailDto::getItemId).collect(Collectors.toList()));
            }

            // 创建映射表，添加空集合保护
            Map<Long, MedicationDefinition> medicationMap =
                medicationDefinitions != null ? medicationDefinitions.stream().filter(Objects::nonNull)
                    .collect(Collectors.toMap(MedicationDefinition::getId, Function.identity())) : new HashMap<>();

            Map<Long, DeviceDefinition> deviceMap =
                deviceDefinitions != null ? deviceDefinitions.stream().filter(Objects::nonNull)
                    .collect(Collectors.toMap(DeviceDefinition::getId, Function.identity())) : new HashMap<>();

            // 设置库存变更参数，添加完整判空
            for (SupplyItemDetailDto dto : supplyItemDetailList) {
                if (dto == null)
                    continue;
                if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dto.getItemTable())) {
                    if (dto.getItemId() != null) {
                        MedicationDefinition med = medicationMap.get(dto.getItemId());
                        if (med != null) {
                            dto.setItemBusNo(med.getBusNo()).setPartPercent(med.getPartPercent())
                                .setRxFlag(med.getRxFlag()).setYbNo(med.getYbNo());
                        }
                    }
                } else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dto.getItemTable())) {
                    if (dto.getItemId() != null) {
                        DeviceDefinition dev = deviceMap.get(dto.getItemId());
                        if (dev != null) {
                            dto.setItemBusNo(dev.getBusNo()).setPartPercent(dev.getPartPercent())
                                .setRxFlag(dev.getRxFlag()).setYbNo(dev.getYbNo());
                        }
                    }
                }
            }
            uploadFailedNoList = this.ybReturnIntegrated(medDispenseIdList, devDispenseIdList);
            uploadFailedNoList = receiptApprovalAppService.ybInventoryIntegrated(supplyItemDetailList,
                YbInvChgType.OTHER_OUT, DateUtils.getNowDate());
            if (uploadFailedNoList != null) {
                returnMsg = "3506商品销售退货上传错误，错误项目编码" + uploadFailedNoList;
            } else {
                returnMsg = "3506商品销售退货上传成功";
            }
        }
        // 返回退药成功信息
        return R.ok(returnMsg, MessageUtils.createMessage(PromptMsgConstant.Common.M00004, new Object[] {"退药"}));
    }

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

    private Medical3506Param getMedical3505Result(DispenseInventoryDto dispenseInventoryDto) {
        Medical3506Param medical3506Param = new Medical3506Param();
        ChargeItem chargeItem = null;
        if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            // 查询费用结算信息
            chargeItem = iChargeItemService.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 = iChargeItemService.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("未查找到就诊诊断信息");
        }
        // 查询付款信息
        PaymentReconciliation paymentReconciliation =
            iPaymentReconciliationService.getOne(new LambdaQueryWrapper<PaymentReconciliation>()
                .eq(PaymentReconciliation::getEncounterId, chargeItem.getEncounterId())
                .like(PaymentReconciliation::getChargeItemIds, chargeItem.getId())
                .eq(PaymentReconciliation::getStatusEnum, PaymentStatus.SUCCESS.getValue())
                .eq(PaymentReconciliation::getPatientId, chargeItem.getPatientId())
                .eq(PaymentReconciliation::getPaymentEnum, PaymentType.PAY.getValue()));
        if (paymentReconciliation == null) {
            throw new ServiceException("未查询到收费");
        }

        // 查询账户信息
        Account account = accountService
            .getOne(new LambdaQueryWrapper<Account>().eq(Account::getEncounterId, chargeItem.getEncounterId())
                .eq(Account::getEncounterFlag, Whether.YES.getValue()));
        if (account == null) {
            throw new ServiceException("未查询到账户");
        }
        // 查询合同实体
        Contract contract =
            iContractService.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())) {
            medical3506Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo());
        } else {
            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) {
                medical3506Param.setMdtrtSn(clinicSettle.getMdtrtId());
            } else {
                medical3506Param.setMdtrtSn(dispenseInventoryDto.getEncounterNo());
            }
        }
        // // 查询发票信息
        // 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);
            }
        }
        medical3506Param.setMedListCodg(dispenseInventoryDto.getYbNo())
            .setFixmedinsBchno(dispenseInventoryDto.getLotNumber())
            .setFixmedinsHilistId(dispenseInventoryDto.getItemNo())
            .setFixmedinsHilistName(CommonConstants.TableName.ADM_DEVICE_DEFINITION)
            .setPsnCertType(mdtrtCertType.getValue()).setManuLotnum(dispenseInventoryDto.getLotNumber())
            .setManuDate(dispenseInventoryDto.getProductionDate())
            .setSelRetnCnt(new BigDecimal(dispenseInventoryDto.getDispenseQuantity().toString()))
            .setSelRetnTime(dispenseInventoryDto.getDispenseTime()).setExpyEnd(dispenseInventoryDto.getExpirationDate())
            .setDrugtracinfo(medicalTraceNo).setCertno(dispenseInventoryDto.getIdCard());
        // 查看所属医院
        String fixmedinsCode =
            SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
        if (dispenseInventoryDto.getPreparerName() == null && HospitalCodeEnum.CCU.getCode().equals(fixmedinsCode)) {
            medical3506Param.setSelRetnOpterName(CommonConstants.CCU.DisDeviceDoctorName);
        } else {
            medical3506Param.setSelRetnOpterName(dispenseInventoryDto.getPreparerName());
        }
        if (dispenseInventoryDto.getInventoryUnitCode().equals(dispenseInventoryDto.getDispenseUnitCode())) {
            medical3506Param.setTrdnFlag(Whether.YES.getCode());
        } else {
            medical3506Param.setTrdnFlag(Whether.NO.getCode());
        }
        if (YbRxFlag.IMPORTANT_HERBAL_SLICES.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3506Param.setRxFlag(YbRxFlag.IMPORTANT_HERBAL_SLICES.getName());
        } else if (YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3506Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
        } else if (YbRxFlag.SELF_PREPARED_MEDICATION.getCode() == dispenseInventoryDto.getRxFlag()) {
            medical3506Param.setRxFlag(YbRxFlag.WESTERN_AND_CHINESE_PATENT_MEDICINE.getName());
        }
        if (CommonConstants.TableName.MED_MEDICATION_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            medical3506Param.setFixmedinsHilistName(CommonConstants.TableName.MED_MEDICATION_DEFINITION);
        } else if (CommonConstants.TableName.ADM_DEVICE_DEFINITION.equals(dispenseInventoryDto.getItemTable())) {
            medical3506Param.setFixmedinsHilistName(CommonConstants.TableName.ADM_DEVICE_DEFINITION);
        }
        return medical3506Param;
    }

    private MedicalInventory3511Param getMedical3511Param(DispenseInventoryDto dispenseInventoryDto) {
        MedicalInventory3511Param medicalInventory3511Param = new MedicalInventory3511Param();

        String fixmedinsCode =
            SecurityUtils.getLoginUser().getOptionJson().getString(CommonConstants.Option.FIXMEDINS_CODE);
        // TODO
        medicalInventory3511Param.setFixmedinsCode(fixmedinsCode).setMedinsListCodg(dispenseInventoryDto.getYbNo())
            .setFixmedinsBchno(dispenseInventoryDto.getLotNumber()).setBegndate(dispenseInventoryDto.getDispenseTime())
            .setEnddate(dispenseInventoryDto.getDispenseTime());

        return medicalInventory3511Param;
    }
}
