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

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

import javax.annotation.Resource;

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.conditions.update.LambdaUpdateWrapper;
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.utils.AssignSeqUtil;
import com.core.common.utils.MessageUtils;
import com.core.common.utils.SecurityUtils;
import com.core.common.utils.StringUtils;
import com.openhis.administration.domain.ChargeItem;
import com.openhis.administration.domain.EncounterDiagnosis;
import com.openhis.administration.service.IChargeItemService;
import com.openhis.administration.service.IEncounterDiagnosisService;
import com.openhis.clinical.domain.Condition;
import com.openhis.clinical.domain.ConditionDefinition;
import com.openhis.clinical.mapper.ConditionDefinitionMapper;
import com.openhis.clinical.service.IConditionService;
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.HisPageUtils;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.medication.domain.MedicationRequest;
import com.openhis.medication.service.IMedicationDispenseService;
import com.openhis.medication.service.IMedicationRequestService;
import com.openhis.web.doctorstation.appservice.IDoctorStationAdviceAppService;
import com.openhis.web.doctorstation.appservice.IDoctorStationChineseMedicalAppService;
import com.openhis.web.doctorstation.dto.*;
import com.openhis.web.doctorstation.mapper.DoctorStationChineseMedicalAppMapper;
import com.openhis.web.doctorstation.utils.AdviceUtils;
import com.openhis.workflow.service.IActivityDefinitionService;

/**
 * 医生站-中医 应用实现类
 */
@Service
public class DoctorStationChineseMedicalAppServiceImpl implements IDoctorStationChineseMedicalAppService {

    @Resource
    DoctorStationChineseMedicalAppMapper doctorStationChineseMedicalAppMapper;

    @Resource
    ConditionDefinitionMapper conditionDefinitionMapper;

    @Resource
    IConditionService iConditionService;

    @Resource
    IEncounterDiagnosisService iEncounterDiagnosisService;

    @Resource
    IDoctorStationAdviceAppService iDoctorStationAdviceAppService;

    @Resource
    IMedicationRequestService iMedicationRequestService;

    @Resource
    IMedicationDispenseService iMedicationDispenseService;

    @Resource
    IActivityDefinitionService iActivityDefinitionService;

    @Resource
    IChargeItemService iChargeItemService;

    @Resource
    AssignSeqUtil assignSeqUtil;

    @Resource
    AdviceUtils adviceUtils;

