package cn.iocoder.yudao.module.system.service.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.*;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.*;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.system.enums.change.BusinessConstants;
import cn.iocoder.yudao.module.system.enums.common.BooleanEnum;
import cn.iocoder.yudao.module.system.util.BizUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;


/**
 * 长者退住结算单 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class RefundSettlementOrderServiceImpl implements RefundSettlementOrderService {

    @Resource
    private DepositMapper depositMapper;
    @Resource
    private BuildService buildService;
    @Resource
    private ElderlyInfoMapper elderlyInfoMapper;

    @Resource
    private ElderlyContractMapper elderlyContractMapper;

    @Resource
    private ExpenseOrderMapper expenseOrderMapper;

    @Resource
    private ExpensePayOrderMapper expensePayOrderMapper;

    @Resource
    private ExpensePayOrderItemMapper expensePayOrderItemMapper;

    @Resource
    private ExpenseItemMapper expenseItemMapper;

    @Resource
    private DailyExpensesMapper dailyExpensesMapper;

    @Resource
    private ExpenseOrderItemMapper expenseOrderItemMapper;

    @Resource
    private RefundSettlementOrderMapper refundSettlementOrderMapper;

    @Resource
    private ElderlyRetreatRecordMapper elderlyRetreatRecordMapper;

    @Resource
    private RefundSupplementarySettlementMapper refundSupplementarySettlementMapper;
    @Resource
    private RefundSettlementOrderItemMapper refundSettlementOrderItemMapper;

    @Resource
    private DepositRecordMapper depositRecordMapper;

    @Resource
    private TenantMapper tenantMapper;

    @Autowired
    private NotifyMessageSendApi notifyMessageSendApi;
    @Resource
    private ExpenseSubsidyMapper expenseSubsidyMapper;
    @Autowired
    private ElderlyConsumerVouchersMapper elderlyConsumerVouchersMapper;

    @Resource
    private BizUtil bizUtil;

    @Override
    public PageResult<RefundSettlementOrderDO> getRefundSettlementOrderPage(RefundSettlementOrderPageReqVO pageReqVO) {
        Page<RefundSettlementOrderDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<RefundSettlementOrderDO> list = refundSettlementOrderMapper.getRefundSettlementOrderPage(page, pageReqVO);
        for (RefundSettlementOrderDO refundSettlementOrderDO : list) {
            refundSettlementOrderDO.setBedName(buildService.getFullBedName(refundSettlementOrderDO.getElderId()));
            TenantDO tenantDO = tenantMapper.selectById(refundSettlementOrderDO.getTenantId());
            refundSettlementOrderDO.setTenantName(tenantDO == null ? null : tenantDO.getName());
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public RefundSettlementOrderRespVO getRefundSettlementOrder(Long id) {
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(id);
        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());
        if (elderlyInfo == null) {
            throw new RuntimeException("找不到该长者信息");
        }
        ElderlyRetreatRecordDO elderlyRetreatRecord = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());

        RefundSettlementOrderRespVO respVO = new RefundSettlementOrderRespVO();
        respVO.setId(refundSettlementOrder.getId());
        respVO.setOrderNumber(refundSettlementOrder.getOrderNumber());
        respVO.setElderName(elderlyInfo.getElderName());
        respVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
        respVO.setCheckInTime(elderlyInfo.getCheckInTime());
        respVO.setRetreatDate(elderlyRetreatRecord.getRetreatDate());
        respVO.setCostDeadlineDate(elderlyRetreatRecord.getCostDeadlineDate());
        respVO.setSettlementTime(refundSettlementOrder.getSettlementTime() == null ? null : refundSettlementOrder.getSettlementTime());
        respVO.setSettlementPersonName(StringUtils.isBlank(refundSettlementOrder.getSettlementPersonName()) ? null : refundSettlementOrder.getSettlementPersonName());
        respVO.setRefundableAmount(refundSettlementOrder.getRefundableAmount());
        respVO.setReceivableAmount(refundSettlementOrder.getReceivableAmount());
        respVO.setRefundAmount(refundSettlementOrder.getRefundAmount());

        //获取退住单费用项
        List<RefundSettlementOrderItemDO> refundSettlementOrderItems = refundSettlementOrderItemMapper.selectList(new LambdaQueryWrapperX<RefundSettlementOrderItemDO>()
                .eq(RefundSettlementOrderItemDO::getRefundSettlementOrderId, refundSettlementOrder.getId()));

        respVO.setRefundSettlementOrderItems(refundSettlementOrderItems);
        // 更新总金额
        updateTotalAmount(respVO);
        return respVO;
    }

//    private void createdDepositData(ElderlyInfoDO elderlyInfo, RefundSettlementOrderDO refundSettlementOrder, RefundSettlementOrderRespVO respVO) {
//        List<RefundSettlementOrderItemDO> settlementOrderItemList = new ArrayList<>();
//        List<ExpenseOrderDO> expenseOrderList = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
//                .eq(ExpenseOrderDO::getElderId, elderlyInfo.getId())
//                .eq(ExpenseOrderDO::getTenantId, elderlyInfo.getTenantId())
//                .eq(ExpenseOrderDO::getType, 1)
//                .orderByDesc(ExpenseOrderDO::getCreatedTime));
//
//        if (expenseOrderList != null && !expenseOrderList.isEmpty()) {
//            ExpenseOrderDO expenseOrderDO = expenseOrderList.stream().findFirst().get();
//            List<ExpenseOrderItemDO> expenseOrderItemList = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
//                    .eq(ExpenseOrderItemDO::getExpenseOrderId, expenseOrderDO.getId()));
//
//            for (ExpenseOrderItemDO orderItemDO : expenseOrderItemList) {
//                ExpenseItemDO dbExpenseItemDO = expenseItemMapper.selectOne(new LambdaQueryWrapperX<ExpenseItemDO>()
//                        .eq(ExpenseItemDO::getId, orderItemDO.getSourceExpenseItemId())
//                        .eq(ExpenseItemDO::getIsDeposit, 1));
//
//                if (dbExpenseItemDO != null) {
//                    RefundSettlementOrderItemDO refundSettlementOrderItemDO = new RefundSettlementOrderItemDO();
//                    refundSettlementOrderItemDO.setRefundSettlementOrderId(refundSettlementOrder.getId());
//                    refundSettlementOrderItemDO.setRefundAmount(dbExpenseItemDO.getAmount());
//                    refundSettlementOrderItemDO.setActualRefundAmount(dbExpenseItemDO.getAmount());
//                    refundSettlementOrderItemDO.setItemName(dbExpenseItemDO.getItemName());
//                    refundSettlementOrderItemDO.setTenantId(elderlyInfo.getTenantId());
//                    settlementOrderItemList.add(refundSettlementOrderItemDO);
//                }
//            }
//
//        }
//        respVO.setRefundSettlementOrderItems(settlementOrderItemList);
//    }

    private void createdDepositData(ElderlyInfoDO elderlyInfo, RefundSettlementOrderDO refundSettlementOrder, RefundSettlementOrderRespVO respVO) {
        List<RefundSettlementOrderItemDO> settlementOrderItemList = new ArrayList<>();

        // 查询押金记录表中类型为缴纳的押金记录
        List<DepositRecordDO> depositRecordList = depositRecordMapper.selectList(new LambdaQueryWrapperX<DepositRecordDO>()
                .eq(DepositRecordDO::getElderId, elderlyInfo.getId())
                .eq(DepositRecordDO::getType, 1) // 1: 缴纳类型
                .orderByDesc(DepositRecordDO::getCreatedTime));

        // 按照押金名称分组，合并相同押金的金额
        Map<String, List<DepositRecordDO>> depositGroupMap = depositRecordList.stream()
                .collect(Collectors.groupingBy(DepositRecordDO::getItemName));

        // 为每种押金创建退款项
        for (Map.Entry<String, List<DepositRecordDO>> entry : depositGroupMap.entrySet()) {
            String itemName = entry.getKey();
            List<DepositRecordDO> records = entry.getValue();

            // 计算该押金类型的总金额
            BigDecimal totalAmount = records.stream()
                    .map(DepositRecordDO::getAmount)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                RefundSettlementOrderItemDO refundSettlementOrderItemDO = new RefundSettlementOrderItemDO();
                refundSettlementOrderItemDO.setRefundSettlementOrderId(refundSettlementOrder.getId());
                refundSettlementOrderItemDO.setRefundAmount(totalAmount);
                refundSettlementOrderItemDO.setActualRefundAmount(totalAmount);
                refundSettlementOrderItemDO.setItemName(itemName);
                refundSettlementOrderItemDO.setTenantId(elderlyInfo.getTenantId());
                settlementOrderItemList.add(refundSettlementOrderItemDO);
            }
        }

        respVO.setRefundSettlementOrderItems(settlementOrderItemList);
    }


    @Override
    public RefundSettlementOrderRespVO getRefundSettlementOrderDetails(Long id) {
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(id);
        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());
        ElderlyRetreatRecordDO elderlyRetreatRecord = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());

        RefundSettlementOrderRespVO respVO = new RefundSettlementOrderRespVO();
        respVO.setOrderNumber(refundSettlementOrder.getOrderNumber());
        respVO.setElderName(elderlyInfo.getElderName());
        respVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
        respVO.setCheckInTime(elderlyInfo.getCheckInTime());
        respVO.setRetreatDate(elderlyRetreatRecord.getRetreatDate());
        respVO.setCostDeadlineDate(elderlyRetreatRecord.getCostDeadlineDate());
        respVO.setSettlementTime(refundSettlementOrder.getSettlementTime() == null ? null : refundSettlementOrder.getSettlementTime());
        respVO.setSettlementPersonName(StringUtils.isBlank(refundSettlementOrder.getSettlementPersonName()) ? null : refundSettlementOrder.getSettlementPersonName());


        //获取押金记录
        createdDepositData(elderlyInfo, refundSettlementOrder, respVO);

        //获取支付信息
        ExpensePayOrderDO expensePayOrderDO = expensePayOrderMapper
                .selectOne(new LambdaQueryWrapperX<ExpensePayOrderDO>()
                        .eq(ExpensePayOrderDO::getExpenseOrderId, refundSettlementOrder.getId())
                        .eq(ExpensePayOrderDO::getType, 2));  //退住结算单类型的
        if (expensePayOrderDO != null) {
            List<ExpensePayOrderItemDO> payInfo = expensePayOrderItemMapper
                    .selectList(new LambdaQueryWrapperX<ExpensePayOrderItemDO>()
                            .eq(ExpensePayOrderItemDO::getPayOrderId, expensePayOrderDO.getId()));

            respVO.setPayInfo(payInfo);
            respVO.setRemarks(expensePayOrderDO.getRemarks());
        }

        //获取订单信息
        LocalDate costDeadlineDate = respVO.getCostDeadlineDate();
        String nowDate = costDeadlineDate.format(DateTimeFormatter.ofPattern("yyyy-MM"));

        //查询参与退住结算的订单
        List<ExpenseOrderDO> result = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getRefundSettlementOrderId, refundSettlementOrder.getId()));


        List<ExpenseOrderVO> orders = result.stream().map(item -> {
            ExpenseOrderVO orderVO = new ExpenseOrderVO();
            orderVO.setId(item.getId());
            orderVO.setBillingMonth(item.getBillingMonth());
            orderVO.setType(item.getType());
            orderVO.setPayStatus(item.getPayStatus());
            orderVO.setPayableAmount(item.getPayableAmount() == null ? BigDecimal.ZERO : item.getPayableAmount());


            //计算金额
            BigDecimal refundableAmount = BigDecimal.ZERO;   //应退金额
            BigDecimal receivableAmount = BigDecimal.ZERO;   //应收金额

            List<ExpenseOrderItemDO> expenseOrderItems = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                    .eq(ExpenseOrderItemDO::getExpenseOrderId, item.getId()));

            for (ExpenseOrderItemDO expenseOrderItem : expenseOrderItems) {
                if (expenseOrderItem.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                    ExpenseItemDO expenseItemDO = expenseItemMapper.selectById(expenseOrderItem.getSourceExpenseItemId());
                    expenseOrderItem.setIsMonthlyExpense(expenseItemDO == null ? null : expenseItemDO.getIsMonthlyExpense());
                    expenseOrderItem.setIsOneTimeFee(expenseItemDO == null ? null : expenseItemDO.getIsOneTimeFee());
                }
            }

            List<ExpenseOrderItemVO> resultList = new ArrayList<>();
            for (ExpenseOrderItemDO e : expenseOrderItems) {
                ExpenseOrderItemVO itemVO = new ExpenseOrderItemVO();
                //长住走正常退款计算
                if (elderlyInfo.getInStatusType() == 1) {
                    //已支付账单
                    if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
                        //入院账单，不会包含日常费用
                        if (item.getType() == 1) {
                            if (e.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                                ExpenseItemDO expenseItem = expenseItemMapper.selectById(e.getSourceExpenseItemId());
                                if (expenseItem.getIsDeposit() == 1) {
                                    continue;
                                }
                                if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
                                    LocalDate checkInDate = elderlyInfo.getCheckInTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                                    //查询变更
                                    List<ExpenseItemDO> changeExpenseItems = expenseItemMapper.selectListByMonth(item.getElderId(), checkInDate, expenseItem.getType());
                                    //判断有没有变更
                                    if (CollectionUtil.isNotEmpty(changeExpenseItems)) {
                                        for (ExpenseItemDO changeExpenseItem : changeExpenseItems) {
                                            ExpenseOrderItemVO newItemVO = new ExpenseOrderItemVO();
                                            if (changeExpenseItem.getChangeStartDate().isBefore(costDeadlineDate) || changeExpenseItem.getChangeStartDate().equals(costDeadlineDate)) {
                                                LocalDate changeStartDate = changeExpenseItem.getChangeStartDate();
                                                LocalDate changeEndDate = changeExpenseItem.getChangeEndDate();
                                                if (changeStartDate != null && changeEndDate != null) {
                                                    long stayDay = ChronoUnit.DAYS.between(changeStartDate, changeEndDate) + 1;
                                                    BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(checkInDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                    BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                    newItemVO.setRemarks("收" + changeStartDate + "到" + changeEndDate + "共" + stayDay + "天的费用");
                                                    newItemVO.setItemName(changeExpenseItem.getItemName());
                                                    newItemVO.setDays((int) stayDay);
                                                    newItemVO.setPrice(dayPrice);
                                                    newItemVO.setAmount(amount);
                                                    newItemVO.setIsMonthlyExpense(changeExpenseItem.getIsMonthlyExpense());
                                                    newItemVO.setIsOneTimeFee(changeExpenseItem.getIsOneTimeFee());
                                                    receivableAmount = receivableAmount.add(newItemVO.getAmount());
                                                    resultList.add(newItemVO);

                                                } else {
                                                    long stayDay = ChronoUnit.DAYS.between(changeStartDate, costDeadlineDate) + 1;
                                                    BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(checkInDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                    BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                    newItemVO.setRemarks("收" + changeStartDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                                    newItemVO.setItemName(changeExpenseItem.getItemName());
                                                    newItemVO.setDays((int) stayDay);

                                                    newItemVO.setPrice(dayPrice);
                                                    newItemVO.setAmount(amount);
                                                    newItemVO.setIsMonthlyExpense(changeExpenseItem.getIsMonthlyExpense());
                                                    newItemVO.setIsOneTimeFee(changeExpenseItem.getIsOneTimeFee());
                                                    receivableAmount = receivableAmount.add(newItemVO.getAmount());
                                                    resultList.add(newItemVO);
                                                }
                                            }
                                        }
                                    } else {
                                        long stayDay = ChronoUnit.DAYS.between(checkInDate, costDeadlineDate) + 1;  //入住天数
                                        BigDecimal dayPrice = e.getPrice().divide(BigDecimal.valueOf(checkInDate.lengthOfMonth()), 8, RoundingMode.DOWN);  //每日单价
                                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP); //总金额
                                        itemVO.setRemarks("收" + checkInDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setDays((int) stayDay);
                                        itemVO.setPrice(dayPrice);
                                        itemVO.setAmount(amount);
//                                        itemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());  //月度费用
                                        itemVO.setIsMonthlyExpense(e.getIsMonthlyExpense());
                                        itemVO.setIsOneTimeFee(e.getIsOneTimeFee());
                                        //应收金额
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    }
                                } else {
                                    itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());  //其他费用
                                    if (expenseItem.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        long monthBetween = ChronoUnit.MONTHS.between(expenseItem.getFreeStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                                                expenseItem.getFreeEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
                                        itemVO.setRemarks("赠送" + monthBetween + "个月" + e.getItemName());
                                    } else if (expenseItem.getIsOneTimeFee().equals(BooleanEnum.TRUE.getValue())) {
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setRemarks(e.getItemName());
                                    }
                                    //应收金额
                                    receivableAmount = receivableAmount.add(itemVO.getAmount());
                                }
                            } else {
                                DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                if (dailyExpenses != null) {
                                    itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                    itemVO.setDailyExpenseType(dailyExpenses.getType());
                                    itemVO.setItemName(e.getItemName());
                                    itemVO.setCount(e.getCount());
                                    itemVO.setPrice(e.getActualPrice());
                                    itemVO.setAmount(e.getTotalAmount());
                                    itemVO.setRemarks(dailyExpenses.getRemarks());
                                    //分两种情况，有应退的和应收的
                                    if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                        //应退金额
                                        refundableAmount = refundableAmount.add(itemVO.getAmount());
                                    } else {
                                        //应收金额
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    }
                                }
                            }
                        } else {
                            //月度账单,可能包含日常杂费
                            //当月退住计算入住天数和金额
                            if (nowDate.equals(item.getBillingMonth())) {
                                if (e.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                                    ExpenseItemDO expenseItem = expenseItemMapper.selectById(e.getSourceExpenseItemId());
                                    if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
                                        //计算月度费用,从月初到结算时间的费用
                                        LocalDate firstDayDate = costDeadlineDate.with(TemporalAdjusters.firstDayOfMonth()); //首月第一天
                                        //查询变更
                                        List<ExpenseItemDO> changeExpenseItems = expenseItemMapper.selectListByMonth(item.getElderId(), firstDayDate, expenseItem.getType());
                                        //判断有没有变更
                                        if (CollectionUtil.isNotEmpty(changeExpenseItems)) {
                                            for (ExpenseItemDO changeExpenseItem : changeExpenseItems) {
                                                ExpenseOrderItemVO newItemVO = new ExpenseOrderItemVO();
                                                if (changeExpenseItem.getChangeStartDate().isBefore(costDeadlineDate) || changeExpenseItem.getChangeStartDate().equals(costDeadlineDate)) {
                                                    LocalDate changeStartDate = changeExpenseItem.getChangeStartDate();
                                                    LocalDate changeEndDate = changeExpenseItem.getChangeEndDate();
                                                    if (changeStartDate != null && changeEndDate != null) {
                                                        long stayDay = ChronoUnit.DAYS.between(changeStartDate, changeEndDate) + 1;
                                                        BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                        newItemVO.setRemarks("收" + changeStartDate + "到" + changeEndDate + "共" + stayDay + "天的费用");
                                                        newItemVO.setItemName(changeExpenseItem.getItemName());
                                                        newItemVO.setDays((int) stayDay);
                                                        newItemVO.setPrice(dayPrice);
                                                        newItemVO.setAmount(amount);
                                                        newItemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());
                                                        receivableAmount = receivableAmount.add(newItemVO.getAmount());

                                                    } else {
                                                        long stayDay = ChronoUnit.DAYS.between(changeStartDate, costDeadlineDate) + 1;
                                                        BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                        newItemVO.setRemarks("收" + changeStartDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                                        newItemVO.setItemName(changeExpenseItem.getItemName());
                                                        newItemVO.setDays((int) stayDay);
                                                        newItemVO.setPrice(dayPrice);
                                                        newItemVO.setAmount(amount);
                                                        newItemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());
                                                        receivableAmount = receivableAmount.add(newItemVO.getAmount());
                                                    }
                                                }
                                            }
                                        } else {
                                            //已住天数
                                            long stayDay = ChronoUnit.DAYS.between(firstDayDate, costDeadlineDate) + 1;
                                            BigDecimal dayPrice = e.getActualPrice().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                            BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                            itemVO.setRemarks("收" + firstDayDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                            itemVO.setItemName(e.getItemName());
                                            itemVO.setDays((int) stayDay);
                                            itemVO.setPrice(dayPrice);
                                            itemVO.setAmount(amount);
                                            itemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());
                                            //应收金额
                                            receivableAmount = receivableAmount.add(itemVO.getAmount());
                                        }
                                    } else {
                                        if (expenseItem.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
                                            itemVO.setItemName(e.getItemName());
                                            itemVO.setCount(e.getCount());
                                            itemVO.setPrice(e.getActualPrice());
                                            itemVO.setAmount(e.getTotalAmount());
                                            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                            long monthBetween = ChronoUnit.MONTHS.between(expenseItem.getFreeStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                                                    expenseItem.getFreeEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
                                            itemVO.setRemarks("赠送" + monthBetween + "个月" + e.getItemName());
                                        }
                                    }
                                } else {
                                    //其他费用
                                    DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                    if (dailyExpenses != null) {
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        itemVO.setDailyExpenseType(dailyExpenses.getType());
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setRemarks(dailyExpenses.getRemarks());
                                        //分两种情况，有应退的和应收的
                                        if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                            //应退金额
                                            refundableAmount = refundableAmount.add(itemVO.getAmount());
                                        } else {
                                            //应收金额
                                            receivableAmount = receivableAmount.add(itemVO.getAmount());
                                        }
                                    }
                                }
                            } else {
                                //非当月不计算固定费用，只计算其他费用
                                if (e.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                                    ExpenseItemDO expenseItem = expenseItemMapper.selectById(e.getSourceExpenseItemId());
                                    if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
                                        TemporalAccessor parsed = DateTimeFormatter.ofPattern("yyyy-MM").parse(item.getBillingMonth());
                                        int day = YearMonth.from(parsed).lengthOfMonth(); //本月天数
                                        BigDecimal dayPrice = e.getActualPrice().divide(BigDecimal.valueOf(day), 8, RoundingMode.DOWN);
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setDays(0);
                                        itemVO.setPrice(dayPrice);
                                        itemVO.setAmount(BigDecimal.ZERO);
                                        itemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());
                                        itemVO.setRemarks("预收" + e.getTotalAmount().setScale(2, RoundingMode.DOWN) + "元,在住天数" + itemVO.getDays() + "天,应退" + e.getTotalAmount().setScale(2, RoundingMode.DOWN) + "元");
                                    } else if (e.getIsFreeGift() != null && e.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        long monthBetween = ChronoUnit.MONTHS.between(expenseItem.getFreeStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                                                expenseItem.getFreeEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
                                        itemVO.setRemarks("赠送" + monthBetween + "个月" + e.getItemName());
                                    }
                                    //应收金额
                                    if (itemVO.getAmount() != null) {
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    }

                                } else {
                                    //其他费用
                                    DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                    if (dailyExpenses != null) {
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        itemVO.setDailyExpenseType(dailyExpenses.getType());
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setRemarks(dailyExpenses.getRemarks());

                                        //分两种情况，有应退的和应收的
                                        if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                            //应退金额
                                            refundableAmount = refundableAmount.add(itemVO.getAmount());
                                        } else {
                                            //应收金额
                                            receivableAmount = receivableAmount.add(itemVO.getAmount());
                                        }
                                    }
                                }
                            }
                        }


                    } else {
                        //未支付完成的账单，只存在月度账单，入院账单必须缴纳
                        //如果是当前月份计算需要计算出已住的天数金额
                        if (nowDate.equals(item.getBillingMonth())) {
                            if (e.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                                //固定费用
                                ExpenseItemDO expenseItem = expenseItemMapper.selectById(e.getSourceExpenseItemId());
                                if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
                                    //计算月度费用,从月初到结算时间的费用
                                    LocalDate firstDayDate = costDeadlineDate.with(TemporalAdjusters.firstDayOfMonth()); //首月第一天
                                    //查询变更
                                    List<ExpenseItemDO> changeExpenseItems = expenseItemMapper.selectListByMonth(item.getElderId(), firstDayDate, expenseItem.getType());
                                    //判断有没有变更
                                    if (CollectionUtil.isNotEmpty(changeExpenseItems)) {
                                        for (ExpenseItemDO changeExpenseItem : changeExpenseItems) {
                                            ExpenseOrderItemVO newItemVO = new ExpenseOrderItemVO();
                                            if (changeExpenseItem.getChangeStartDate().isBefore(costDeadlineDate) || changeExpenseItem.getChangeStartDate().equals(costDeadlineDate)) {
                                                LocalDate changeStartDate = changeExpenseItem.getChangeStartDate();
                                                LocalDate changeEndDate = changeExpenseItem.getChangeEndDate();
                                                if (changeStartDate != null && changeEndDate != null) {
                                                    long stayDay = ChronoUnit.DAYS.between(changeStartDate, changeEndDate) + 1;
                                                    BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                    BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                    newItemVO.setRemarks("收" + changeStartDate + "到" + changeEndDate + "共" + stayDay + "天的费用");
                                                    newItemVO.setItemName(changeExpenseItem.getItemName());
                                                    newItemVO.setDays((int) stayDay);
                                                    newItemVO.setPrice(dayPrice);
                                                    newItemVO.setAmount(amount);
                                                    newItemVO.setIsMonthlyExpense(changeExpenseItem.getIsMonthlyExpense());
                                                    newItemVO.setIsOneTimeFee(changeExpenseItem.getIsOneTimeFee());
                                                    receivableAmount = receivableAmount.add(newItemVO.getAmount());
                                                    resultList.add(newItemVO);
                                                } else {
                                                    long stayDay = ChronoUnit.DAYS.between(changeStartDate, costDeadlineDate) + 1;
                                                    BigDecimal dayPrice = changeExpenseItem.getTotalAmount().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);
                                                    BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);
                                                    newItemVO.setRemarks("收" + changeStartDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                                    newItemVO.setItemName(changeExpenseItem.getItemName());
                                                    newItemVO.setDays((int) stayDay);
                                                    newItemVO.setPrice(dayPrice);
                                                    newItemVO.setAmount(amount);
                                                    newItemVO.setIsMonthlyExpense(changeExpenseItem.getIsMonthlyExpense());
                                                    newItemVO.setIsOneTimeFee(changeExpenseItem.getIsOneTimeFee());
                                                    receivableAmount = receivableAmount.add(newItemVO.getAmount());
                                                    resultList.add(newItemVO);
                                                }
                                            }
                                        }
                                    } else {
                                        //已住天数
                                        long stayDay = ChronoUnit.DAYS.between(firstDayDate, costDeadlineDate) + 1;
                                        BigDecimal dayPrice = e.getPrice().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);  //每日单价
                                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP); //总金额
                                        itemVO.setRemarks("收" + firstDayDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setDays((int) stayDay);
                                        itemVO.setPrice(dayPrice);
                                        itemVO.setAmount(amount);
//                                        itemVO.setIsMonthlyExpense(BooleanEnum.TRUE.getValue());  //月度费用
                                        itemVO.setIsMonthlyExpense(e.getIsMonthlyExpense());
                                        itemVO.setIsOneTimeFee(e.getIsOneTimeFee());
                                        //应收金额
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    }
                                } else {
                                    if (expenseItem.getIsFreeGift() != null && expenseItem.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        long monthBetween = ChronoUnit.MONTHS.between(expenseItem.getFreeStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                                                expenseItem.getFreeEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
                                        itemVO.setRemarks("赠送" + monthBetween + "个月" + e.getItemName());
                                    }
                                }
                            } else {
                                //其他费用
                                DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                if (dailyExpenses != null) {
                                    itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                    itemVO.setDailyExpenseType(dailyExpenses.getType());
                                    itemVO.setItemName(e.getItemName());
                                    itemVO.setCount(e.getCount());
                                    itemVO.setPrice(e.getActualPrice());
                                    itemVO.setAmount(e.getTotalAmount());
                                    itemVO.setRemarks(dailyExpenses.getRemarks());

                                    if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                        //应退金额
                                        refundableAmount = refundableAmount.add(itemVO.getAmount());
                                    } else {
                                        //应收金额
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    }
                                }
                            }
                        } else {
                            //非当前月份的账单，可能当前月份之前的或者之后的
                            TemporalAccessor parsed = DateTimeFormatter.ofPattern("yyyy-MM").parse(item.getBillingMonth());
                            LocalDate billingMonth = YearMonth.from(parsed).atEndOfMonth();
                            //退住月份之前的账单只查未缴费的费项
                            if (billingMonth.isBefore(costDeadlineDate)) {
                                //todo 退住月份之前的只查未缴费的费项，退住月份之后的只查其他费用，固定费用过滤掉
                                if (e.getPayStatus().equals(BooleanEnum.FALSE.getValue())) {
                                    if (e.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                                        //计算月度费用,从月初到结算时间的费用，之前未缴费的固定费用从月初收到月尾
                                        LocalDate firstDayDate = billingMonth.with(TemporalAdjusters.firstDayOfMonth()); //月份第一天
                                        LocalDate endDayDate = billingMonth.with(TemporalAdjusters.lastDayOfMonth());  //月份最后一天
                                        //已住天数
                                        long stayDay = firstDayDate.lengthOfMonth();
                                        BigDecimal dayPrice = e.getPrice().divide(BigDecimal.valueOf(firstDayDate.lengthOfMonth()), 8, RoundingMode.DOWN);  //每日单价
                                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP); //总金额
                                        itemVO.setRemarks("收" + firstDayDate + "到" + endDayDate + "共" + stayDay + "天的费用");
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setDays((int) stayDay);
                                        itemVO.setPrice(dayPrice);
                                        itemVO.setAmount(amount);
                                        itemVO.setIsMonthlyExpense(e.getIsMonthlyExpense());  //月度费用
                                        itemVO.setIsOneTimeFee(e.getIsOneTimeFee());
                                        //应收金额
                                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                                    } else {
                                        //其他费用
                                        DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                        if (dailyExpenses != null) {
                                            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                            itemVO.setDailyExpenseType(dailyExpenses.getType());
                                            itemVO.setItemName(e.getItemName());
                                            itemVO.setCount(e.getCount());
                                            itemVO.setPrice(e.getActualPrice());
                                            itemVO.setAmount(e.getTotalAmount());
                                            itemVO.setRemarks(dailyExpenses.getRemarks());

                                            if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                                //应退金额
                                                refundableAmount = refundableAmount.add(itemVO.getAmount());
                                            } else {
                                                //应收金额
                                                receivableAmount = receivableAmount.add(itemVO.getAmount());
                                            }
                                        }
                                    }
                                }
                            } else {
                                //退住月份之后的账单只查其他费用，固定费用过滤掉
                                if (e.getExpenseSource().equals(BusinessConstants.DAILY_EXPENSES)) {
                                    DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(e.getSourceExpenseItemId());
                                    if (dailyExpenses != null) {
                                        itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                                        itemVO.setDailyExpenseType(dailyExpenses.getType());
                                        itemVO.setItemName(e.getItemName());
                                        itemVO.setCount(e.getCount());
                                        itemVO.setPrice(e.getActualPrice());
                                        itemVO.setAmount(e.getTotalAmount());
                                        itemVO.setRemarks(dailyExpenses.getRemarks());

                                        if (itemVO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
                                            //应退金额
                                            refundableAmount = refundableAmount.add(itemVO.getAmount());
                                        } else {
                                            //应收金额
                                            receivableAmount = receivableAmount.add(itemVO.getAmount());
                                        }
                                    }
                                }
                            }
                        }
                    }
                } else {
                    //试住
                    //试住状态下的退费流程
                    ElderlyContractDO elderlyContract = elderlyContractMapper.selectOne(new LambdaQueryWrapperX<ElderlyContractDO>().eq(ElderlyContractDO::getElderId, elderlyInfo.getId()));
                    Date beginTime = elderlyContract.getBeginTime();
                    Date expireTime = elderlyContract.getExpireTime();


                    LocalDate beginDate = beginTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    LocalDate expireDate = expireTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    //合同天数
                    long daysBetween = ChronoUnit.DAYS.between(beginDate, expireDate) + 1;
                    if (e.getIsDeposit().equals(BooleanEnum.FALSE.getValue())) {
                        //日价
                        BigDecimal dayPrice = e.getActualPrice().divide(BigDecimal.valueOf(daysBetween), 8, RoundingMode.DOWN);
                        //已住天数
                        long stayDay = ChronoUnit.DAYS.between(beginDate, costDeadlineDate) + 1;
                        //已住金额
                        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay));
                        //试用期未住满
                        if (stayDay != daysBetween) {
                            itemVO.setItemName(e.getItemName());
                            itemVO.setCount(1);
                            itemVO.setAmount(amount);
                            itemVO.setRemarks("收" + beginDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                        } else {
                            itemVO.setItemName(e.getItemName());
                            itemVO.setCount(1);
                            itemVO.setAmount(e.getTotalAmount());
                            itemVO.setRemarks("收" + beginDate + "到" + costDeadlineDate + "共" + stayDay + "天的费用");
                            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                        }
                        //应收金额
                        receivableAmount = receivableAmount.add(itemVO.getAmount());
                    }
                }
                resultList.add(itemVO);
            }
            //统计金额
            orderVO.setRefundableAmount(refundableAmount);
            orderVO.setReceivableAmount(receivableAmount);
            orderVO.setOrderItems(resultList.stream().filter(e -> StringUtils.isNotBlank(e.getItemName())).collect(Collectors.toList()));
            if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
                orderVO.setOrderAmount(item.getPayableAmount().subtract(receivableAmount.add(refundableAmount)).negate());
            } else {
                //未支付的订单，分两种情况，一种是缴纳了部分费用的账单和另外一种全部未缴纳的账单
                if (orderVO.getPayableAmount().compareTo(BigDecimal.ZERO) > 0) {
                    //存在部分实缴，部分未缴纳的
                    //总额等于 （应收金额 + 应退金额）
                    orderVO.setOrderAmount(orderVO.getReceivableAmount().add(orderVO.getRefundableAmount()));
                } else {
                    //全部未缴纳的账单
                    orderVO.setOrderAmount(orderVO.getReceivableAmount().add(orderVO.getRefundableAmount()));
                }
            }

            return orderVO;
        }).sorted(Comparator.comparing(ExpenseOrderVO::getBillingMonth)).collect(Collectors.toList());
        respVO.setOrders(orders);
        return respVO;
    }


//    @Override
//    public void settleAccounts(ExpensePayOrderSaveReqVO saveReqVO) {
//        RefundSettlementOrderDO refundSettlementOrderDO = refundSettlementOrderMapper.selectById(saveReqVO.getRefundSettlementOrderId());
//        if (refundSettlementOrderDO != null) {
//            refundSettlementOrderDO.setSettlementPersonName(SecurityFrameworkUtils.getLoginUserNickname());
//            refundSettlementOrderDO.setSettlementTime(new Date());
//            refundSettlementOrderDO.setStatus(BooleanEnum.TRUE.getValue());
//            refundSettlementOrderDO.setRefundAmount(saveReqVO.getPayAmount());
//            refundSettlementOrderMapper.updateById(refundSettlementOrderDO);
//
//            ExpensePayOrderDO payOrder = new ExpensePayOrderDO();
//            BeanUtils.copyProperties(saveReqVO, payOrder);
//            payOrder.setExpenseOrderId(refundSettlementOrderDO.getId());
//            payOrder.setType(BusinessConstants.REFUND_EXPENSE_PAY_ORDER);
//            payOrder.setRoundPayAmount(saveReqVO.getPayAmount().setScale(0, RoundingMode.HALF_UP));
//            payOrder.setRoundPayTwoDecimalAmount(saveReqVO.getPayAmount().setScale(2, RoundingMode.HALF_UP));
//            payOrder.setCreatedTime(new Date());
//            payOrder.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
//            expensePayOrderMapper.insert(payOrder);
//
//
//            List<ExpensePayOrderItemDO> items = saveReqVO.getItems();
//            for (ExpensePayOrderItemDO item : items) {
//                item.setPayOrderId(payOrder.getId());
//                item.setCreatedTime(new Date());
//                item.setRoundPayAmount(item.getPayAmount().setScale(0, RoundingMode.HALF_UP));
//                item.setRoundPayTwoDecimalAmount(item.getPayAmount().setScale(2, RoundingMode.HALF_UP));
//                item.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
//                expensePayOrderItemMapper.insert(item);
//            }
//
//
////            List<ExpenseOrderDO> expenseOrderList = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>().eq(ExpenseOrderDO::getElderId, refundSettlementOrderDO.getElderId()));
////            for (ExpenseOrderDO expenseOrderDO : expenseOrderList) {
////                expenseOrderDO.setPayStatus(1);
////                expenseOrderDO.setPayableAmount(expenseOrderDO.getPayableAmount());
//////                expenseOrderDO.setPayType();
////                expenseOrderDO.setPayTime(new Date());
////                expenseOrderDO.setPayeeName(SecurityFrameworkUtils.getLoginUserNickname());
////
////
////                List<ExpenseOrderItemDO> expenseOrderItemDOS = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
////                        .eq(ExpenseOrderItemDO::getExpenseOrderId, expenseOrderDO.getId()));
////
////                for (ExpenseOrderItemDO expenseOrderItemDO : expenseOrderItemDOS) {
////                    expenseOrderItemDO.setPayStatus(1);
////                    expenseOrderItemMapper.updateById(expenseOrderItemDO);
////                }
////                //todo 更新账单实际金额
////                expenseOrderMapper.updateById(expenseOrderDO);
////            }
//
//            for (ExpenseOrderDO order : saveReqVO.getOrders()) {
//                ExpenseOrderDO expenseOrderDO = expenseOrderMapper.selectById(order.getId());
//                expenseOrderDO.setRefundAmount(order.getRefundAmount());
//                expenseOrderDO.setRefundSettlementOrderId(saveReqVO.getRefundSettlementOrderId());
//                if (expenseOrderDO.getPayStatus().equals(BooleanEnum.FALSE.getValue())) {
//                    expenseOrderDO.setPayStatus(1);
//                    expenseOrderDO.setPayableAmount(order.getPayableAmount());
//                    expenseOrderDO.setPayTime(new Date());
//                    expenseOrderDO.setPayeeName(SecurityFrameworkUtils.getLoginUserNickname());
//
//                    List<ExpenseOrderItemDO> expenseOrderItemDOS = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
//                            .eq(ExpenseOrderItemDO::getExpenseOrderId, expenseOrderDO.getId()));
//
//                    for (ExpenseOrderItemDO expenseOrderItemDO : expenseOrderItemDOS) {
//                        expenseOrderItemDO.setPayStatus(1);
//                        expenseOrderItemMapper.updateById(expenseOrderItemDO);
//                    }
//                }
//                expenseOrderMapper.updateById(expenseOrderDO);
//            }
//
//
//            BigDecimal totalAmount = BigDecimal.ZERO;
//            List<RefundSettlementOrderItemDO> refundSettlementOrderItems = saveReqVO.getRefundSettlementOrderItems();
//            for (RefundSettlementOrderItemDO refundSettlementOrderItem : refundSettlementOrderItems) {
//                refundSettlementOrderItemMapper.insert(refundSettlementOrderItem);
//
//                DepositRecordDO record = new DepositRecordDO();
//                record.setType(3);
//                record.setAmount(refundSettlementOrderItem.getActualRefundAmount());
//                record.setElderId(refundSettlementOrderDO.getElderId());
//                record.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
//                record.setCreatedTime(new Date());
//                record.setOrderNo("Y" + RandomUtil.randomNumbers(15));
//                record.setName("退住结算");
//                record.setTenantId(refundSettlementOrderDO.getTenantId());
//                depositRecordMapper.insert(record);
//
//                totalAmount = totalAmount.add(refundSettlementOrderItem.getActualRefundAmount());
//            }
//            DepositDO depositDO = depositMapper.selectOne(new LambdaQueryWrapperX<DepositDO>().eq(DepositDO::getElderId, refundSettlementOrderDO.getElderId()));
//            if (depositDO != null) {
//                BigDecimal amount = depositDO.getAmount();
//                depositDO.setAmount(amount.subtract(totalAmount));
//                depositMapper.updateById(depositDO);
//            }
//
//            notifyMessageSendApi.updateMessageByCodeAndPkMessage(BpmMessageEnum.REFUND_SETTLEMENT_HANDLE.getTemplateCode(), refundSettlementOrderDO.getElderId());
//        }
//    }

    @Override
    public void refundSupplementarySettlement(RefundSupplementarySettlementSaveReqVO saveReqVO) {
        RefundSettlementOrderDO refundSettlementOrderDO = refundSettlementOrderMapper.selectById(saveReqVO.getRefundSettlementOrderId());
        Long elderId = refundSettlementOrderDO.getElderId();


        List<RefundSupplementarySettlementDO> items = saveReqVO.getItems();
        for (RefundSupplementarySettlementDO item : items) {
            if (item.getId() == null) {
                item.setCreatedDate(new Date());
                item.setElderId(elderId);
                item.setRefundSettlementOrderId(saveReqVO.getRefundSettlementOrderId());
                item.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
                refundSupplementarySettlementMapper.insert(item);
            }
        }


    }

    @Override
    public RefundSupplementarySettlementRespVO getRefundSupplementarySettlement(Long refundSettlementOrderId) {
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(refundSettlementOrderId);

        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());


        ElderlyRetreatRecordDO elderlyRetreatRecordDO = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());

        RefundSupplementarySettlementRespVO respVO = new RefundSupplementarySettlementRespVO();
        respVO.setElderName(elderlyInfo.getElderName());
        respVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
        respVO.setRefundSettlementOrderId(refundSettlementOrderId);
        respVO.setRetreatDate(elderlyRetreatRecordDO == null ? null : elderlyRetreatRecordDO.getRetreatDate());
        respVO.setAmount(refundSettlementOrder.getRefundAmount());


        List<RefundSupplementarySettlementDO> items = refundSupplementarySettlementMapper
                .selectList(new LambdaQueryWrapperX<RefundSupplementarySettlementDO>()
                        .eq(RefundSupplementarySettlementDO::getRefundSettlementOrderId, refundSettlementOrderId));
        respVO.setItems(items);
        return respVO;
    }


    /**
     * 获取未生成到账单的日常费用
     *
     * @param elderId          长者ID
     * @param costDeadlineDate 费用截止日期
     * @return 日常费用列表
     */
    private List<ExpenseOrderItemVO> getUnBilledDailyExpenses(Long elderId, LocalDate costDeadlineDate) {
        List<ExpenseOrderItemVO> result = new ArrayList<>();

        // 查询未生成到账单且未缴费的日常费用
        List<DailyExpensesDO> dailyExpensesList = dailyExpensesMapper.selectList(new LambdaQueryWrapperX<DailyExpensesDO>()
                .eq(DailyExpensesDO::getElderId, elderId)
                .eq(DailyExpensesDO::getIsGenerateBill, BooleanEnum.FALSE.getValue())
                .eq(DailyExpensesDO::getStatus, BooleanEnum.FALSE.getValue()));

        for (DailyExpensesDO dailyExpenses : dailyExpensesList) {
            // 过滤掉变更类型的日常费用中单价为0的费用项
            if (dailyExpenses.getType() != null && dailyExpenses.getType() == 2 &&
                    (dailyExpenses.getPrice() == null || dailyExpenses.getPrice().compareTo(BigDecimal.ZERO) == 0)) {
                continue;
            }

            ExpenseOrderItemVO itemVO = new ExpenseOrderItemVO();
            itemVO.setItemName(dailyExpenses.getItemName());
            itemVO.setPrice(dailyExpenses.getPrice() == null ? BigDecimal.ZERO : dailyExpenses.getPrice().setScale(2, RoundingMode.HALF_UP));
            itemVO.setAmount(dailyExpenses.getAmount() == null ? BigDecimal.ZERO : dailyExpenses.getAmount().setScale(2, RoundingMode.HALF_UP));
            itemVO.setCount(dailyExpenses.getCount());
            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
            itemVO.setDailyExpenseType(dailyExpenses.getType());
            LocalDate endDate = dailyExpenses.getEndDate().isAfter(costDeadlineDate) ? costDeadlineDate : dailyExpenses.getEndDate();
            String remark = dailyExpenses.getStartDate() + "至" + endDate + "的" + dailyExpenses.getItemName();
            itemVO.setRemarks(StringUtils.isBlank(dailyExpenses.getRemarks()) ? remark : dailyExpenses.getRemarks());
            itemVO.setItemId(dailyExpenses.getId());
            // 根据费用类型设置天数
            if (dailyExpenses.getType() != null) {
                switch (dailyExpenses.getType()) {
                    case 1: // 日常费用
                        if (dailyExpenses.getCreatedTime() != null) {
                            LocalDate createdDate = dailyExpenses.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                            if (!createdDate.isAfter(costDeadlineDate)) {
                                itemVO.setDays(1);
                            }
                        }
                        break;
                    case 2: // 变更费用
                    case 3: // 外出费用
                        if (dailyExpenses.getStartDate() != null && dailyExpenses.getEndDate() != null) {
                            LocalDate startDate = dailyExpenses.getStartDate();
                            if (!startDate.isAfter(costDeadlineDate) && !endDate.isBefore(startDate)) {
                                long days = ChronoUnit.DAYS.between(startDate, endDate) + 1;
                                itemVO.setDays((int) days);
                            }
                        }
                        break;
                    default:
                        itemVO.setDays(1);
                        break;
                }
            }

            result.add(itemVO);
        }
        return result;
    }

    @Override
    public RefundSettlementOrderRespVO getVirtualRefundSettlementOrder(Long id) {
        // 1. 获取基础信息
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(id);
        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());
        if (elderlyInfo == null) {
            throw new RuntimeException("找不到该长者信息");
        }
        ElderlyRetreatRecordDO elderlyRetreatRecord = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());

        // 2. 构建返回对象基础信息
        RefundSettlementOrderRespVO respVO = buildBasicResponseVO(refundSettlementOrder, elderlyInfo, elderlyRetreatRecord);

        // 3. 组装押金退款单细项
        createdDepositData(elderlyInfo, refundSettlementOrder, respVO);

        // 4. 处理费用项
        processExpenseItems(elderlyInfo, elderlyRetreatRecord, respVO);
        return respVO;
    }

    /**
     * 构建返回对象的基础信息
     */
    private RefundSettlementOrderRespVO buildBasicResponseVO(RefundSettlementOrderDO refundSettlementOrder,
                                                             ElderlyInfoDO elderlyInfo,
                                                             ElderlyRetreatRecordDO elderlyRetreatRecord) {
        RefundSettlementOrderRespVO respVO = new RefundSettlementOrderRespVO();
        respVO.setId(refundSettlementOrder.getId());
        respVO.setOrderNumber(refundSettlementOrder.getOrderNumber());
        respVO.setElderName(elderlyInfo.getElderName());
        respVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
        respVO.setCheckInTime(elderlyInfo.getCheckInTime());
        respVO.setRetreatDate(elderlyRetreatRecord.getRetreatDate());
        respVO.setCostDeadlineDate(elderlyRetreatRecord.getCostDeadlineDate());
        respVO.setSettlementTime(refundSettlementOrder.getSettlementTime() == null ? null : refundSettlementOrder.getSettlementTime());
        respVO.setSettlementPersonName(StringUtils.isBlank(refundSettlementOrder.getSettlementPersonName()) ? null : refundSettlementOrder.getSettlementPersonName());
        return respVO;
    }

    /**
     * 处理费用项
     */
    private void processExpenseItems(ElderlyInfoDO elderlyInfo,
                                     ElderlyRetreatRecordDO elderlyRetreatRecord,
                                     RefundSettlementOrderRespVO respVO) {
        // 获取费用截止日期
        LocalDate costDeadlineDate = respVO.getCostDeadlineDate();
        YearMonth costDeadlineYearMonth = YearMonth.from(costDeadlineDate);

        // 查询所有账单（包括已缴费、未缴费和部分缴费的）
        List<ExpenseOrderDO> allOrders = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getElderId, elderlyInfo.getId()));

        // 创建虚拟账单列表
        List<ExpenseOrderItemVO> virtualBillItems = new ArrayList<>();

        // 计算金额
        BigDecimal totalRefundableAmount = BigDecimal.ZERO;   // 总应退金额
        BigDecimal totalReceivableAmount = BigDecimal.ZERO;   // 总应收金额

        // 处理所有账单中的费用项（包括已支付和未支付的）
        for (ExpenseOrderDO order : allOrders) {
            YearMonth orderYearMonth = YearMonth.from(DateTimeFormatter.ofPattern("yyyy-MM").parse(order.getBillingMonth()));

            // 过滤不需要处理的账单
            if (shouldSkipOrder(order, orderYearMonth, costDeadlineYearMonth, costDeadlineDate)) {
                continue;
            }

            // 补充费用项信息
            List<ExpenseOrderItemDO> expenseOrderItems = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                    .eq(ExpenseOrderItemDO::getExpenseOrderId, order.getId()));

            supplementExpenseItemInfo(expenseOrderItems);

            // 处理每个费用项
            for (ExpenseOrderItemDO item : expenseOrderItems) {
                // 过滤不需要处理的费用项
                if (shouldSkipExpenseItem(item, orderYearMonth, costDeadlineYearMonth, costDeadlineDate)) {
                    continue;
                }

                ExpenseOrderItemVO itemVO = new ExpenseOrderItemVO();

                // 根据长者类型处理费用项
                if (elderlyInfo.getInStatusType() == 2) {
                    // 试住类型的长者处理逻辑
                    processProbationElderlyExpenseItem(item, elderlyInfo, costDeadlineDate, itemVO);
                } else {
                    // 正式入住长者处理逻辑
                    processRegularElderlyExpenseItem(item, elderlyInfo, order, costDeadlineDate, itemVO);
                }

                // 只添加有名称且不被跳过的费用项
                if (StringUtils.isNotBlank(itemVO.getItemName())) {
                    if(itemVO.isSkip() || itemVO.getAmount().compareTo(BigDecimal.ZERO) == 0){
                        continue;
                    }
                    virtualBillItems.add(itemVO);

                    // 计算应收和应退金额
                    if (itemVO.getAmount() != null) {
                        if (itemVO.getAmount().compareTo(BigDecimal.ZERO) < 0) {
                            // 应退金额
                            totalRefundableAmount = totalRefundableAmount.add(itemVO.getAmount().setScale(2, RoundingMode.HALF_UP));
                        } else {
                            // 应收金额
                            totalReceivableAmount = totalReceivableAmount.add(itemVO.getAmount().setScale(2, RoundingMode.HALF_UP));
                        }
                    }
                }
            }
        }

        // 获取未生成到账单的日常费用
        List<ExpenseOrderItemVO> unbilledDailyExpenses = getUnBilledDailyExpenses(elderlyInfo.getId(), costDeadlineDate);
        virtualBillItems.addAll(unbilledDailyExpenses);

        // 计算未生成账单的费用的总金额
        for (ExpenseOrderItemVO itemVO : unbilledDailyExpenses) {
            if (itemVO.getAmount() != null) {
                if (itemVO.getAmount().compareTo(BigDecimal.ZERO) < 0) {
                    // 应退金额
                    totalRefundableAmount = totalRefundableAmount.add(itemVO.getAmount().setScale(2, RoundingMode.HALF_UP));
                } else {
                    // 应收金额
                    totalReceivableAmount = totalReceivableAmount.add(itemVO.getAmount().setScale(2, RoundingMode.HALF_UP));
                }
            }
        }

        // 添加押金信息到费用项中，并计算押金的应退金额
        if (respVO.getRefundSettlementOrderItems() != null) {
            for (RefundSettlementOrderItemDO depositItem : respVO.getRefundSettlementOrderItems()) {
                ExpenseOrderItemVO depositItemVO = new ExpenseOrderItemVO();
                depositItemVO.setItemName(depositItem.getItemName());
                // 押金金额需要取负值，因为押金是应退的
                BigDecimal depositAmount = depositItem.getActualRefundAmount() != null ?
                        depositItem.getActualRefundAmount().negate().setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO;
                depositItemVO.setAmount(depositAmount);
                depositItemVO.setPrice(depositAmount);
                depositItemVO.setCount(1);
                depositItemVO.setIsDeposit(1);
                depositItemVO.setRemarks("押金退款");

                virtualBillItems.add(depositItemVO);

                // 押金作为应退金额处理（depositAmount已经是负数，所以直接加）
                if (depositItem.getActualRefundAmount() != null) {
                    totalRefundableAmount = totalRefundableAmount.add(depositAmount);
                }
            }
        }

        // 创建一个虚拟账单对象来包装所有费用项
        ExpenseOrderVO virtualOrder = new ExpenseOrderVO();
        virtualOrder.setOrderItems(virtualBillItems);
        virtualOrder.setReceivableAmount(totalReceivableAmount.setScale(2, RoundingMode.HALF_UP));
        virtualOrder.setRefundableAmount(totalRefundableAmount.setScale(2, RoundingMode.HALF_UP));
        virtualOrder.setOrderAmount(totalReceivableAmount.add(totalRefundableAmount).setScale(2, RoundingMode.HALF_UP));
        virtualOrder.setBillingMonth("虚拟账单");
        virtualOrder.setPayStatus(BooleanEnum.FALSE.getValue());

        // 设置返回结果
        respVO.setOrders(Collections.singletonList(virtualOrder));
    }

    /**
     * 判断是否应该跳过处理某个账单
     */
    private boolean shouldSkipOrder(ExpenseOrderDO order, YearMonth orderYearMonth, YearMonth costDeadlineYearMonth, LocalDate costDeadlineDate) {
        // 过滤掉已完全缴纳且不在退住月份内的账单
        if (order.getPayStatus().equals(BooleanEnum.TRUE.getValue())
                && orderYearMonth.isBefore(costDeadlineYearMonth)) {
            // 如果账单已经完全缴纳且账单月份不在退住月份，则跳过整个账单
            return true;
        }

        // 如果账单未缴费且月份在退住日期之前，则检查是否有未缴费的费用项
        if (order.getPayStatus().equals(BooleanEnum.FALSE.getValue())
                && orderYearMonth.isBefore(costDeadlineYearMonth)) {
            // 检查是否有未缴费的费用项
            List<ExpenseOrderItemDO> unpaidItems = expenseOrderItemMapper.selectList(
                    new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                            .eq(ExpenseOrderItemDO::getExpenseOrderId, order.getId())
                            .eq(ExpenseOrderItemDO::getPayStatus, BooleanEnum.FALSE.getValue()));

            if (unpaidItems.isEmpty()) {
                // 没有未缴费的费用项，跳过整个账单
                return true;
            }
        }

        // 对于退住当月且完整居住的情况，过滤掉账单
        if (orderYearMonth.equals(costDeadlineYearMonth)) {
            // 检查是否为完整居住一个月（退住在月末）
            LocalDate firstDayOfMonth = costDeadlineDate.with(TemporalAdjusters.firstDayOfMonth());
            LocalDate lastDayOfMonth = costDeadlineDate.with(TemporalAdjusters.lastDayOfMonth());
            if (!costDeadlineDate.isBefore(firstDayOfMonth) && !costDeadlineDate.isBefore(lastDayOfMonth)
                    && costDeadlineDate.equals(lastDayOfMonth)) {
                // 退住日期在月末，视为完整居住一个月
                if (order.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
                    // 已缴费且完整居住，跳过整个账单
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 补充费用项信息
     */
    private void supplementExpenseItemInfo(List<ExpenseOrderItemDO> expenseOrderItems) {
        for (ExpenseOrderItemDO expenseOrderItem : expenseOrderItems) {
            if (expenseOrderItem.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                ExpenseItemDO expenseItemDO = expenseItemMapper.selectById(expenseOrderItem.getSourceExpenseItemId());
                if (expenseItemDO != null) {
                    expenseOrderItem.setIsMonthlyExpense(expenseItemDO.getIsMonthlyExpense());
                    expenseOrderItem.setIsOneTimeFee(expenseItemDO.getIsOneTimeFee());
                }
            }
        }
    }

    /**
     * 判断是否应该跳过处理某个费用项
     */
    private boolean shouldSkipExpenseItem(ExpenseOrderItemDO item, YearMonth orderYearMonth, YearMonth costDeadlineYearMonth, LocalDate costDeadlineDate) {
        if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
            return false;
        }
        // 如果是变更类型的日常费用但单价为0，则过滤掉
        if (item.getExpenseSource().equals(BusinessConstants.DAILY_EXPENSES)) {
            DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(item.getSourceExpenseItemId());
            if (dailyExpenses != null && dailyExpenses.getType() != null &&
                    dailyExpenses.getType() == 2 && // 变更类型
                    (dailyExpenses.getPrice() == null || dailyExpenses.getPrice().compareTo(BigDecimal.ZERO) == 0)) {
                return true; // 过滤掉单价为0的变更类型费用
            }
        }

        // 对于退住之后月份的账单，仅处理日常费用，跳过未缴费的固定月费，但需要处理已缴费的固定月费（生成退款）
        if (orderYearMonth.isAfter(costDeadlineYearMonth) || orderYearMonth.equals(costDeadlineYearMonth)) {
            // 检查是否为固定月费
            boolean isMonthlyExpense = false;
            if (item.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
                ExpenseItemDO expenseItem = expenseItemMapper.selectById(item.getSourceExpenseItemId());
                if (expenseItem != null && expenseItem.getIsMonthlyExpense() != null
                        && expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
                    isMonthlyExpense = true;
                }
            }

            // 如果是固定月费
            if (isMonthlyExpense) {
                return item.getStartDate() != null && item.getStartDate().isAfter(costDeadlineDate);
            }
        }

        return false;
    }

    /**
     * 处理试住类型长者的费用项
     */
    private void processProbationElderlyExpenseItem(ExpenseOrderItemDO item,
                                                    ElderlyInfoDO elderlyInfo,
                                                    LocalDate costDeadlineDate,
                                                    ExpenseOrderItemVO itemVO) {
        if (item.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
            ExpenseItemDO expenseItem = expenseItemMapper.selectById(item.getSourceExpenseItemId());
            if (expenseItem != null && expenseItem.getIsDeposit() != null
                    && expenseItem.getIsDeposit().equals(BooleanEnum.FALSE.getValue())) {
                // 获取试住合同信息
                ElderlyContractDO elderlyContract = elderlyContractMapper.selectOne(
                        new LambdaQueryWrapperX<ElderlyContractDO>()
                                .eq(ElderlyContractDO::getElderId, elderlyInfo.getId()));

                if (elderlyContract != null) {
                    LocalDate beginDate = elderlyContract.getBeginTime().toInstant()
                            .atZone(ZoneId.systemDefault()).toLocalDate();
                    LocalDate expireDate = elderlyContract.getExpireTime().toInstant()
                            .atZone(ZoneId.systemDefault()).toLocalDate();

                    // 合同天数
                    long contractDays = ChronoUnit.DAYS.between(beginDate, expireDate) + 1;

                    // 日价
                    BigDecimal dayPrice = expenseItem.getTotalAmount()
                            .divide(BigDecimal.valueOf(contractDays), 8, RoundingMode.DOWN);

                    // 实际居住天数（从合同开始日期到退住日期）
                    long actualStayDays = ChronoUnit.DAYS.between(beginDate, costDeadlineDate) + 1;

                    // 已住金额
                    BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(actualStayDays));

                    // 应退天数（合同总天数 - 实际居住天数）
                    long refundDays = contractDays - actualStayDays;

                    // 应退金额
                    BigDecimal refundAmount = dayPrice.multiply(BigDecimal.valueOf(refundDays));
                    itemVO.setPrice(expenseItem.getActualAmount());
                    itemVO.setItemName(expenseItem.getItemName());
                    itemVO.setCount(1);
                    itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
                    itemVO.setItemId(item.getSourceExpenseItemId());
                    // 根据账单缴费状态处理
                    if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
                        // 已缴费账单
                        itemVO.setAmount(amount);

                        // 如果实际居住天数少于合同天数，则有应退金额
                        if (actualStayDays < contractDays) {
                            // 应退金额设为负值表示退款
                            BigDecimal finalRefundAmount = refundAmount.negate();
                            itemVO.setAmount(finalRefundAmount);
                            itemVO.setRemarks("住" + beginDate + "到" + costDeadlineDate + "共" + actualStayDays +
                                    "天，应收" + amount + "元；未住" + refundDays + "天，应退" + refundAmount + "元");
                        } else {
                            // 全部居住，无退款
                            itemVO.setRemarks("住" + beginDate + "到" + costDeadlineDate + "共" + actualStayDays + "天，应收" + amount + "元");
                        }
                    } else if (item.getPayStatus().equals(BooleanEnum.FALSE.getValue())) {
                        // 未缴费账单
                        itemVO.setAmount(amount);
                        itemVO.setRemarks("住" + beginDate + "到" + costDeadlineDate + "共" + actualStayDays + "天，应收" + amount + "元");
                    }
                }
            }
        }
    }

    /**
     * 处理正式入住长者的费用项
     */
    private void processRegularElderlyExpenseItem(ExpenseOrderItemDO item,
                                                  ElderlyInfoDO elderlyInfo,
                                                  ExpenseOrderDO order,
                                                  LocalDate costDeadlineDate,
                                                  ExpenseOrderItemVO itemVO) {
        if (item.getExpenseSource().equals(BusinessConstants.EXPENSE_ITEM)) {
            // 处理费用项
            ExpenseItemDO expenseItem = expenseItemMapper.selectById(item.getSourceExpenseItemId());
            if (expenseItem != null) {
                itemVO.setItemName(expenseItem.getItemName());
                itemVO.setIsMonthlyExpense(expenseItem.getIsMonthlyExpense());
                itemVO.setIsOneTimeFee(expenseItem.getIsOneTimeFee());
                itemVO.setItemId(item.getSourceExpenseItemId());

//                if (order.getType() == 1) {
//                    // 入院账单
//                    processAdmissionBill(item, expenseItem, elderlyInfo, costDeadlineDate, itemVO);
//                } else {
//                    // 月度账单
//                    processMonthlyBill(item, expenseItem, order, costDeadlineDate, itemVO);
//                }
                // 月度账单
                processMonthlyBill(item, expenseItem, order, costDeadlineDate, itemVO);
            }
        } else {
            // 处理长护险和其他费用
            processOtherExpenses(elderlyInfo.getId(),item, costDeadlineDate, itemVO);
        }
    }

    /**
     * 处理入院账单
     */
    private void processAdmissionBill(ExpenseOrderItemDO item,
                                      ExpenseItemDO expenseItem,
                                      ElderlyInfoDO elderlyInfo,
                                      LocalDate costDeadlineDate,
                                      ExpenseOrderItemVO itemVO) {
        itemVO.setPrice(item.getPrice());
        itemVO.setAmount(item.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
        itemVO.setCount(item.getCount());

        if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
            // 月度费用需要计算实际天数
            processMonthlyExpenseForAdmission(item, expenseItem, elderlyInfo, costDeadlineDate, itemVO);
        } else if (expenseItem.getIsFreeGift() != null && expenseItem.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
            // 赠送费用
            processFreeGiftExpense(expenseItem, item, itemVO);
        } else {
            // 其他一次性费用
            processOneTimeExpense(item, itemVO);
        }
    }

    /**
     * 处理月度账单
     */
    private void processMonthlyBill(ExpenseOrderItemDO item,
                                    ExpenseItemDO expenseItem,
                                    ExpenseOrderDO order,
                                    LocalDate costDeadlineDate,
                                    ExpenseOrderItemVO itemVO) {
        itemVO.setPrice(item.getPrice());
        itemVO.setAmount(item.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
        itemVO.setCount(item.getCount());

        if (expenseItem.getIsMonthlyExpense().equals(BooleanEnum.TRUE.getValue())) {
            // 月度费用需要计算实际天数（按当月第一天开始计算）
            processMonthlyExpenseForMonthlyBill(item, expenseItem, order, costDeadlineDate, itemVO);
        } else if (expenseItem.getIsFreeGift() != null && expenseItem.getIsFreeGift().equals(BooleanEnum.TRUE.getValue())) {
            // 赠送费用
            processFreeGiftExpense(expenseItem, item, itemVO);
        } else {
            // 其他费用
            processOtherExpense(item, itemVO);
        }
    }

    /**
     * 处理月度费用（入院账单）
     */
    private void processMonthlyExpenseForAdmission(ExpenseOrderItemDO item,
                                                   ExpenseItemDO expenseItem,
                                                   ElderlyInfoDO elderlyInfo,
                                                   LocalDate costDeadlineDate,
                                                   ExpenseOrderItemVO itemVO) {
        LocalDate checkInDate = elderlyInfo.getCheckInTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        LocalDate calcEndDate = costDeadlineDate.isBefore(checkInDate) ? checkInDate : costDeadlineDate;

        // 只有当退住日期在入住日期所在月份内时才计算费用
        YearMonth checkInYearMonth = YearMonth.from(checkInDate);
        YearMonth costDeadlineYearMonthLocal = YearMonth.from(costDeadlineDate);

        if (costDeadlineYearMonthLocal.equals(checkInYearMonth)) {
            // 退住日期在入住月份内
            processCheckInMonthExpense(item, checkInDate, calcEndDate, itemVO);
        } else if (costDeadlineYearMonthLocal.isAfter(checkInYearMonth)) {
            // 退住日期在入住月份之后，计算整月费用
            processPostCheckInMonthExpense(item, checkInDate, itemVO);
        } else {
            // 退住日期在入住日期之前，不计算费用
            processPreCheckInMonthExpense(item, itemVO);
        }
    }

    /**
     * 处理月度费用（月度账单）
     */
    private void processMonthlyExpenseForMonthlyBill(ExpenseOrderItemDO item,
                                                     ExpenseItemDO expenseItem,
                                                     ExpenseOrderDO order,
                                                     LocalDate costDeadlineDate,
                                                     ExpenseOrderItemVO itemVO) {
        String orderMonth = order.getBillingMonth();
        YearMonth orderYearMonthParsed = YearMonth.from(DateTimeFormatter.ofPattern("yyyy-MM").parse(orderMonth));
        LocalDate firstDayDate = orderYearMonthParsed.atDay(1);

        // 处理startDate为null的情况
        LocalDate itemStartDate = item.getStartDate();
        LocalDate beginDate = (itemStartDate != null && firstDayDate.isAfter(itemStartDate)) ? firstDayDate :
                (itemStartDate != null ? itemStartDate : firstDayDate);

        LocalDate lastMonthDayDate = orderYearMonthParsed.atEndOfMonth();
        // 获取结束日期并不是费用截止日期
        LocalDate endDayDate = bizUtil.getEndDateWithExpireDate(order.getElderId(),item.getContractId(),lastMonthDayDate,item.getEndDate() != null ? item.getEndDate() : lastMonthDayDate);
        // 确保计算日期在账单月内
        if (costDeadlineDate.getYear() == orderYearMonthParsed.getYear() &&
                costDeadlineDate.getMonthValue() == orderYearMonthParsed.getMonthValue()) {
            // 当月退住需要计算实际天数
            processCurrentMonthExpense(item, beginDate,endDayDate, itemVO,costDeadlineDate);
        } else if (costDeadlineDate.isBefore(beginDate)) {
            // 退住日期在账单月之前，不计算费用
            processPreMonthExpense(item, beginDate, itemVO);
        } else if (orderYearMonthParsed.isBefore(YearMonth.from(costDeadlineDate))) {
            // 账单月在退住日期之前，计算整月费用
            processPastMonthExpense(item, beginDate, endDayDate, itemVO);
        }
    }

    /**
     * 处理赠送费用
     */
    private void processFreeGiftExpense(ExpenseItemDO expenseItem, ExpenseOrderItemDO item, ExpenseOrderItemVO itemVO) {
        long monthBetween = ChronoUnit.MONTHS.between(
                expenseItem.getFreeStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate(),
                expenseItem.getFreeEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
        itemVO.setRemarks("赠送" + monthBetween + "个月" + item.getItemName());
        itemVO.setItemId(item.getSourceExpenseItemId());
        // 如果账单已支付，赠送费用不需要退费
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); // amount为应退金额（0元）
            itemVO.setRemarks("赠送" + monthBetween + "个月" + item.getItemName() + "（无需退费）");
        }
    }

    /**
     * 处理一次性费用
     */
    private void processOneTimeExpense(ExpenseOrderItemDO item, ExpenseOrderItemVO itemVO) {
        itemVO.setCount(item.getCount());
        itemVO.setPrice(item.getActualPrice().setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(item.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
        itemVO.setItemId(item.getSourceExpenseItemId());
        // 如果账单已支付，一次性费用不需要退费
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); // amount为应退金额（0元）
            itemVO.setRemarks(item.getItemName() + "（无需退费）");
        }
    }

    /**
     * 处理其他费用
     */
    private void processOtherExpense(ExpenseOrderItemDO item, ExpenseOrderItemVO itemVO) {
        itemVO.setCount(item.getCount());
        itemVO.setPrice(item.getActualPrice().setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(item.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
        // 如果账单已支付，其他费用不需要退费
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); // amount为应退金额（0元）
            itemVO.setRemarks(item.getItemName() + "（无需退费）");
        }
    }

    /**
     * 处理入住当月的费用
     */
    private void processCheckInMonthExpense(ExpenseOrderItemDO item, LocalDate checkInDate, LocalDate calcEndDate, ExpenseOrderItemVO itemVO) {
        if (!checkInDate.isAfter(calcEndDate)) {
            long stayDay = ChronoUnit.DAYS.between(checkInDate, calcEndDate) + 1;
            BigDecimal dayPrice = item.getPrice().divide(BigDecimal.valueOf(checkInDate.lengthOfMonth()), 8, RoundingMode.DOWN);
            BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);

            itemVO.setDays((int) stayDay);
            itemVO.setPrice(dayPrice.setScale(2, RoundingMode.HALF_UP));
            itemVO.setAmount(amount);
            itemVO.setRemarks("收" + checkInDate + "到" + calcEndDate + "共" + stayDay + "天的费用");
            // 如果账单已支付，需要计算应退金额
            if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
                // 已支付的账单需要计算应退金额
                BigDecimal totalAmount = item.getTotalAmount();
                BigDecimal refundAmount = totalAmount.subtract(amount).setScale(2, RoundingMode.HALF_UP);
                itemVO.setAmount(refundAmount.negate()); // amount为应退金额（负数）
                itemVO.setRemarks("退费区间：" + checkInDate + "到" + calcEndDate + "共" + stayDay + "天的费用");
            }
        }
    }

    /**
     * 处理入住后月份的费用
     */
    private void processPostCheckInMonthExpense(ExpenseOrderItemDO item, LocalDate checkInDate, ExpenseOrderItemVO itemVO) {
        long stayDay = ChronoUnit.DAYS.between(checkInDate,checkInDate.with(TemporalAdjusters.lastDayOfMonth()))+1;
        BigDecimal dayPrice = item.getPrice().divide(BigDecimal.valueOf(checkInDate.lengthOfMonth()), 8, RoundingMode.DOWN);
        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);

        itemVO.setDays((int) stayDay);
        itemVO.setPrice(dayPrice.setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(amount);
        itemVO.setRemarks("收" + checkInDate + "到" + checkInDate.with(TemporalAdjusters.lastDayOfMonth()) + "共" + stayDay + "天的费用");
        // 如果账单已支付，不需要退费
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); // amount为应退金额（0元）
            itemVO.setRemarks("退费区间：" + checkInDate + "到" + checkInDate.with(TemporalAdjusters.lastDayOfMonth()) + "共" + stayDay + "天的费用（无需退费）");
        }
    }

    /**
     * 处理入住前月份的费用
     */
    private void processPreCheckInMonthExpense(ExpenseOrderItemDO item, ExpenseOrderItemVO itemVO) {
        itemVO.setDays(0);
        itemVO.setPrice(item.getPrice().setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        itemVO.setRemarks("退住日期在入住日期之前，不计算费用");
        // 如果账单已支付，需要全额退款
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            BigDecimal refundAmount = item.getTotalAmount().setScale(2, RoundingMode.HALF_UP);
            itemVO.setAmount(refundAmount.negate()); // amount为应退金额（负数）
            itemVO.setRemarks("退费区间："+item.getStartDate()+"至"+item.getEndDate()+"全额退款");
        }
    }

    /**
     * 处理当前月份费用（退住当月）
     */
    private void processCurrentMonthExpense(ExpenseOrderItemDO item, LocalDate firstDayDate,
                                            LocalDate endDayDate, ExpenseOrderItemVO itemVO,LocalDate costDeadlineDate) {
        LocalDate calEndDate = Collections.min(Arrays.asList(endDayDate, costDeadlineDate));
        // 获取计费天数
        long stayDay = firstDayDate.isAfter(calEndDate) ? 0 : ChronoUnit.DAYS.between(firstDayDate, calEndDate) + 1;
        int daysInMonth = firstDayDate.lengthOfMonth();
        BigDecimal dayPrice = item.getPrice().divide(BigDecimal.valueOf(daysInMonth), 8, RoundingMode.DOWN);
        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);

        itemVO.setDays((int) stayDay);
        itemVO.setPrice(dayPrice.setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(amount);
        itemVO.setRemarks("收" + firstDayDate + "到" + endDayDate + "共" + stayDay + "天的费用");
        // 如果账单已支付，需要计算应退金额
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            // 修正退费天数计算逻辑：从退住日期的下一天开始计算
            LocalDate refundStartDate = firstDayDate.isAfter(costDeadlineDate) ? firstDayDate : costDeadlineDate.plusDays(1);
            long refundDays = ChronoUnit.DAYS.between(refundStartDate, endDayDate) + 1;
            // 已支付的账单需要计算应退金额
            BigDecimal totalAmount = item.getTotalAmount();
            BigDecimal refundAmount = totalAmount.subtract(amount).setScale(2, RoundingMode.HALF_UP);
            // 处理特殊情况：如果退费开始日期超过了结束日期，则退费天数为0
            if (!refundStartDate.isAfter(endDayDate)) {
                if(endDayDate.equals(costDeadlineDate)){
                    itemVO.setRemarks("退费区间：无退费（已居住至合同到期）");
                    itemVO.setAmount(BigDecimal.ZERO);
                }else {
                    itemVO.setAmount(refundAmount.negate()); // amount为应退金额（负数）
                    itemVO.setRemarks("退费区间：" + refundStartDate + "到" + endDayDate + "共" + refundDays + "天的费用");
                }
            } else {
                itemVO.setAmount(BigDecimal.ZERO);
                itemVO.setRemarks("退费区间：无退费（已居住至费用结束日期）");
            }
        }
    }

    /**
     * 处理退住前月份的费用
     */
    private void processPreMonthExpense(ExpenseOrderItemDO item, LocalDate firstDayDate, ExpenseOrderItemVO itemVO) {
        itemVO.setDays(0);
        itemVO.setPrice(item.getPrice().setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        itemVO.setRemarks("退住日期在账单月之前，不计算费用");
        // 如果账单已支付，需要全额退款
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            BigDecimal refundAmount = item.getTotalAmount().setScale(2, RoundingMode.HALF_UP);
            itemVO.setAmount(refundAmount.negate()); // amount为应退金额（负数）
            itemVO.setRemarks("退费区间："+item.getStartDate()+"至"+item.getEndDate()+"全额退款");
        }
    }

    /**
     * 处理过去的月份费用
     */
    private void processPastMonthExpense(ExpenseOrderItemDO item, LocalDate beginDate, LocalDate endDayDate, ExpenseOrderItemVO itemVO) {
        long stayDay = ChronoUnit.DAYS.between(beginDate,endDayDate) + 1;
        BigDecimal dayPrice = item.getPrice().divide(BigDecimal.valueOf(beginDate.lengthOfMonth()), 8, RoundingMode.DOWN);
        BigDecimal amount = dayPrice.multiply(BigDecimal.valueOf(stayDay)).setScale(2, RoundingMode.HALF_UP);

        itemVO.setDays((int) stayDay);
        itemVO.setPrice(dayPrice.setScale(2, RoundingMode.HALF_UP));
        itemVO.setAmount(amount);
        itemVO.setRemarks("收" + beginDate + "到" + endDayDate + "共" + stayDay + "天的费用");
        // 如果账单已支付，不需要退费
        if (item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP)); // amount为应退金额（0元）
            itemVO.setRemarks("退费区间：" + beginDate + "到" + endDayDate + "共" + stayDay + "天的费用（无需退费）");
        }
    }

    /**
     * 处理其他费用（如长护险、消费券、日常费用等）
     */
    private void processOtherExpenses(Long elderId,ExpenseOrderItemDO item, LocalDate costDeadlineDate, ExpenseOrderItemVO itemVO) {
        YearMonth costDeadlineYearMonth = YearMonth.from(costDeadlineDate);
        if(StringUtils.isNotBlank(item.getExpenseSource()) && item.getExpenseSource().equals("consumer_voucher")){
            if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
                return;
            }
            ElderlyConsumerVouchersDO voucher = elderlyConsumerVouchersMapper.selectById(item.getSourceExpenseItemId());
            itemVO.setAmount(voucher.getAmount());
            itemVO.setPrice(voucher.getAmount());
            itemVO.setRemarks(voucher.getRemarks());
            itemVO.setItemId(voucher.getId());
            return;
        }
        // 处理长护险
        if (((item.getItemCategoryName() != null && item.getItemCategoryName().contains("长护险")) || (item.getItemName() != null && item.getItemName().contains("长护险")))) {
            itemVO.setItemName("长护险");
            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
            itemVO.setDailyExpenseType(4);
            itemVO.setCount(1);
            LocalDate endDate = bizUtil.getEndDateWithExpireDate(elderId,item.getContractId(),costDeadlineDate.with(TemporalAdjusters.lastDayOfMonth()));
            // 根据是否缴费来确定正负，若未缴费，那么需要抵扣长护险就是负，天数为月初到截止日期，如果已缴费那么就是收回长护险是正，天数为费用截止日期到月末
            long calDay = item.getPayStatus().equals(BooleanEnum.FALSE.getValue()) ?
                    -(ChronoUnit.DAYS.between(costDeadlineDate.withDayOfMonth(1),costDeadlineDate)) :
                    ChronoUnit.DAYS.between(costDeadlineDate,endDate);
            BigDecimal daysOfMonth = new BigDecimal(Math.abs(ChronoUnit.DAYS.between(costDeadlineDate.withDayOfMonth(1),endDate))).add(BigDecimal.ONE);
            ExpenseSubsidyDO expenseSubsidyDO = expenseSubsidyMapper.selectById(item.getSourceExpenseItemId());
            // 长护险补充备注
            String subsidyRemarks = calDay > 0 ? ";收回" + calDay + "天的长护险" : ";抵扣" + (-calDay) + "天的长护险";
            if (expenseSubsidyDO != null) {
                YearMonth yearMonth = YearMonth.parse(expenseSubsidyDO.getMonth());
                if(yearMonth.isAfter(costDeadlineYearMonth)){
                    itemVO.setSkip(true);
                }
                YearMonth decutionBillYearMonth = YearMonth.parse(expenseSubsidyDO.getDeductionBillMonth());
                if(decutionBillYearMonth.isAfter(costDeadlineYearMonth)){
                    if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
                        BigDecimal subsidyAmount = expenseSubsidyDO.getAmount() == null ? BigDecimal.ZERO : expenseSubsidyDO.getAmount();
                        itemVO.setAmount(subsidyAmount);
                        itemVO.setPrice(expenseSubsidyDO.getAmount().negate());
                        itemVO.setRemarks(subsidyAmount.compareTo(BigDecimal.ZERO) > 0 ? "全额收回" + expenseSubsidyDO.getDeductionBillMonth() + "长护险" : "抵扣" + expenseSubsidyDO.getDeductionBillMonth() + "长护险");
                        itemVO.setItemId(expenseSubsidyDO.getId());
                    }
                }else {
                    BigDecimal subsidyAmount = expenseSubsidyDO.getAmount() == null ? BigDecimal.ZERO : expenseSubsidyDO.getAmount();
                    // 计算长护险单日费用
                    BigDecimal dayPrice = subsidyAmount.divide(daysOfMonth, RoundingMode.HALF_UP);
                    itemVO.setAmount(dayPrice.multiply(new BigDecimal(calDay)));
                    itemVO.setPrice(expenseSubsidyDO.getAmount().negate());
                    itemVO.setRemarks(expenseSubsidyDO.getRemarks() + subsidyRemarks);
                    itemVO.setItemId(expenseSubsidyDO.getId());
                }
            } else {    // 长护险录入成了日常费用
                DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(item.getSourceExpenseItemId());
                if(dailyExpenses.getEndDate().isBefore(costDeadlineDate)){
                    itemVO.setSkip(true);
                }
                BigDecimal subsidyAmount = dailyExpenses.getAmount() == null ? BigDecimal.ZERO : dailyExpenses.getAmount();
                YearMonth attributionYearMonth = YearMonth.parse(dailyExpenses.getAttributionBillTime());
                if(attributionYearMonth.isAfter(costDeadlineYearMonth)){
                    if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
                        itemVO.setAmount(subsidyAmount);
                        itemVO.setPrice(subsidyAmount.negate());
                        itemVO.setRemarks(subsidyAmount.compareTo(BigDecimal.ZERO) > 0 ? "全额收回" + dailyExpenses.getAttributionBillTime() + "长护险" : "抵扣" + dailyExpenses.getAttributionBillTime() + "长护险");
                        itemVO.setItemId(dailyExpenses.getId());
                    }
                }else {
                    // 计算长护险单日费用
                    BigDecimal dayPrice = subsidyAmount.divide(daysOfMonth, RoundingMode.HALF_UP);
                    itemVO.setAmount(dayPrice.multiply(new BigDecimal(calDay)));
                    itemVO.setPrice(subsidyAmount);
                    itemVO.setRemarks(dailyExpenses.getRemarks() + subsidyRemarks);
                    itemVO.setItemId(dailyExpenses.getId());
                }
            }
        } else {
            // 处理日常费用
            processDailyExpenses(item, costDeadlineDate, itemVO);
        }
    }

    /**
     * 处理日常费用
     */
    private void processDailyExpenses(ExpenseOrderItemDO item, LocalDate costDeadlineDate, ExpenseOrderItemVO itemVO) {
        DailyExpensesDO dailyExpenses = dailyExpensesMapper.selectById(item.getSourceExpenseItemId());
        if (dailyExpenses != null) {
            itemVO.setItemName(dailyExpenses.getItemName());
            itemVO.setPrice(dailyExpenses.getPrice() == null ? BigDecimal.ZERO : dailyExpenses.getPrice().setScale(2, RoundingMode.HALF_UP));
            itemVO.setAmount(dailyExpenses.getAmount() == null ? BigDecimal.ZERO : dailyExpenses.getAmount().setScale(2, RoundingMode.HALF_UP));
            itemVO.setCount(dailyExpenses.getCount());
            itemVO.setIsMonthlyExpense(BooleanEnum.FALSE.getValue());
            itemVO.setDailyExpenseType(dailyExpenses.getType());
            LocalDate endDate = dailyExpenses.getEndDate().isAfter(costDeadlineDate) ? costDeadlineDate : dailyExpenses.getEndDate();
            String remark = dailyExpenses.getStartDate() + "至" + endDate + "的" + dailyExpenses.getItemName();
            itemVO.setRemarks(StringUtils.isBlank(dailyExpenses.getRemarks()) ? remark : dailyExpenses.getRemarks());
            itemVO.setItemId(dailyExpenses.getId());

            // 根据费用类型设置天数
            if (dailyExpenses.getType() != null) {
                switch (dailyExpenses.getType()) {
                    case 1: // 日常费用
                        processRegularDailyExpense(item,dailyExpenses, costDeadlineDate, itemVO);
                        break;
                    case 2: // 变更费用
                        processChangeExpense(item,dailyExpenses, costDeadlineDate, itemVO);
                        break;
                    case 3: // 外出费用
                        processChangeOrOutgoingExpense(dailyExpenses, costDeadlineDate, itemVO);
                        break;
                    default:
                        itemVO.setDays(1);
                        break;
                }
            }
            itemVO.setSkip(itemVO.getAmount().compareTo(BigDecimal.ZERO) == 0);
        }
    }

    /**
     * 处理常规日常费用
     */
    private void processRegularDailyExpense(ExpenseOrderItemDO item,DailyExpensesDO dailyExpenses, LocalDate costDeadlineDate, ExpenseOrderItemVO itemVO) {
        if (dailyExpenses.getCreatedTime() != null) {
            LocalDate createdDate = dailyExpenses.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            if (!createdDate.isAfter(costDeadlineDate)) {
                itemVO.setDays(1);
            } else {
                // 费用创建日期在退住日期之后，设置为1天（仍需显示但不收费）
                itemVO.setDays(1);
            }
        }
        if (item.getPayStatus() != null && item.getPayStatus().equals(BooleanEnum.TRUE.getValue())) {
            // 已支付的应收项目设置为0
            itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
        }
    }

    /**
     * 处理变更费用
     */
    private void processChangeExpense(ExpenseOrderItemDO item,DailyExpensesDO dailyExpenses, LocalDate costDeadlineDate, ExpenseOrderItemVO itemVO){
        if (dailyExpenses.getStartDate() != null && dailyExpenses.getEndDate() != null) {
            LocalDate startDate = dailyExpenses.getStartDate();
            LocalDate endDate = dailyExpenses.getEndDate().isAfter(costDeadlineDate) ? costDeadlineDate : dailyExpenses.getEndDate();
            if (startDate.isBefore(costDeadlineDate) && endDate.isAfter(startDate)) {
                // 退费的单日费用
                BigDecimal price = dailyExpenses.getAmount().divide(new BigDecimal(Math.abs(ChronoUnit.DAYS.between(dailyExpenses.getStartDate(),dailyExpenses.getEndDate()))+1),RoundingMode.HALF_UP);
                if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
                    // 费用已缴，那么需要处理的部分为费用截止日期到合同结束日期或月末
                    long days = Math.abs(ChronoUnit.DAYS.between(costDeadlineDate, dailyExpenses.getEndDate()));
                    itemVO.setDays((int) days);
                    itemVO.setAmount(price.multiply(new BigDecimal(days)).negate());
                    // 添加退费区间备注
                    String preRemarks = itemVO.getAmount().compareTo(BigDecimal.ZERO) > 0 ? "变更缴费:长者变更,缴" : "变更退费:长者变更,退";
                    itemVO.setRemarks(preRemarks + costDeadlineDate + "到" +  dailyExpenses.getEndDate() + "的费用(" +
                            startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")) + "月份共" + days + "天)");
                }else {
                    // 费用未缴，那么需要处理的部分为开始日期到费用截止日期
                    long days = Math.abs(ChronoUnit.DAYS.between(startDate, endDate)) + 1;
                    itemVO.setDays((int) days);
                    itemVO.setAmount(price.multiply(new BigDecimal(days)));
                    // 添加退费区间备注
                    String preRemarks = itemVO.getAmount().compareTo(BigDecimal.ZERO) > 0 ? "变更缴费:长者变更,缴" : "变更退费:长者变更,退";
                    itemVO.setRemarks(preRemarks + startDate + "到" + endDate + "的费用(" +
                            startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")) + "月份共" + days + "天)");
                }
            } else if (startDate.isAfter(costDeadlineDate)) {   // 开始日期大于截止日期
                if(item.getPayStatus().equals(BooleanEnum.TRUE.getValue())){
                    // 已缴费那么全额退回
                    long days = Math.abs(ChronoUnit.DAYS.between(dailyExpenses.getStartDate(), dailyExpenses.getEndDate())) + 1;
                    itemVO.setAmount(dailyExpenses.getAmount());
                    itemVO.setDays((int) days);
                    itemVO.setRemarks("变更退费:长者变更,退" + dailyExpenses.getStartDate() + "到" +  dailyExpenses.getEndDate() + "的费用(" +
                            startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")) + "月份共" + days + "天)");
                }else {
                    // 未缴费则无需缴费
                    itemVO.setDays(0);
                    itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
                    itemVO.setRemarks("费用开始日期在退住日期之后，无需缴费");
                }
            }
        }
    }
    /**
     * 处理外出费用
     */
    private void processChangeOrOutgoingExpense(DailyExpensesDO dailyExpenses, LocalDate costDeadlineDate, ExpenseOrderItemVO itemVO) {
        if (dailyExpenses.getStartDate() != null && dailyExpenses.getEndDate() != null) {
            LocalDate startDate = dailyExpenses.getStartDate();
            LocalDate endDate = dailyExpenses.getEndDate().isAfter(costDeadlineDate) ? costDeadlineDate : dailyExpenses.getEndDate();
            if (startDate.isBefore(costDeadlineDate) && endDate.isAfter(startDate)) {
                long days = ChronoUnit.DAYS.between(startDate, endDate) + 1;
                itemVO.setDays((int) days);
                // 添加退费区间备注
                itemVO.setRemarks(dailyExpenses.getRemarks() == null ? "外出退补费:长者外出,退补" + startDate + "到" + endDate + "的费用(" +
                        startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")) + "月份共" + days + "天)" : dailyExpenses.getRemarks());
            } else if (startDate.isAfter(costDeadlineDate)) {
                // 费用开始日期在退住日期之后，计算实际天数（可能为0）
                if (!startDate.isAfter(endDate)) {
                    long days = ChronoUnit.DAYS.between(startDate, endDate) + 1;
                    itemVO.setDays((int) days);
                    itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
                    itemVO.setRemarks("费用开始日期在退住日期之后，无需退补费");
                } else {
                    itemVO.setDays(0);
                    itemVO.setAmount(BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP));
                    itemVO.setRemarks("费用开始日期在退住日期之后，无需退补费");
                }
            }
        }
    }

    /**
     * 处理押金项
     */
    private void processDepositItems(RefundSettlementOrderRespVO respVO,
                                     List<ExpenseOrderItemVO> virtualBillItems,
                                     BigDecimal totalRefundableAmount) {
        // 添加押金信息到费用项中（已通过createdDepositData方法查询并放入refundSettlementOrderItems中）
        if (respVO.getRefundSettlementOrderItems() != null) {
            for (RefundSettlementOrderItemDO depositItem : respVO.getRefundSettlementOrderItems()) {
                ExpenseOrderItemVO depositItemVO = new ExpenseOrderItemVO();
                depositItemVO.setItemName(depositItem.getItemName());
                // 押金金额需要取负值，因为押金是应退的
                BigDecimal depositAmount = depositItem.getActualRefundAmount() != null ?
                        depositItem.getActualRefundAmount().negate().setScale(2, RoundingMode.HALF_UP) : BigDecimal.ZERO;
                depositItemVO.setAmount(depositAmount);
                depositItemVO.setPrice(depositAmount);
                depositItemVO.setCount(1);
                depositItemVO.setIsDeposit(1);
                depositItemVO.setRemarks("押金退款");
                depositItemVO.setItemId(depositItem.getSourceItemId());
                virtualBillItems.add(depositItemVO);
            }
        }
    }






    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settleVirtualRefundOrder(ExpensePayOrderSaveReqVO saveReqVO) {

        // 获取退住结算单基础信息
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(saveReqVO.getRefundSettlementOrderId());
        if (refundSettlementOrder == null) {
            throw new RuntimeException("找不到该退住结算单");
        }

        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());
        if (elderlyInfo == null) {
            throw new RuntimeException("找不到该长者信息");
        }
        // 更新退住结算单状态
        refundSettlementOrder.setSettlementPersonName(SecurityFrameworkUtils.getLoginUserNickname());
        refundSettlementOrder.setSettlementTime(new Date());
        refundSettlementOrder.setStatus(BooleanEnum.TRUE.getValue()); // 已结算
        refundSettlementOrder.setRefundAmount(saveReqVO.getPayAmount());
        refundSettlementOrderMapper.updateById(refundSettlementOrder);

        // 创建支付订单
        ExpensePayOrderDO payOrder = new ExpensePayOrderDO();
        BeanUtils.copyProperties(saveReqVO, payOrder);
        payOrder.setExpenseOrderId(refundSettlementOrder.getId());
        payOrder.setType(BusinessConstants.REFUND_EXPENSE_PAY_ORDER);
        payOrder.setRoundPayAmount(saveReqVO.getPayAmount().setScale(0, RoundingMode.HALF_UP));
        payOrder.setRoundPayTwoDecimalAmount(saveReqVO.getPayAmount().setScale(2, RoundingMode.HALF_UP));
        payOrder.setCreatedTime(new Date());
        payOrder.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
        expensePayOrderMapper.insert(payOrder);

        // 创建支付订单项
        List<ExpensePayOrderItemDO> payItems = saveReqVO.getItems();
        for (ExpensePayOrderItemDO item : payItems) {
            item.setPayOrderId(payOrder.getId());
            item.setCreatedTime(new Date());
            item.setRoundPayAmount(item.getPayAmount().setScale(0, RoundingMode.HALF_UP));
            item.setRoundPayTwoDecimalAmount(item.getPayAmount().setScale(2, RoundingMode.HALF_UP));
            item.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
            expensePayOrderItemMapper.insert(item);
        }

        // 获取费用截止日期
        ElderlyRetreatRecordDO elderlyRetreatRecord = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());
        LocalDate costDeadlineDate = elderlyRetreatRecord.getCostDeadlineDate();
        YearMonth costDeadlineYearMonth = YearMonth.from(costDeadlineDate);
        // 删除该长者不显示的账单
        List<ExpenseOrderDO> notShowOrders = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getElderId, elderlyInfo.getId())
                .eq(ExpenseOrderDO::getIsShow, Boolean.FALSE));
        List<Long> notShowOrderIds = notShowOrders.stream().map(ExpenseOrderDO::getId).collect(Collectors.toList());
        if(CollectionUtil.isNotEmpty(notShowOrderIds)){
            expenseOrderItemMapper.delete(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                    .in(ExpenseOrderItemDO::getExpenseOrderId,notShowOrderIds));
            expenseOrderMapper.deleteBatchIds(notShowOrders);
        }
        // 查询所有账单（包括已缴费、未缴费和部分缴费的）
        List<ExpenseOrderDO> allOrders = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getElderId, elderlyInfo.getId()));

        // 处理所有账单中的费用项
        for (ExpenseOrderDO order : allOrders) {
            YearMonth orderYearMonth = YearMonth.from(DateTimeFormatter.ofPattern("yyyy-MM").parse(order.getBillingMonth()));

            // 过滤掉已完全缴纳且不在退住月份内的账单
            if (order.getPayStatus().equals(BooleanEnum.TRUE.getValue())
                    && !orderYearMonth.equals(costDeadlineYearMonth)) {
                continue;
            }

            // 更新账单状态
            order.setRefundSettlementOrderId(saveReqVO.getRefundSettlementOrderId());
            if (order.getPayStatus().equals(BooleanEnum.FALSE.getValue())) {
                order.setPayStatus(BooleanEnum.TRUE.getValue());
                order.setPayTime(new Date());
                order.setPayeeName(SecurityFrameworkUtils.getLoginUserNickname());

                // 更新账单项状态
                List<ExpenseOrderItemDO> expenseOrderItems = expenseOrderItemMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                        .eq(ExpenseOrderItemDO::getExpenseOrderId, order.getId()));

                for (ExpenseOrderItemDO item : expenseOrderItems) {
                    item.setPayStatus(BooleanEnum.TRUE.getValue());
                    expenseOrderItemMapper.updateById(item);
                }
            }
            expenseOrderMapper.updateById(order);
        }

        // 处理未生成到账单的日常费用
        List<DailyExpensesDO> unbilledDailyExpenses = dailyExpensesMapper.selectList(new LambdaQueryWrapperX<DailyExpensesDO>()
                .eq(DailyExpensesDO::getElderId, elderlyInfo.getId())
                .eq(DailyExpensesDO::getIsGenerateBill, BooleanEnum.FALSE.getValue())
                .eq(DailyExpensesDO::getStatus, BooleanEnum.FALSE.getValue()));

        for (DailyExpensesDO dailyExpenses : unbilledDailyExpenses) {
            // 过滤掉变更类型的日常费用中单价为0的费用项
            if (dailyExpenses.getType() != null && dailyExpenses.getType() == 2 &&
                    (dailyExpenses.getPrice() == null || dailyExpenses.getPrice().compareTo(BigDecimal.ZERO) == 0)) {
                continue;
            }

            // 标记这些日常费用为已处理
            dailyExpenses.setStatus(BooleanEnum.TRUE.getValue());
            dailyExpensesMapper.updateById(dailyExpenses);
        }

        // 处理押金退款项
        BigDecimal totalDepositRefundAmount = BigDecimal.ZERO;
        List<RefundSettlementOrderItemDO> refundSettlementOrderItems = saveReqVO.getRefundSettlementOrderItems();
        for (RefundSettlementOrderItemDO refundSettlementOrderItem : refundSettlementOrderItems) {
            if (refundSettlementOrderItem.getType() == 4){
                // 创建押金记录
                DepositRecordDO record = new DepositRecordDO();
                record.setType(3); // 退住结算类型
                record.setAmount(refundSettlementOrderItem.getActualRefundAmount());
                record.setElderId(refundSettlementOrder.getElderId());
                record.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
                record.setCreatedTime(new Date());
                record.setOrderNo("Y" + RandomUtil.randomNumbers(15));
                record.setItemName("退住结算");
                record.setTenantId(refundSettlementOrder.getTenantId());
                depositRecordMapper.insert(record);

                totalDepositRefundAmount = totalDepositRefundAmount.add(refundSettlementOrderItem.getActualRefundAmount());
            }
            refundSettlementOrderItem.setStatus(true);
            refundSettlementOrderItemMapper.updateById(refundSettlementOrderItem);
        }

        // 更新押金总额
        DepositDO depositDO = depositMapper.selectOne(new LambdaQueryWrapperX<DepositDO>()
                .eq(DepositDO::getElderId, refundSettlementOrder.getElderId()));
        if (depositDO != null) {
            BigDecimal amount = depositDO.getAmount();
            depositDO.setAmount(amount.subtract(totalDepositRefundAmount));
            depositMapper.updateById(depositDO);
        }


        // 通知消息更新
        notifyMessageSendApi.updateMessageByCodeAndPkMessage(BpmMessageEnum.REFUND_SETTLEMENT_HANDLE.getTemplateCode(),
                refundSettlementOrder.getElderId());
    }

    @Override
    public RefundSettledOrderDetailVO getSettledRefundOrderDetail(Long id) {
        // 获取退住结算单基础信息
        RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(id);
        if (refundSettlementOrder == null) {
            throw new RuntimeException("找不到该退住结算单");
        }

        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(refundSettlementOrder.getElderId());
        if (elderlyInfo == null) {
            throw new RuntimeException("找不到该长者信息");
        }

        // 构建返回对象
        RefundSettledOrderDetailVO detailVO = new RefundSettledOrderDetailVO();
        detailVO.setId(refundSettlementOrder.getId());
        detailVO.setOrderNumber(refundSettlementOrder.getOrderNumber());
        detailVO.setElderName(elderlyInfo.getElderName());
        detailVO.setBedName(buildService.getFullBedName(elderlyInfo.getId()));
        detailVO.setCheckInTime(elderlyInfo.getCheckInTime());
        detailVO.setSettlementTime(refundSettlementOrder.getSettlementTime());
        detailVO.setSettlementPersonName(refundSettlementOrder.getSettlementPersonName());
        detailVO.setRefundAmount(refundSettlementOrder.getRefundAmount());
        detailVO.setStatus(refundSettlementOrder.getStatus());
//        detailVO.setRemarks(refundSettlementOrder.getRemarks());

        // 获取退住相关信息（从退住记录表中获取）
        ElderlyRetreatRecordDO retreatRecord = elderlyRetreatRecordMapper.selectById(refundSettlementOrder.getBusinessId());
        if (retreatRecord != null) {
            detailVO.setRetreatDate(retreatRecord.getRetreatDate());
            detailVO.setCostDeadlineDate(retreatRecord.getCostDeadlineDate());
        }

        // 获取结算单细项
        List<RefundSettlementOrderItemDO> items = refundSettlementOrderItemMapper.selectList(
                new LambdaQueryWrapperX<RefundSettlementOrderItemDO>()
                        .eq(RefundSettlementOrderItemDO::getRefundSettlementOrderId, id));
        detailVO.setItems(items);

        // 获取支付信息
        ExpensePayOrderDO payOrder = expensePayOrderMapper.selectOne(
                new LambdaQueryWrapperX<ExpensePayOrderDO>()
                        .eq(ExpensePayOrderDO::getExpenseOrderId, id)
                        .eq(ExpensePayOrderDO::getType, BusinessConstants.REFUND_EXPENSE_PAY_ORDER));

        if (payOrder != null) {
            detailVO.setPayOrder(payOrder);

            // 获取支付明细
            List<ExpensePayOrderItemDO> payItems = expensePayOrderItemMapper.selectList(
                    new LambdaQueryWrapperX<ExpensePayOrderItemDO>()
                            .eq(ExpensePayOrderItemDO::getPayOrderId, payOrder.getId()));
            detailVO.setPayItems(payItems);
        }

        return detailVO;
    }

    @Override
    public void editRefundSettlementOrder(RefundSettlementOrderRespVO respVO) {
        List<RefundSettlementOrderItemDO> refundSettlementOrderItems = respVO.getRefundSettlementOrderItems();

        //更新结算单
        RefundSettlementOrderDO refundSettlementOrderDO = refundSettlementOrderMapper.selectById(respVO.getId());
        if (refundSettlementOrderDO != null){
            refundSettlementOrderDO.setRefundAmount(respVO.getRefundAmount());
            refundSettlementOrderDO.setReceivableAmount(respVO.getReceivableAmount());
            refundSettlementOrderDO.setRefundableAmount(respVO.getRefundableAmount());
            refundSettlementOrderMapper.updateById(refundSettlementOrderDO);
        }

        for (RefundSettlementOrderItemDO refundSettlementOrderItem : refundSettlementOrderItems) {
            refundSettlementOrderItemMapper.updateById(refundSettlementOrderItem);
        }
    }

    /**
     * 更新总金额，由于产生费用变动的位置太多，并且相同的更新代码冗余，目前可以使用查询时再更新总金额的方法
     */
    private void updateTotalAmount(RefundSettlementOrderRespVO respVO){
        // 应退金额
        BigDecimal receivableAmount = BigDecimal.ZERO;
        // 应收金额
        BigDecimal refundableAmount = BigDecimal.ZERO;
        for (RefundSettlementOrderItemDO refundSettlementOrderItem : respVO.getRefundSettlementOrderItems()) {
            BigDecimal actualRefundAmount = refundSettlementOrderItem.getActualRefundAmount();
            if(actualRefundAmount.compareTo(BigDecimal.ZERO) > 0){
                refundableAmount = refundableAmount.add(actualRefundAmount);
            }else {
                receivableAmount = receivableAmount.add(actualRefundAmount);
            }
        }
        respVO.setReceivableAmount(receivableAmount);
        respVO.setRefundableAmount(refundableAmount);
        respVO.setRefundAmount(refundableAmount.add(receivableAmount));
    }
}