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

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

import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
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.enums.DeleteFlag;
import com.core.common.utils.AssignSeqUtil;
import com.core.common.utils.DateUtils;
import com.core.common.utils.SecurityUtils;
import com.openhis.administration.domain.ChargeItemDefinition;
import com.openhis.administration.service.IChargeItemDefinitionService;
import com.openhis.common.constant.CommonConstants;
import com.openhis.common.enums.*;
import com.openhis.common.enums.ybenums.YbChrgitmLv;
import com.openhis.common.utils.HisQueryUtils;
import com.openhis.medication.domain.MedicationDefinition;
import com.openhis.medication.service.IMedicationDefinitionService;
import com.openhis.nenu.domain.GfRatio;
import com.openhis.nenu.domain.GfRatioApplication;
import com.openhis.nenu.service.IGfRatioApplicationService;
import com.openhis.nenu.service.IGfRatioService;
import com.openhis.web.nenu.appservice.IGfRatioApplicationRecordAppService;
import com.openhis.web.nenu.dto.GfRatioApplicationDefinitionSelectDto;
import com.openhis.web.nenu.dto.GfRatioApplicationPrintDto;
import com.openhis.web.nenu.dto.GfRatioApplicationProcessDto;
import com.openhis.web.nenu.dto.GfRatioApplicationRecordDto;
import com.openhis.web.nenu.mapper.GfRatioApplicationRecordAppMapper;
import com.openhis.workflow.domain.ActivityDefinition;
import com.openhis.workflow.service.IActivityDefinitionService;

/**
 * 公费医疗-比例调整申请记录 AppServiceImpl
 *
 * @author Thanking
 * @date 2025-10-21
 */
@Service
public class GfRatioApplicationRecordAppServiceImpl implements IGfRatioApplicationRecordAppService {

    @Autowired
    private IGfRatioService gfRatioService;
    @Autowired
    private IGfRatioApplicationService gfRatioApplicationService;
    @Autowired
    private IMedicationDefinitionService medicationDefinitionService;
    @Autowired
    private IActivityDefinitionService activityDefinitionService;
    @Autowired
    private IChargeItemDefinitionService chargeItemDefinitionService;
    @Autowired
    private GfRatioApplicationRecordAppMapper gfRatioApplicationRecordAppMapper;
    @Autowired
    private AssignSeqUtil assignSeqUtil;

    /**
     * 查询比例调整申请记录分页
     *
     * @param searchParam 查询参数
     * @param printable 申请单是否可打印
     * @param searchKey 模糊查询关键字
     * @param pageNo 页码
     * @param pageSize 行数
     * @return 比例调整申请记录分页
     */
    @Override
    public R<IPage<GfRatioApplicationRecordDto>> getPage(GfRatioApplicationRecordDto searchParam, String printable,
        String searchKey, Integer pageNo, Integer pageSize) {
        // 构造查询条件
        QueryWrapper<GfRatioApplicationRecordDto> queryWrapper = HisQueryUtils.buildQueryWrapper(searchParam, searchKey,
            new HashSet<>(Set.of("application_no", "bus_no", "name", "py_str", "wb_str", "yb_no")), null);
        // 可打印筛选
        if (Whether.YES.getCode().equals(printable)) {
            queryWrapper.eq("application_status", GfApplicationStatus.PROCESSING.getValue()).eq("final_approval_result",
                GfApplicationStatus.PROCESSING.getValue());
        }
        // 查询比例调整申请记录分页
        IPage<GfRatioApplicationRecordDto> page = gfRatioApplicationRecordAppMapper
            .selectGfRatioApplicationRecordPage(new Page<>(pageNo, pageSize), queryWrapper);
        for (GfRatioApplicationRecordDto r : page.getRecords()) {
            // 翻译非字典枚举
            GfItemType gfItemType = GfItemType.getByValue(r.getItemType());
            if (gfItemType != null) {
                r.setItemTypeName(gfItemType.getInfo());
            }
        }
        return R.ok(page);
    }