    /**
     * 查询中医诊断数据
     *
     * @param searchKey 关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 中医诊断数据
     */
    @Override
    public Page<ConditionDefinitionMetadata> getConditionInfo(String searchKey, Integer pageNo, Integer pageSize) {
        // 构建查询条件
        ConditionDefinition conditionDefinition = new ConditionDefinition();
        // 查询状态是有效的
        conditionDefinition.setStatusEnum(PublicationStatus.ACTIVE.getValue());
        // 中医诊断
        conditionDefinition.setSourceEnum(ConditionDefinitionSource.TRADITIONAL_CHINESE_MEDICINE_DIAGNOSIS.getValue());
        QueryWrapper<ConditionDefinition> queryWrapper = HisQueryUtils.buildQueryWrapper(conditionDefinition, searchKey,
            new HashSet<>(Arrays.asList("name", "py_str", "wb_str")), null);
        // 设置排序
        queryWrapper.orderByDesc("update_time");
        // 诊断信息
        Page<ConditionDefinitionMetadata> conditionDefinitionMetadataPage = HisPageUtils
            .selectPage(conditionDefinitionMapper, queryWrapper, pageNo, pageSize, ConditionDefinitionMetadata.class);
        conditionDefinitionMetadataPage.getRecords().forEach(e -> {
            // 所属分类
            e.setSourceEnum_enumText(EnumUtils.getInfoByValue(ConditionDefinitionSource.class, e.getSourceEnum()));
            // 中医诊断
            e.setTypeName(CommonConstants.BusinessName.TCM_DIAGNOSIS);
            // 医保标记
            e.setYbFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbFlag()));
            // 医保对码标记
            e.setYbMatchFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbMatchFlag()));
        });
        return conditionDefinitionMetadataPage;
    }

    /**
     * 查询中医证候数据
     *
     * @param searchKey 关键字
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @return 中医证候数据
     */
    @Override
    public Page<ConditionDefinitionMetadata> getSyndromeInfo(String searchKey, Integer pageNo, Integer pageSize) {
        // 构建查询条件
        ConditionDefinition conditionDefinition = new ConditionDefinition();
        // 查询状态是有效的
        conditionDefinition.setStatusEnum(PublicationStatus.ACTIVE.getValue());
        // 中医证候
        conditionDefinition
            .setSourceEnum(ConditionDefinitionSource.TRADITIONAL_CHINESE_MEDICINE_SYNDROME_CATALOG.getValue());
        QueryWrapper<ConditionDefinition> queryWrapper = HisQueryUtils.buildQueryWrapper(conditionDefinition, searchKey,
            new HashSet<>(Arrays.asList("name", "py_str", "wb_str")), null);
        // 设置排序
        queryWrapper.orderByDesc("update_time");
        // 诊断信息
        Page<ConditionDefinitionMetadata> conditionDefinitionMetadataPage = HisPageUtils
            .selectPage(conditionDefinitionMapper, queryWrapper, pageNo, pageSize, ConditionDefinitionMetadata.class);
        conditionDefinitionMetadataPage.getRecords().forEach(e -> {
            // 所属分类
            e.setSourceEnum_enumText(EnumUtils.getInfoByValue(ConditionDefinitionSource.class, e.getSourceEnum()));
            // 中医证候
            e.setTypeName(CommonConstants.BusinessName.TCM_SYNDROME_CATALOG);
            // 医保标记
            e.setYbFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbFlag()));
            // 医保对码标记
            e.setYbMatchFlag_enumText(EnumUtils.getInfoByValue(Whether.class, e.getYbMatchFlag()));
        });
        return conditionDefinitionMetadataPage;
    }

    /**
     * 保存中医诊断
     *
     * @param saveDiagnosisParam 诊断信息
     * @return 结果
     */
    @Override
    public R<?> saveTcmDiagnosis(SaveDiagnosisParam saveDiagnosisParam) {
        // 患者id
        Long patientId = saveDiagnosisParam.getPatientId();
        // 就诊ID
        Long encounterId = saveDiagnosisParam.getEncounterId();
        // 诊断定义集合
        List<SaveDiagnosisChildParam> diagnosisChildList = saveDiagnosisParam.getDiagnosisChildList();
        // 保存诊断管理
        Condition condition;
        for (SaveDiagnosisChildParam saveDiagnosisChildParam : diagnosisChildList) {
            condition = new Condition();
            condition.setId(saveDiagnosisChildParam.getConditionId());
            condition.setVerificationStatusEnum(saveDiagnosisChildParam.getVerificationStatusEnum());
            condition.setPatientId(patientId);
            condition.setDefinitionId(saveDiagnosisChildParam.getDefinitionId());
            condition.setYbNo(saveDiagnosisChildParam.getYbNo());
            condition.setTcmFlag(Whether.YES.getValue());// 中医标识
            condition.setRecordedDatetime(new Date());
            condition.setRecorderId(SecurityUtils.getLoginUser().getPractitionerId());// 记录人
            iConditionService.saveOrUpdate(condition);
            saveDiagnosisChildParam.setConditionId(condition.getId());
        }
        // 保存就诊诊断
        EncounterDiagnosis encounterDiagnosis;
        for (SaveDiagnosisChildParam saveDiagnosisChildParam : diagnosisChildList) {
            encounterDiagnosis = new EncounterDiagnosis();
            encounterDiagnosis.setId(saveDiagnosisChildParam.getEncounterDiagnosisId());
            encounterDiagnosis.setEncounterId(encounterId);
            encounterDiagnosis.setConditionId(saveDiagnosisChildParam.getConditionId());
            encounterDiagnosis.setMaindiseFlag(saveDiagnosisChildParam.getMaindiseFlag());
            encounterDiagnosis.setDiagSrtNo(saveDiagnosisChildParam.getDiagSrtNo()); // 排序号
            encounterDiagnosis.setMedTypeCode(saveDiagnosisChildParam.getMedTypeCode());// 医疗类型
            encounterDiagnosis.setDiagnosisDesc(saveDiagnosisChildParam.getDiagnosisDesc()); // 诊断描述
            encounterDiagnosis.setIptDiseTypeCode(saveDiagnosisChildParam.getIptDiseTypeCode()); // 患者疾病诊断类型代码
            encounterDiagnosis.setTcmFlag(Whether.YES.getValue());// 中医标识
            encounterDiagnosis.setSyndromeGroupNo(saveDiagnosisChildParam.getSyndromeGroupNo());// 中医证候组号
            iEncounterDiagnosisService.saveOrUpdate(encounterDiagnosis);
        }
        return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"中医诊断"}));
    }

    /**
     * 查询中医就诊诊断信息
     *
     * @param encounterId 就诊id
     * @return 中医就诊诊断信息
     */
    @Override
    public R<?> getTcmEncounterDiagnosis(Long encounterId) {
        HashMap<String, Object> resultMap = new HashMap<>();
        // 中医就诊诊断信息
        List<DiagnosisQueryDto> tcmEncounterDiagnosis =
            doctorStationChineseMedicalAppMapper.getTcmEncounterDiagnosis(encounterId);
        // 病
        List<DiagnosisQueryDto> illness = tcmEncounterDiagnosis.stream().filter(
            e -> ConditionDefinitionSource.TRADITIONAL_CHINESE_MEDICINE_DIAGNOSIS.getValue().equals(e.getSourceEnum()))
            .collect(Collectors.toList());
        // 症
        List<DiagnosisQueryDto> symptom = tcmEncounterDiagnosis.stream()
            .filter(e -> ConditionDefinitionSource.TRADITIONAL_CHINESE_MEDICINE_SYNDROME_CATALOG.getValue()
                .equals(e.getSourceEnum()))
            .collect(Collectors.toList());
        resultMap.put("illness", illness);
        resultMap.put("symptom", symptom);
        return R.ok(resultMap);
    }

    /**
     * 查询中医医嘱信息
     *
     * @param adviceBaseDto 查询条件
     * @param searchKey 模糊查询关键字
     * @param locationId 药房id
     * @param adviceDefinitionIdParamList 医嘱定义id参数集合
     * @param organizationId 患者挂号对应的科室id
     * @param pageNo 当前页
     * @param pageSize 每页多少条
     * @param pricingFlag 划价标记
     * @return 中医医嘱信息
     */
    @Override
    public IPage<AdviceBaseDto> getTcmAdviceBaseInfo(AdviceBaseDto adviceBaseDto, String searchKey, Long locationId,
        List<Long> adviceDefinitionIdParamList, Long organizationId, Integer pageNo, Integer pageSize,
        Integer pricingFlag) {
        adviceBaseDto.setAdviceType(1); // 医嘱类型为药品
        adviceBaseDto.setCategoryCode(MedCategoryCode.CHINESE_HERBAL_MEDICINE.getValue());// 中草药
        return iDoctorStationAdviceAppService.getAdviceBaseInfo(adviceBaseDto, searchKey, locationId,
            adviceDefinitionIdParamList, organizationId, pageNo, pageSize, pricingFlag, List.of(1, 2, 3));
    }

    /**
     * 门诊保存(签发)中医医嘱
     *
     * @param adviceSaveParam 医嘱表单信息
     * @param adviceOpType 保存或签发
     * @return 结果
     */
    @Override
    public R<?> saveOrSignTcmAdvice(AdviceSaveParam adviceSaveParam, String adviceOpType) {
        // 医嘱分类信息 (中草药)
        List<AdviceSaveDto> medicineList = adviceSaveParam.getAdviceSaveList();
        // 保存操作
        boolean is_save = AdviceOpType.SAVE_ADVICE.getCode().equals(adviceOpType);
        // 签发操作
        boolean is_sign = AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType);
        // 当前时间
        Date curDate = new Date();
        // 当前登录账号的科室id
        Long orgId = SecurityUtils.getLoginUser().getOrgId();
        // 患者挂号对应的科室id
        Long organizationId = adviceSaveParam.getOrganizationId();
        // 是否代煎
        Integer sufferingFlag = adviceSaveParam.getSufferingFlag();
        // 中药代煎定义id
        Long sufferingDefinitionId =
            iActivityDefinitionService.getAppointActivityDefinitionId(CommonConstants.BusinessName.SUFFERING_TCM);
        // 保存时,校验库存
        if (is_save) {
            List<AdviceSaveDto> needCheckList = medicineList.stream()
                .filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType())).collect(Collectors.toList());
            // 校验库存
            String tipRes = adviceUtils.checkInventory(needCheckList);
            if (tipRes != null) {
                return R.fail(null, tipRes);
            }
        }
        // 药品请求
        MedicationRequest medicationRequest;
        // 费用项
        ChargeItem chargeItem;
        // 新增 + 修改
        List<AdviceSaveDto> insertOrUpdateList =
            medicineList.stream().filter(e -> (DbOpType.INSERT.getCode().equals(e.getDbOpType())
                || DbOpType.UPDATE.getCode().equals(e.getDbOpType()))).collect(Collectors.toList());
        // 删除
        List<AdviceSaveDto> deleteList = medicineList.stream()
            .filter(e -> DbOpType.DELETE.getCode().equals(e.getDbOpType())).collect(Collectors.toList());
        for (AdviceSaveDto adviceSaveDto : deleteList) {
            iMedicationRequestService.removeById(adviceSaveDto.getRequestId());
            // 删除已经产生的药品发放信息
            iMedicationDispenseService.deleteMedicationDispense(adviceSaveDto.getRequestId());
            // 删除费用项
            iChargeItemService.deleteByServiceTableAndId(CommonConstants.TableName.MED_MEDICATION_REQUEST,
                adviceSaveDto.getRequestId());
            // 删除代煎费
            iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
                .eq(ChargeItem::getPrescriptionNo, adviceSaveDto.getPrescriptionNo())
                .eq(ChargeItem::getProductId, sufferingDefinitionId));

        }

        if (is_sign) {
            // 按groupId分组
            Map<Long, List<AdviceSaveDto>> groupMap =
                insertOrUpdateList.stream().collect(Collectors.groupingBy(AdviceSaveDto::getGroupId));
            // 为每个分组生成唯一的处方号
            groupMap.forEach((groupId, groupList) -> {
                // 先查询当前groupId是否已经被签发生成过处方号
                List<MedicationRequest> list = iMedicationRequestService
                    .list(new LambdaQueryWrapper<MedicationRequest>().eq(MedicationRequest::getGroupId, groupId));
                if (!list.isEmpty() && StringUtils.isNotEmpty(list.get(0).getPrescriptionNo())) {
                    groupList.forEach(dto -> dto.setPrescriptionNo(list.get(0).getPrescriptionNo()));
                } else {
                    String prescriptionNo =
                        assignSeqUtil.getSeq(AssignSeqEnum.PRESCRIPTION_CHINESE_HERBAL_MEDICINE.getPrefix(), 8);
                    groupList.forEach(dto -> dto.setPrescriptionNo(prescriptionNo));
                }
            });
        }

        // 医嘱签发编码
        String signCode = assignSeqUtil.getSeq(AssignSeqEnum.ADVICE_SIGN.getPrefix(), 10);
        for (AdviceSaveDto adviceSaveDto : insertOrUpdateList) {
            // 中药付数
            BigDecimal chineseHerbsDoseQuantity = adviceSaveDto.getChineseHerbsDoseQuantity();
            medicationRequest = new MedicationRequest();
            medicationRequest.setTcmFlag(Whether.YES.getValue());// 中医标识
            medicationRequest.setId(adviceSaveDto.getRequestId()); // 主键id
            medicationRequest.setStatusEnum(is_save ? RequestStatus.DRAFT.getValue() : RequestStatus.ACTIVE.getValue()); // 请求状态
            if (is_sign) {
                medicationRequest.setPrescriptionNo(adviceSaveDto.getPrescriptionNo()); // 处方号
                medicationRequest.setSignCode(signCode);
            }
            // 保存时,处理数据(请求,发放,账单)
            if (is_save) {
                medicationRequest.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.MEDICATION_RES_NO.getPrefix(), 4));
                medicationRequest.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
                medicationRequest.setGroupId(adviceSaveDto.getGroupId()); // 组号
                medicationRequest.setChineseHerbsDoseQuantity(chineseHerbsDoseQuantity); // 中药付数
                medicationRequest.setSufferingFlag(sufferingFlag); // 代煎标识
                medicationRequest.setQuantity(adviceSaveDto.getQuantity().multiply(chineseHerbsDoseQuantity)); // 请求数量
                medicationRequest.setUnitCode(adviceSaveDto.getUnitCode()); // 请求单位编码
                medicationRequest.setLotNumber(adviceSaveDto.getLotNumber()); // 产品批号
                medicationRequest.setCategoryEnum(adviceSaveDto.getCategoryEnum()); // 请求类型
                medicationRequest.setMedicationId(adviceSaveDto.getAdviceDefinitionId());// 医嘱定义id
                medicationRequest.setPatientId(adviceSaveDto.getPatientId()); // 患者
                medicationRequest.setPractitionerId(adviceSaveDto.getPractitionerId()); // 开方医生
                medicationRequest.setOrgId(adviceSaveDto.getFounderOrgId()); // 开方人科室
                medicationRequest.setReqAuthoredTime(curDate); // 请求开始时间
                // 发放药房
                medicationRequest.setPerformLocation(adviceSaveDto.getLocationId());
                medicationRequest.setEncounterId(adviceSaveDto.getEncounterId()); // 就诊id
                medicationRequest.setConditionId(adviceSaveDto.getConditionId()); // 诊断id
                medicationRequest.setEncounterDiagnosisId(adviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
                medicationRequest.setTherapyEnum(adviceSaveDto.getTherapyEnum()); // 治疗类型,默认-临时
                medicationRequest.setMethodCode(adviceSaveDto.getMethodCode()); // 用法
                medicationRequest.setRateCode(adviceSaveDto.getRateCode()); // 用药频次
                medicationRequest.setDose(adviceSaveDto.getDose()); // 单次剂量
                medicationRequest.setDoseUnitCode(adviceSaveDto.getDoseUnitCode()); // 剂量单位
                // medicationRequest.setDispensePerDuration(adviceSaveDto.getDispensePerDuration()); // 每次发药供应天数
                medicationRequest.setContentJson(adviceSaveDto.getContentJson()); // 请求内容json
                medicationRequest.setYbClassEnum(adviceSaveDto.getYbClassEnum());// 类别医保编码
                medicationRequest.setDosageInstruction(adviceSaveDto.getDosageInstruction()); // 用药说明 , 即煎法
            }
            iMedicationRequestService.saveOrUpdate(medicationRequest);
            if (is_save) {
                // 处理药品发放
                Long dispenseId =
                    iMedicationDispenseService.handleMedicationDispense(medicationRequest, adviceSaveDto.getDbOpType());

                // 保存药品费用项
                chargeItem = new ChargeItem();
                chargeItem.setId(adviceSaveDto.getChargeItemId()); // 费用项id
                chargeItem.setStatusEnum(ChargeItemStatus.DRAFT.getValue()); // 默认-草稿
                chargeItem.setBusNo(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix().concat(medicationRequest.getBusNo()));
                chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
                chargeItem.setPrescriptionNo(adviceSaveDto.getPrescriptionNo()); // 处方号
                chargeItem.setPatientId(adviceSaveDto.getPatientId()); // 患者
                chargeItem.setContextEnum(adviceSaveDto.getAdviceType()); // 类型
                chargeItem.setEncounterId(adviceSaveDto.getEncounterId()); // 就诊id
                chargeItem.setDefinitionId(adviceSaveDto.getDefinitionId()); // 费用定价ID
                chargeItem.setDefDetailId(adviceSaveDto.getDefinitionDetailId()); // 定价子表主键
                chargeItem.setEntererId(adviceSaveDto.getPractitionerId());// 开立人ID
                chargeItem.setRequestingOrgId(orgId); // 开立科室
                chargeItem.setEnteredDate(curDate); // 开立时间
                chargeItem.setServiceTable(CommonConstants.TableName.MED_MEDICATION_REQUEST);// 医疗服务类型
                chargeItem.setServiceId(medicationRequest.getId()); // 医疗服务ID
                chargeItem.setProductTable(adviceSaveDto.getAdviceTableName());// 产品所在表
                chargeItem.setProductId(adviceSaveDto.getAdviceDefinitionId());// 收费项id
                chargeItem.setAccountId(adviceSaveDto.getAccountId());// 关联账户ID
                chargeItem.setConditionId(adviceSaveDto.getConditionId()); // 诊断id
                chargeItem.setEncounterDiagnosisId(adviceSaveDto.getEncounterDiagnosisId()); // 就诊诊断id
                // chargeItem.setDispenseId(dispenseId); // 发放ID

                chargeItem.setQuantityValue(medicationRequest.getQuantity()); // 数量
                chargeItem.setQuantityUnit(medicationRequest.getUnitCode()); // 单位
                chargeItem.setUnitPrice(adviceSaveDto.getUnitPrice()); // 单价
                // 计算总价,保留6位小数
                BigDecimal qty = chargeItem.getQuantityValue();
                chargeItem.setTotalPrice(qty.multiply(chargeItem.getUnitPrice()).setScale(6, RoundingMode.HALF_UP)); // 总价

                chargeItem.setTcmFlag(Whether.YES.getValue());// 中医标识
                iChargeItemService.saveOrUpdate(chargeItem);
            }
        }
        // 就诊id
        Long encounterId = medicineList.get(0).getEncounterId();
        // 患者id
        Long patientId = medicineList.get(0).getPatientId();
        // 账户id
        Long accountId = medicineList.get(0).getAccountId();
        // 诊断ID
        Long conditionId = medicineList.get(0).getConditionId();
        // 就诊诊断id
        Long encounterDiagnosisId = medicineList.get(0).getEncounterDiagnosisId();
        // 中药付数
        BigDecimal chineseHerbsDoseQuantity = medicineList.get(0).getChineseHerbsDoseQuantity();
        // 处方号
        String prescriptionNo = insertOrUpdateList.get(0).getPrescriptionNo();

        // 签发时,生成中药代煎的账单
        if (Whether.YES.getValue().equals(sufferingFlag) && is_sign) {
            BigDecimal quantity = chineseHerbsDoseQuantity; // 请求数量

            AdviceBaseDto adviceBaseDto = new AdviceBaseDto();
            adviceBaseDto.setAdviceDefinitionId(sufferingDefinitionId); // 医嘱定义id

            // 先删除中药代煎的账单
            iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
                .eq(ChargeItem::getPrescriptionNo, prescriptionNo).eq(ChargeItem::getProductId, sufferingDefinitionId));

            // 对应的诊疗医嘱信息
            AdviceBaseDto activityAdviceBaseDto = iDoctorStationAdviceAppService.getAdviceBaseInfo(adviceBaseDto, null,
                null, null, organizationId, 1, 1, Whether.NO.getValue(), List.of(3)).getRecords().get(0);
            if (activityAdviceBaseDto != null) {
                // 费用定价
                AdvicePriceDto advicePriceDto = activityAdviceBaseDto.getPriceList().get(0);
                if (advicePriceDto != null) {
                    // 生成账单
                    chargeItem = new ChargeItem();
                    chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
                    chargeItem.setPrescriptionNo(prescriptionNo); // 处方号
                    chargeItem.setStatusEnum(ChargeItemStatus.PLANNED.getValue()); // 收费状态
                    chargeItem.setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.CHARGE_ITEM_NO.getPrefix(), 4));
                    chargeItem.setGenerateSourceEnum(GenerateSource.DOCTOR_PRESCRIPTION.getValue()); // 生成来源
                    chargeItem.setPatientId(patientId); // 患者
                    chargeItem.setContextEnum(ChargeItemContext.ACTIVITY.getValue()); // 类型
                    chargeItem.setEncounterId(encounterId); // 就诊id
                    chargeItem.setDefinitionId(advicePriceDto.getDefinitionId()); // 费用定价ID
                    chargeItem.setEntererId(SecurityUtils.getLoginUser().getPractitionerId());// 开立人ID
                    chargeItem.setRequestingOrgId(orgId); // 开立科室
                    chargeItem.setEnteredDate(curDate); // 开立时间
                    chargeItem.setProductTable(activityAdviceBaseDto.getAdviceTableName());// 产品所在表
                    chargeItem.setProductId(activityAdviceBaseDto.getAdviceDefinitionId());// 收费项id
                    chargeItem.setAccountId(accountId);// 关联账户ID
                    chargeItem.setConditionId(conditionId); // 诊断id
                    chargeItem.setEncounterDiagnosisId(encounterDiagnosisId); // 就诊诊断id

                    chargeItem.setQuantityValue(quantity); // 数量
                    chargeItem.setQuantityUnit(activityAdviceBaseDto.getUnitCode()); // 单位
                    chargeItem.setUnitPrice(advicePriceDto.getPrice()); // 单价
                    // 计算总价,保留6位小数
                    BigDecimal qty = quantity;
                    chargeItem.setTotalPrice(qty.multiply(advicePriceDto.getPrice()).setScale(6, RoundingMode.HALF_UP)); // 总价
                    chargeItem.setTcmFlag(Whether.YES.getValue());// 中医标识
                    iChargeItemService.save(chargeItem);
                }
            }
        } else if (Whether.NO.getValue().equals(sufferingFlag)) {
            // 删除中药代煎的账单
            iChargeItemService.remove(new LambdaQueryWrapper<ChargeItem>()
                .eq(ChargeItem::getPrescriptionNo, prescriptionNo).eq(ChargeItem::getProductId, sufferingDefinitionId));
        }

        // 签发时,把草稿状态的账单更新为待收费[中医]
        if (AdviceOpType.SIGN_ADVICE.getCode().equals(adviceOpType) && !medicineList.isEmpty()) {
            // 签发的医嘱id集合
            List<Long> requestIds = medicineList.stream()
                .filter(e -> !DbOpType.DELETE.getCode().equals(e.getDbOpType()) && e.getRequestId() != null)
                .collect(Collectors.toList()).stream().map(AdviceSaveDto::getRequestId).collect(Collectors.toList());
            iChargeItemService.update(new LambdaUpdateWrapper<ChargeItem>()
                .set(ChargeItem::getStatusEnum, ChargeItemStatus.PLANNED.getValue())
                .eq(ChargeItem::getEncounterId, encounterId)
                .eq(ChargeItem::getStatusEnum, ChargeItemStatus.DRAFT.getValue())
                .in(ChargeItem::getServiceId, requestIds));
        }

        return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00002, new Object[] {"门诊中医医嘱"}));
    }

    /**
     * 查询中医医嘱请求数据
     *
     * @param encounterId 就诊id
     * @return 医嘱请求数据
     */
    public R<?> getTcmRequestBaseInfo(Long encounterId) {
        // 当前账号的参与者id
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        // 医嘱请求数据
        List<RequestBaseDto> requestBaseInfo = doctorStationChineseMedicalAppMapper.getTcmRequestBaseInfo(encounterId,
            null, CommonConstants.TableName.MED_MEDICATION_REQUEST, CommonConstants.TableName.WOR_DEVICE_REQUEST,
            CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId, Whether.NO.getCode(),
            GenerateSource.DOCTOR_PRESCRIPTION.getValue());
        for (RequestBaseDto requestBaseDto : requestBaseInfo) {
            // 请求状态
            requestBaseDto
                .setStatusEnum_enumText(EnumUtils.getInfoByValue(RequestStatus.class, requestBaseDto.getStatusEnum()));
            // 收费状态
            requestBaseDto.setChargeStatus_enumText(
                EnumUtils.getInfoByValue(ChargeItemStatus.class, requestBaseDto.getChargeStatus()));
        }
        return R.ok(requestBaseInfo);
    }

    /**
     * 查询中医历史医嘱请求数据
     *
     * @param patientId 病人id
     * @param encounterId 就诊id
     * @return 中医历史医嘱请求数据
     */
    @Override
    public R<?> getTcmRequestHistoryInfo(Long patientId, Long encounterId) {
        // 当前账号的参与者id
        Long practitionerId = SecurityUtils.getLoginUser().getPractitionerId();
        // 医嘱请求数据
        List<RequestBaseDto> requestBaseInfo = doctorStationChineseMedicalAppMapper.getTcmRequestHistoryInfo(
            encounterId, patientId, CommonConstants.TableName.MED_MEDICATION_REQUEST,
            CommonConstants.TableName.WOR_DEVICE_REQUEST, CommonConstants.TableName.WOR_SERVICE_REQUEST, practitionerId,
            Whether.YES.getCode(), GenerateSource.DOCTOR_PRESCRIPTION.getValue());
        for (RequestBaseDto requestBaseDto : requestBaseInfo) {
            // 请求状态
            requestBaseDto
                .setStatusEnum_enumText(EnumUtils.getInfoByValue(RequestStatus.class, requestBaseDto.getStatusEnum()));
            // 收费状态
            requestBaseDto.setChargeStatus_enumText(
                EnumUtils.getInfoByValue(ChargeItemStatus.class, requestBaseDto.getChargeStatus()));
        }
        return R.ok(requestBaseInfo);
    }

    /**
     * 删除中医诊断
     *
     * @param syndromeGroupNo 中医证候组号
     * @return 结果
     */
    @Override
    public R<?> delTcmDiagnosis(String syndromeGroupNo) {
        // 诊断id集合
        List<Long> conditionIds = doctorStationChineseMedicalAppMapper.getConditionIds(syndromeGroupNo);
        if (conditionIds.isEmpty()) {
            return R.fail("数据已被删除,请刷新页面");
        }
        if (doctorStationChineseMedicalAppMapper.getAdviceNumByConditionIds(conditionIds) > 0) {
            return R.fail("所选诊断已经存在医嘱记录，不允许删除");
        }
        for (Long conditionId : conditionIds) {
            iConditionService.removeById(conditionId);
            iEncounterDiagnosisService.remove(
                new LambdaQueryWrapper<EncounterDiagnosis>().eq(EncounterDiagnosis::getConditionId, conditionId));
        }
        return R.ok(null, MessageUtils.createMessage(PromptMsgConstant.Common.M00005, new Object[] {"就诊诊断信息"}));
    }
}