    /**
     * 查询比例调整申请记录详情
     *
     * @param id ID
     * @return 比例调整申请记录详情
     */
    @Override
    public R<GfRatioApplicationRecordDto> getDetail(Long id) {
        // 查询比例调整申请记录详情
        GfRatioApplication gfRatioApplication = gfRatioApplicationService.getById(id);
        if (gfRatioApplication == null) {
            return R.fail();
        }
        // 定义返回Dto
        GfRatioApplicationRecordDto gfRatioApplicationRecordDto = new GfRatioApplicationRecordDto();
        String defTableName = CommonConstants.TableName.MED_MEDICATION_DEFINITION;
        String chrgitmLv = YbChrgitmLv.SELF_PAY.getCode();
        String ybNo = null;
        if (GfItemType.MEDICATION.getValue().equals(gfRatioApplication.getItemType())) {
            // 如果是药品，获取并设置药品定义信息
            MedicationDefinition medicationDefinition =
                medicationDefinitionService.getById(gfRatioApplication.getDefinitionId());
            if (medicationDefinition != null) {
                gfRatioApplicationRecordDto.setBusNo(medicationDefinition.getBusNo())
                    .setName(medicationDefinition.getName()).setYbNo(medicationDefinition.getYbNo())
                    // 公费项目分类：药品
                    .setItemTypeName(GfItemType.MEDICATION.getInfo());
                chrgitmLv =
                    Optional.of(medicationDefinition.getChrgitmLv()).orElse(YbChrgitmLv.SELF_PAY.getValue()).toString();
                ybNo = medicationDefinition.getYbNo();
            }
        } else if (GfItemType.ACTIVITY.getValue().equals(gfRatioApplication.getItemType())) {
            // 如果是诊疗，获取并设置诊疗定义信息
            ActivityDefinition activityDefinition =
                activityDefinitionService.getById(gfRatioApplication.getDefinitionId());
            if (activityDefinition != null) {
                gfRatioApplicationRecordDto.setBusNo(activityDefinition.getBusNo())
                    .setName(activityDefinition.getName()).setYbNo(activityDefinition.getYbNo())
                    // 公费项目分类：诊疗
                    .setItemTypeName(GfItemType.ACTIVITY.getInfo());
                chrgitmLv =
                    Optional.of(activityDefinition.getChrgitmLv()).orElse(YbChrgitmLv.SELF_PAY.getValue()).toString();
                ybNo = activityDefinition.getYbNo();
            }
            defTableName = CommonConstants.TableName.WOR_ACTIVITY_DEFINITION;
        }
        YbChrgitmLv ybChrgitmLv = YbChrgitmLv.getByCode(chrgitmLv);
        // 查询原支付比例
        Pair<Pair<BigDecimal, BigDecimal>, BigDecimal> oldRatiosAndPrice =
            this.getOldRatiosAndPrice(gfRatioApplication.getDefinitionId(), defTableName, chrgitmLv);
        // Dto赋值返回
        gfRatioApplicationRecordDto.setId(gfRatioApplication.getId()).setApplicationNo(gfRatioApplication.getBusNo())
            .setItemType(gfRatioApplication.getItemType())
            // 医保编号
            .setYbNo(ybNo)
            // 医保等级名称
            .setChrgitmLvName(ybChrgitmLv == null ? null : ybChrgitmLv.getInfo())
            .setApplicationRatio(gfRatioApplication.getApplicationRatio())
            .setOldRatio(oldRatiosAndPrice.getLeft().getLeft()).setTotalPrice(oldRatiosAndPrice.getRight())
            // 价格差：计算得出
            .setPriceDiff(oldRatiosAndPrice.getLeft().getLeft() != null
                && gfRatioApplication.getApplicationRatio() != null && oldRatiosAndPrice.getRight() != null
                    ? gfRatioApplication.getApplicationRatio().subtract(oldRatiosAndPrice.getLeft().getLeft())
                        .multiply(oldRatiosAndPrice.getRight()).divide(new BigDecimal(100), RoundingMode.UNNECESSARY)
                    : null)
            .setTwiceRatio(gfRatioApplication.getTwiceRatio()).setOldTwiceRatio(oldRatiosAndPrice.getLeft().getRight())
            .setStartDate(gfRatioApplication.getStartDate()).setEndDate(gfRatioApplication.getEndDate())
            .setApplicationStatus(gfRatioApplication.getApplicationStatus())
            .setApplicant(gfRatioApplication.getApplicant()).setApplicationTime(gfRatioApplication.getApplicationTime())
            .setApplicationReason(gfRatioApplication.getApplicationReason())
            .setInitialApprover(gfRatioApplication.getInitialApprover())
            .setInitialApprovalResult(gfRatioApplication.getInitialApprovalResult())
            .setInitialApprovalTime(gfRatioApplication.getInitialApprovalTime())
            .setInitialApprovalOpinion(gfRatioApplication.getInitialApprovalOpinion())
            .setFinanceApprover(gfRatioApplication.getFinanceApprover())
            .setFinanceApprovalResult(gfRatioApplication.getFinanceApprovalResult())
            .setFinanceApprovalTime(gfRatioApplication.getFinanceApprovalTime())
            .setFinanceApprovalOpinion(gfRatioApplication.getFinanceApprovalOpinion())
            .setFinalRecorder(gfRatioApplication.getFinalRecorder())
            .setFinalApprovalResult(gfRatioApplication.getFinalApprovalResult())
            .setFinalRecordTime(gfRatioApplication.getFinalRecordTime())
            .setFinalApprovalOpinion(gfRatioApplication.getFinalApprovalOpinion());
        return R.ok(gfRatioApplicationRecordDto);
    }

    /**
     * 创建比例调整申请
     *
     * @param gfRatioApplicationRecordDto 比例调整申请记录Dto
     * @return 结果
     */
    @Override
    public R<?> add(GfRatioApplicationRecordDto gfRatioApplicationRecordDto) {
        // 查询指定项目现行比例
        List<GfRatio> gfRatioList = gfRatioService.list(new LambdaQueryWrapper<GfRatio>()
            .eq(GfRatio::getDefinitionId, gfRatioApplicationRecordDto.getDefinitionId())
            .eq(GfRatio::getDeleteFlag, DeleteFlag.NOT_DELETED.getCode()));
        // 验证时间是否重叠
        if (!gfRatioList.isEmpty()) {
            for (GfRatio r : gfRatioList) {
                if (!r.getStartDate().after(gfRatioApplicationRecordDto.getEndDate())
                    && !r.getEndDate().before(gfRatioApplicationRecordDto.getStartDate())) {
                    return R.fail("该项目此次申请的开始结束时间与现行比例开始结束时间有重叠，请确认");
                }
            }
        }
        // 创建申请
        GfRatioApplication gfRatioApplication = new GfRatioApplication()
            .setBusNo(assignSeqUtil.getSeqByDay(AssignSeqEnum.GF_RATIO_APPLICATION.getPrefix(), 4))
            .setItemType(gfRatioApplicationRecordDto.getItemType())
            .setApplicationRatio(gfRatioApplicationRecordDto.getApplicationRatio())
            .setTwiceRatio(gfRatioApplicationRecordDto.getTwiceRatio())
            .setStartDate(gfRatioApplicationRecordDto.getStartDate())
            // 结束时间：调整为当天23点59分59秒
            .setEndDate(DateUtils.addSeconds(DateUtils.addDays(gfRatioApplicationRecordDto.getEndDate(), 1), -1))
            // 申请状态：处理中
            .setApplicationStatus(GfApplicationStatus.PROCESSING.getValue()).setApplicant(SecurityUtils.getNickName())
            .setApplicationTime(DateUtils.getNowDate())
            .setApplicationReason(gfRatioApplicationRecordDto.getApplicationReason())
            // 测算通过or驳回：处理中
            .setInitialApprovalResult(GfApplicationStatus.PROCESSING.getValue())
            .setDefinitionId(gfRatioApplicationRecordDto.getDefinitionId());
        gfRatioApplicationService.save(gfRatioApplication);
        return R.ok();
    }

    /**
     * 取消比例调整申请
     *
     * @param id ID
     * @return 结果
     */
    @Override
    public R<?> cancel(Long id) {
        // 存在验证
        GfRatioApplication gfRatioApplication = gfRatioApplicationService.getById(id);
        if (gfRatioApplication == null) {
            return R.fail("申请不存在");
        }
        // 状态验证
        if (!GfApplicationStatus.PROCESSING.getValue().equals(gfRatioApplication.getApplicationStatus())
            && !GfApplicationStatus.PROCESSING.getValue().equals(gfRatioApplication.getInitialApprovalResult())) {
            return R.fail("该申请已不可取消");
        }
        // 更新申请记录
        gfRatioApplicationService.update(new GfRatioApplication(), new LambdaUpdateWrapper<GfRatioApplication>()
            // 申请状态：取消
            .set(GfRatioApplication::getApplicationStatus, GfApplicationStatus.CANCELLED.getValue())
            // 测算通过or驳回：NULL
            .set(GfRatioApplication::getInitialApprovalResult, null).eq(GfRatioApplication::getId, id));

        return null;
    }

    /**
     * 处理比例调整申请
     *
     * @param gfRatioApplicationProcessDto 比例调整申请处理Dto
     * @return 结果
     */
    @Override
    public R<?> process(GfRatioApplicationProcessDto gfRatioApplicationProcessDto) {
        // 存在验证
        GfRatioApplication gfRatioApplication = gfRatioApplicationService.getById(gfRatioApplicationProcessDto.getId());
        if (gfRatioApplication == null) {
            return R.fail("申请不存在");
        }
        // 状态验证
        if (GfApplicationStatus.APPROVED.getValue().equals(gfRatioApplication.getApplicationStatus())) {
            return R.fail("该申请已被通过，无需处理");
        }
        if (GfApplicationStatus.REJECTED.getValue().equals(gfRatioApplication.getApplicationStatus())) {
            return R.fail("该申请已被驳回，不可处理");
        }
        if (GfApplicationStatus.CANCELLED.getValue().equals(gfRatioApplication.getApplicationStatus())) {
            return R.fail("该申请已被取消，不可处理");
        }
        // 根据执行操作的角色分别处理
        String loginUserName = SecurityUtils.getNickName();
        Date now = DateUtils.getNowDate();

        // 【测算盈亏】
        if (GfApprovalRole.INITIAL_APPROVER.getValue().equals(gfRatioApplicationProcessDto.getApprovalRole())) {
            if (!GfApplicationStatus.PROCESSING.getValue().equals(gfRatioApplication.getInitialApprovalResult())) {
                return R.fail("该节点已被处理，不可再处理");
            }

            // 申请通过
            if (GfApplicationStatus.APPROVED.getValue().equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(),
                    new LambdaUpdateWrapper<GfRatioApplication>()
                        .set(GfRatioApplication::getInitialApprover, loginUserName)
                        // 测算通过or驳回：通过
                        .set(GfRatioApplication::getInitialApprovalResult, GfApplicationStatus.APPROVED.getValue())
                        .set(GfRatioApplication::getInitialApprovalTime, now)
                        .set(GfRatioApplication::getInitialApprovalOpinion,
                            gfRatioApplicationProcessDto.getApprovalOpinion())
                        // 财务科通过or驳回：处理中
                        .set(GfRatioApplication::getFinanceApprovalResult, GfApplicationStatus.PROCESSING.getValue())
                        .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));

                // 申请驳回
            } else if (GfApplicationStatus.REJECTED.getValue()
                .equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(),
                    new LambdaUpdateWrapper<GfRatioApplication>()
                        .set(GfRatioApplication::getInitialApprover, loginUserName)
                        // 测算通过or驳回：驳回
                        .set(GfRatioApplication::getInitialApprovalResult, GfApplicationStatus.REJECTED.getValue())
                        .set(GfRatioApplication::getInitialApprovalTime, now)
                        .set(GfRatioApplication::getInitialApprovalOpinion,
                            gfRatioApplicationProcessDto.getApprovalOpinion())
                        // 申请状态：驳回
                        .set(GfRatioApplication::getApplicationStatus, GfApplicationStatus.REJECTED.getValue())
                        .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));
            } else {
                return R.fail("通过or驳回指定错误");
            }

            // 【财务科报批】
        } else if (GfApprovalRole.FINANCE_APPROVER.getValue().equals(gfRatioApplicationProcessDto.getApprovalRole())) {
            if (!GfApplicationStatus.PROCESSING.getValue().equals(gfRatioApplication.getFinanceApprovalResult())) {
                return R.fail("该节点已被处理，不可再处理");
            }

            // 申请通过
            if (GfApplicationStatus.APPROVED.getValue().equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(),
                    new LambdaUpdateWrapper<GfRatioApplication>()
                        .set(GfRatioApplication::getFinanceApprover, loginUserName)
                        // 财务科通过or驳回：通过
                        .set(GfRatioApplication::getFinanceApprovalResult, GfApplicationStatus.APPROVED.getValue())
                        .set(GfRatioApplication::getFinanceApprovalTime, now)
                        .set(GfRatioApplication::getFinanceApprovalOpinion,
                            gfRatioApplicationProcessDto.getApprovalOpinion())
                        // 会议通过or驳回：处理中
                        .set(GfRatioApplication::getFinalApprovalResult, GfApplicationStatus.PROCESSING.getValue())
                        .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));

                // 申请驳回
            } else if (GfApplicationStatus.REJECTED.getValue()
                .equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(),
                    new LambdaUpdateWrapper<GfRatioApplication>()
                        .set(GfRatioApplication::getFinanceApprover, loginUserName)
                        // 财务科通过or驳回：驳回
                        .set(GfRatioApplication::getFinanceApprovalResult, GfApplicationStatus.REJECTED.getValue())
                        .set(GfRatioApplication::getFinanceApprovalTime, now)
                        .set(GfRatioApplication::getFinanceApprovalOpinion,
                            gfRatioApplicationProcessDto.getApprovalOpinion())
                        // 申请状态：驳回
                        .set(GfRatioApplication::getApplicationStatus, GfApplicationStatus.REJECTED.getValue())
                        .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));
            } else {
                return R.fail("通过or驳回指定错误");
            }

            // 【会议结果录入】
        } else if (GfApprovalRole.FINAL_RECORDER.getValue().equals(gfRatioApplicationProcessDto.getApprovalRole())) {
            if (!GfApplicationStatus.PROCESSING.getValue().equals(gfRatioApplication.getFinalApprovalResult())) {
                return R.fail("该节点已被处理，不可再处理");
            }

            // 申请通过
            if (GfApplicationStatus.APPROVED.getValue().equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(), new LambdaUpdateWrapper<GfRatioApplication>()
                    .set(GfRatioApplication::getFinalRecorder, loginUserName)
                    // 会议通过or驳回：通过
                    .set(GfRatioApplication::getFinalApprovalResult, GfApplicationStatus.APPROVED.getValue())
                    .set(GfRatioApplication::getFinalRecordTime, now)
                    .set(GfRatioApplication::getFinalApprovalOpinion, gfRatioApplicationProcessDto.getApprovalOpinion())
                    // 申请状态：通过
                    .set(GfRatioApplication::getApplicationStatus, GfApplicationStatus.APPROVED.getValue())
                    .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));
                // 创建现行自付比例
                GfRatio gfRatio = new GfRatio()
                    // 比例类型：单项比例
                    .setRatioType(GfRatioType.INDIVIDUAL_RATIO.getValue()).setItemType(gfRatioApplication.getItemType())
                    .setSelfRatio(gfRatioApplication.getApplicationRatio())
                    .setTwiceRatio(gfRatioApplication.getTwiceRatio()).setStartDate(gfRatioApplication.getStartDate())
                    .setEndDate(gfRatioApplication.getEndDate()).setDefinitionId(gfRatioApplication.getDefinitionId());
                gfRatioService.save(gfRatio);

                // 申请驳回
            } else if (GfApplicationStatus.REJECTED.getValue()
                .equals(gfRatioApplicationProcessDto.getApprovalResult())) {
                // 申请驳回，更新申请记录
                gfRatioApplicationService.update(new GfRatioApplication(), new LambdaUpdateWrapper<GfRatioApplication>()
                    .set(GfRatioApplication::getFinalRecorder, loginUserName)
                    // 财务科通过or驳回：驳回
                    .set(GfRatioApplication::getFinalApprovalResult, GfApplicationStatus.REJECTED.getValue())
                    .set(GfRatioApplication::getFinalRecordTime, now)
                    .set(GfRatioApplication::getFinalApprovalOpinion, gfRatioApplicationProcessDto.getApprovalOpinion())
                    // 申请状态：驳回
                    .set(GfRatioApplication::getApplicationStatus, GfApplicationStatus.REJECTED.getValue())
                    .eq(GfRatioApplication::getId, gfRatioApplicationProcessDto.getId()));
            } else {
                return R.fail("通过or驳回指定错误");
            }
        } else {
            return R.fail("角色指定错误");
        }
        return R.ok();
    }

    /**
     * 查询申请项目选择弹窗分页
     *
     * @param searchParam 查询参数
     * @param searchKey 模糊查询关键字
     * @param itemType 项目分类
     * @param pageNo 页码
     * @param pageSize 行数
     * @return 申请项目选择弹窗分页
     */
    @Override
    public R<IPage<GfRatioApplicationDefinitionSelectDto>> getDefinitionSelectPage(
        GfRatioApplicationDefinitionSelectDto searchParam, String searchKey, Integer itemType, Integer pageNo,
        Integer pageSize) {
        // 构造查询条件
        QueryWrapper<GfRatioApplicationDefinitionSelectDto> queryWrapper = HisQueryUtils.buildQueryWrapper(searchParam,
            searchKey, new HashSet<>(Set.of("bus_no", "name", "py_str", "wb_str", "yb_no")), null);
        // 查询比例调整申请记录分页
        IPage<GfRatioApplicationDefinitionSelectDto> page = gfRatioApplicationRecordAppMapper
            .selectGfRatioApplicationDefinitionSelectPage(itemType, new Page<>(pageNo, pageSize), queryWrapper);
        // 翻译非字典枚举
        for (GfRatioApplicationDefinitionSelectDto dto : page.getRecords()) {
            YbChrgitmLv ybChrgitmLv = YbChrgitmLv.getByValue(dto.getChrgitmLv());
            if (ybChrgitmLv != null) {
                dto.setChrgitmLvName(ybChrgitmLv.getInfo());
            }
        }
        return R.ok(page);
    }

    /**
     * 查询申请单打印列表
     *
     * @param ids 多个ID逗号拼接
     * @return 申请单打印列表
     */
    @Override
    public R<List<GfRatioApplicationPrintDto>> getPrintList(String ids) {
        // 切割读取多个ID
        List<Long> idList;
        try {
            idList = Arrays.stream(ids.split(",")).map(String::trim).filter(s -> !s.isEmpty()).map(Long::valueOf)
                .collect(Collectors.toList());
        } catch (NumberFormatException e) {
            return R.fail("传参有误");
        }
        if (idList.isEmpty()) {
            return R.ok(Collections.emptyList());
        }
        // 查询要打印的申请单
        List<GfRatioApplication> applicationList =
            gfRatioApplicationService.list(new LambdaQueryWrapper<GfRatioApplication>()
                .in(GfRatioApplication::getId, idList).orderByDesc(GfRatioApplication::getId));
        if (applicationList.isEmpty()) {
            return R.ok(Collections.emptyList());
        }
        // 循环做出打印信息列表
        List<GfRatioApplicationPrintDto> printDtoList = new ArrayList<>();
        GfRatioApplicationPrintDto printDto;
        for (GfRatioApplication application : applicationList) {
            printDto = new GfRatioApplicationPrintDto();
            String itemName = "";
            String ybLv = YbChrgitmLv.SELF_PAY.getCode();
            String defTableName = CommonConstants.TableName.MED_MEDICATION_DEFINITION;
            if (GfItemType.MEDICATION.getValue().equals(application.getItemType())) {
                // 获取药品名称和医保等级
                MedicationDefinition medicationDefinition =
                    medicationDefinitionService.getById(application.getDefinitionId());
                if (medicationDefinition != null) {
                    itemName = medicationDefinition.getName();
                    ybLv = Optional.of(medicationDefinition.getChrgitmLv()).orElse(YbChrgitmLv.SELF_PAY.getValue())
                        .toString();
                }
            } else if (GfItemType.ACTIVITY.getValue().equals(application.getItemType())) {
                // 获取诊疗名称和医保等级
                ActivityDefinition activityDefinition =
                    activityDefinitionService.getById(application.getDefinitionId());
                if (activityDefinition != null) {
                    itemName = activityDefinition.getName();
                    ybLv = Optional.of(activityDefinition.getChrgitmLv()).orElse(YbChrgitmLv.SELF_PAY.getValue())
                        .toString();
                }
                defTableName = CommonConstants.TableName.WOR_ACTIVITY_DEFINITION;
            }
            YbChrgitmLv ybChrgitmLv = YbChrgitmLv.getByCode(ybLv);
            // 查询原支付比例和价格（包括二次比例）
            Pair<Pair<BigDecimal, BigDecimal>, BigDecimal> oldRatiosAndPrice =
                this.getOldRatiosAndPrice(application.getDefinitionId(), defTableName, ybLv);
            BigDecimal oldRatio = oldRatiosAndPrice.getLeft().getLeft();
            BigDecimal oldTwiceRatio = oldRatiosAndPrice.getLeft().getRight();
            BigDecimal totalPrice = oldRatiosAndPrice.getRight();
            // 作成返回Dto
            printDto.setItemName(itemName)
                // 全价
                .setTotalPrice(totalPrice == null ? "" : totalPrice.stripTrailingZeros().toPlainString())
                // 医保等级
                .setChrgitmLv(ybChrgitmLv == null ? "" : ybChrgitmLv.getInfo())
                // 原支付比例
                .setOldRatio(oldRatio == null ? "" : oldRatio.stripTrailingZeros().toPlainString())
                // 新支付比例
                .setNewRatio(application.getApplicationRatio() == null ? ""
                    : application.getApplicationRatio().stripTrailingZeros().toPlainString())
                // 价格差
                .setPriceDiff(oldRatio != null && application.getApplicationRatio() != null && totalPrice != null
                    ? application.getApplicationRatio().subtract(oldRatio).multiply(totalPrice)
                        .divide(new BigDecimal(100), RoundingMode.UNNECESSARY).stripTrailingZeros().toPlainString()
                    : "")
                // 原二次支付比例
                .setOldTwiceRatio(oldTwiceRatio == null ? "" : oldTwiceRatio.stripTrailingZeros().toPlainString())
                // 新二次支付比例
                .setNewTwiceRatio(application.getTwiceRatio() == null ? ""
                    : application.getTwiceRatio().stripTrailingZeros().toPlainString());
            printDtoList.add(printDto);
        }
        return R.ok(printDtoList);
    }

    /**
     * 查询原支付比例和价格（包括二次比例）
     * 
     * @param definitionId 定义ID
     * @param definitionTableName 定义表名
     * @param ybLv 医保等级
     * @return 原支付比例和价格（包括二次比例）
     */
    private Pair<Pair<BigDecimal, BigDecimal>, BigDecimal> getOldRatiosAndPrice(Long definitionId,
        String definitionTableName, String ybLv) {
        BigDecimal oldRatio = null;
        BigDecimal price = null;
        // 查询费用定价
        List<ChargeItemDefinition> chargeItemDefinitionList = chargeItemDefinitionService
            .list(new LambdaQueryWrapper<ChargeItemDefinition>().eq(ChargeItemDefinition::getInstanceId, definitionId)
                .eq(ChargeItemDefinition::getInstanceTable, definitionTableName)
                .orderByDesc(ChargeItemDefinition::getId));
        if (!chargeItemDefinitionList.isEmpty()) {
            price = chargeItemDefinitionList.get(0).getPrice();
            // 查询现行大类比例
            List<GfRatio> typeRatioList = gfRatioService
                .list(new LambdaQueryWrapper<GfRatio>().eq(GfRatio::getRatioType, GfRatioType.TYPE_RATIO.getValue())
                    .eq(GfRatio::getYbClass, chargeItemDefinitionList.get(0).getYbType()).eq(GfRatio::getYbLv, ybLv)
                    .eq(GfRatio::getDeleteFlag, DeleteFlag.NOT_DELETED.getCode()));
            if (!typeRatioList.isEmpty()) {
                oldRatio = typeRatioList.get(0).getSelfRatio();
            }
        }
        // 查询历史小项比例
        List<GfRatio> historicalRatioList =
            gfRatioService.list(new LambdaQueryWrapper<GfRatio>().eq(GfRatio::getDefinitionId, definitionId)
                .eq(GfRatio::getDeleteFlag, DeleteFlag.NOT_DELETED.getCode()).orderByDesc(GfRatio::getId));
        BigDecimal oldTwiceRatio = null;
        if (!historicalRatioList.isEmpty()) {
            GfRatio latestRatio = historicalRatioList.get(0);
            Date now = DateUtils.getNowDate();
            // 只获取还在生效中的历史小项比例
            if (latestRatio.getStartDate().before(now) && latestRatio.getEndDate().after(now)) {
                oldRatio = latestRatio.getSelfRatio();
                oldTwiceRatio = latestRatio.getTwiceRatio();
            }
        }
        return Pair.of(Pair.of(oldRatio, oldTwiceRatio), price);
    }
}
