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.exception.ServiceException;
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.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.excel.ExpenseSubsidyImportExcelVO;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ExpenseSubsidyPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ExpenseSubsidyRespVO;
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 com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.RoundingMode;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.EXPENSE_ORDER_ALREADY_CONFIRMED;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.EXPENSE_ORDER_ALREADY_LOCK;


/**
 * 长者长护险 Service 实现类
 *
 * @author 管理员
 */
@Slf4j
@Service
@Validated
public class ExpenseSubsidyServiceImpl implements ExpenseSubsidyService {

    @Resource
    private ExpenseSubsidyMapper expenseSubsidyMapper;
    @Resource
    private ExpenseSubsidyAccountMapper expenseSubsidyAccountMapper;
    @Resource
    private ElderlyInfoMapper elderlyInfoMapper;
    @Resource
    private TenantMapper tenantMapper;
    @Resource
    private ExpenseOrderMapper expenseOrderMapper;
    @Resource
    private ExpenseOrderItemMapper expenseOrderItemMapper;

    @Resource
    private RefundSettlementOrderMapper refundSettlementOrderMapper;
    @Resource
    private RefundSettlementOrderItemMapper refundSettlementOrderItemMapper;


    @Override
    @Transactional
    public Long createExpenseSubsidy(ExpenseSubsidyDO createReqVO) {
        //判断长者当前月份是有长护险，若存在不能生成同样月份的
//        ExpenseSubsidyDO expenseSubsidyDO = expenseSubsidyMapper
//                .selectOne(new LambdaQueryWrapperX<ExpenseSubsidyDO>()
//                        .eq(ExpenseSubsidyDO::getElderId, createReqVO.getElderId())
//                        .eq(ExpenseSubsidyDO::getDeductionBillMonth, createReqVO.getDeductionBillMonth())
//                        .eq(ExpenseSubsidyDO::getTenantId, createReqVO.getTenantId()));
//
//        if (expenseSubsidyDO != null) {
//            throw exception(COMMON_EXIST_ERROR);
//        }
        //创建长护险账号
        ExpenseSubsidyAccountDO expenseSubsidyAccount = expenseSubsidyAccountMapper.selectOne(new LambdaQueryWrapperX<ExpenseSubsidyAccountDO>()
                .eq(ExpenseSubsidyAccountDO::getElderId, createReqVO.getElderId())
                .eq(ExpenseSubsidyAccountDO::getTenantId,createReqVO.getTenantId()));
        if (expenseSubsidyAccount == null) {
            expenseSubsidyAccount = new ExpenseSubsidyAccountDO();
            expenseSubsidyAccount.setElderId(createReqVO.getElderId());
            expenseSubsidyAccount.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
            expenseSubsidyAccount.setCreatedTime(new Date());
            expenseSubsidyAccount.setAmount(createReqVO.getAmount());
            expenseSubsidyAccount.setTenantId(createReqVO.getTenantId());
            expenseSubsidyAccountMapper.insert(expenseSubsidyAccount);
        } else {
            if (expenseSubsidyAccount.getAmount().compareTo(BigDecimal.ZERO) < 0) {
                //小于0进行账单抵扣
                createReqVO.setStatus(BooleanEnum.TRUE.getValue());
            }
            expenseSubsidyAccount.setAmount(expenseSubsidyAccount.getAmount().add(createReqVO.getAmount()));
            expenseSubsidyAccountMapper.updateById(expenseSubsidyAccount);
        }
        createReqVO.setCreatedTime(new Date());
        expenseSubsidyMapper.insert(createReqVO);

        updateExpenseOrder(createReqVO);
        updateRefundOrder(createReqVO,false,false);
        return createReqVO.getId();
    }

    @Override
    public ExpenseSubsidyDO getExpenseSubsidy(Long id) {
        ExpenseSubsidyDO expenseSubsidyDO = expenseSubsidyMapper.selectById(id);
        if (expenseSubsidyDO != null) {
            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(expenseSubsidyDO.getElderId());
            expenseSubsidyDO.setElderName(elderlyInfo == null ? null : elderlyInfo.getElderName());
        }
        return expenseSubsidyDO;
    }

    @Override
    public void updateExpenseSubsidy(ExpenseSubsidyDO updateReqVO) {
        ExpenseSubsidyDO dbSubsidy = expenseSubsidyMapper.selectById(updateReqVO.getId());
        ExpenseSubsidyAccountDO expenseSubsidyAccount = expenseSubsidyAccountMapper.selectOne(new LambdaQueryWrapperX<ExpenseSubsidyAccountDO>()
                .eq(ExpenseSubsidyAccountDO::getElderId, dbSubsidy.getElderId())
                .eqIfPresent(ExpenseSubsidyAccountDO::getTenantId,updateReqVO.getTenantId()));
        if (expenseSubsidyAccount != null) {
            BigDecimal subtract = expenseSubsidyAccount.getAmount().subtract(dbSubsidy.getAmount());
            BigDecimal amount = subtract.add(updateReqVO.getAmount());
            expenseSubsidyAccount.setAmount(amount);
            expenseSubsidyAccountMapper.updateById(expenseSubsidyAccount);
        }
        expenseSubsidyMapper.updateById(updateReqVO);

        // 同步更新账单中的费用项和账单总金额
        // 查找与该长护险记录相关的账单费用项
        List<ExpenseOrderItemDO> orderItems = expenseOrderItemMapper.selectList(
                new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                        .eq(ExpenseOrderItemDO::getExpenseSource, BusinessConstants.LONG_TERM_CARE_INSURANCE)
                        .eq(ExpenseOrderItemDO::getSourceExpenseItemId, updateReqVO.getId())
        );

        // 检查是否修改了抵扣月份
        boolean deductionMonthChanged = !dbSubsidy.getDeductionBillMonth().equals(updateReqVO.getDeductionBillMonth());

        if (deductionMonthChanged) {
            // 如果修改了抵扣月份，需要重新处理账单关联关系
            // 1. 从旧月份账单中移除费用项
            for (ExpenseOrderItemDO orderItem : orderItems) {
                // 获取旧账单
                ExpenseOrderDO oldExpenseOrder = expenseOrderMapper.selectById(orderItem.getExpenseOrderId());
                if (oldExpenseOrder != null) {
                    // 校验账单是否已确认
                    validateExpenseOrderNotConfirmedAndNotLock(oldExpenseOrder);

                    // 从旧账单中减去该抵扣项的金额
                    BigDecimal newActualAmount = oldExpenseOrder.getActualAmount().subtract(orderItem.getTotalAmount());
                    oldExpenseOrder.setActualAmount(newActualAmount);
                    expenseOrderMapper.updateById(oldExpenseOrder);
                }

                // 删除旧的费用项
                expenseOrderItemMapper.deleteById(orderItem.getId());
            }

            // 2. 在新月份账单中添加费用项
            // 查询新月份的账单，如果不存在则创建
            ExpenseOrderDO newExpenseOrder = expenseOrderMapper.selectOne(new LambdaQueryWrapperX<ExpenseOrderDO>()
                    .eq(ExpenseOrderDO::getElderId, updateReqVO.getElderId())
                    .eq(ExpenseOrderDO::getBillingMonth, updateReqVO.getDeductionBillMonth())
                    .eq(ExpenseOrderDO::getType, 2)); // 月度账单

            if (newExpenseOrder != null) {
                // 校验账单是否已确认
                validateExpenseOrderNotConfirmedAndNotLock(newExpenseOrder);

                // 创建新的账单费用项
                ExpenseOrderItemDO newOrderItem = new ExpenseOrderItemDO();
                newOrderItem.setExpenseOrderId(newExpenseOrder.getId());
                newOrderItem.setSourceExpenseItemId(updateReqVO.getId());
                newOrderItem.setExpenseSource(BusinessConstants.LONG_TERM_CARE_INSURANCE);
                newOrderItem.setCount(1);
                newOrderItem.setItemName("长护险抵扣");
                newOrderItem.setPrice(updateReqVO.getAmount()); // 单价为负数表示抵扣
                newOrderItem.setActualPrice(updateReqVO.getAmount()); // 实际单价
                newOrderItem.setTotalAmount(updateReqVO.getAmount()); // 总金额为负数表示抵扣
                newOrderItem.setRoundAmount(newOrderItem.getTotalAmount().setScale(0, RoundingMode.HALF_UP));
                newOrderItem.setRoundTwoDecimalAmount(newOrderItem.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
                newOrderItem.setCreatedTime(new Date());
                newOrderItem.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
                newOrderItem.setTenantId(updateReqVO.getTenantId());
                newOrderItem.setPayStatus(0); // 未缴费状态
                expenseOrderItemMapper.insert(newOrderItem);

                // 更新新账单总金额
                BigDecimal currentAmount = newExpenseOrder.getActualAmount() != null ? newExpenseOrder.getActualAmount() : BigDecimal.ZERO;
                BigDecimal newAmount = currentAmount.add(newOrderItem.getTotalAmount());
                newExpenseOrder.setActualAmount(newAmount);
                expenseOrderMapper.updateById(newExpenseOrder);
            }
        } else {
            // 如果没有修改抵扣月份，只更新金额
            // 更新所有相关的账单费用项
            for (ExpenseOrderItemDO orderItem : orderItems) {
                // 保存旧的金额用于计算差值
                BigDecimal oldTotalAmount = orderItem.getTotalAmount();

                // 更新费用项金额（负数表示抵扣）
                orderItem.setPrice(updateReqVO.getAmount());
                orderItem.setActualPrice(updateReqVO.getAmount());
                orderItem.setTotalAmount(updateReqVO.getAmount());
                orderItem.setRoundAmount(orderItem.getTotalAmount().setScale(0, RoundingMode.HALF_UP));
                orderItem.setRoundTwoDecimalAmount(orderItem.getTotalAmount().setScale(2, RoundingMode.HALF_UP));

                // 更新费用项
                expenseOrderItemMapper.updateById(orderItem);

                // 更新对应账单的总金额
                ExpenseOrderDO expenseOrder = expenseOrderMapper.selectById(orderItem.getExpenseOrderId());
                if (expenseOrder != null) {
                    // 校验账单是否已确认
                    validateExpenseOrderNotConfirmedAndNotLock(expenseOrder);

                    // 计算金额差值并更新账单总金额
                    BigDecimal amountDifference = orderItem.getTotalAmount().subtract(oldTotalAmount);
                    BigDecimal newActualAmount = expenseOrder.getActualAmount().add(amountDifference);
                    expenseOrder.setActualAmount(newActualAmount);
                    expenseOrderMapper.updateById(expenseOrder);
                }
            }
        }

    }

    @Override
    public ExpenseSubsidyRespVO getDetails(Long elderId, String month) {
        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderId);

        ExpenseSubsidyRespVO respVO = new ExpenseSubsidyRespVO();
        respVO.setElderId(elderId);
        respVO.setElderName(elderlyInfo.getElderName());
        respVO.setSocialSecurityCardNumber(StringUtils.isBlank(elderlyInfo.getSocialSecurityCardNumber()) ? null : elderlyInfo.getSocialSecurityCardNumber());

        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal balance = BigDecimal.ZERO;
        List<ExpenseSubsidyDO> expenseSubsidyList = expenseSubsidyMapper.selectList(new LambdaQueryWrapperX<ExpenseSubsidyDO>()
                .eq(ExpenseSubsidyDO::getElderId, elderId)
                .eqIfPresent(ExpenseSubsidyDO::getDeductionBillMonth, month));
        for (ExpenseSubsidyDO expenseSubsidy : expenseSubsidyList) {
            totalAmount = totalAmount.add(expenseSubsidy.getAmount());
            //修正长护险余额
            ExpenseSubsidyAccountDO expenseSubsidyAccount = expenseSubsidyAccountMapper.selectOne(new LambdaQueryWrapperX<ExpenseSubsidyAccountDO>()
                    .eq(ExpenseSubsidyAccountDO::getElderId, elderId)
                    .eq(ExpenseSubsidyAccountDO::getTenantId, elderlyInfo.getTenantId()));
            if (expenseSubsidyAccount != null) {
                balance = expenseSubsidyAccount.getAmount();
            }

        }
        respVO.setTotalAmount(totalAmount);
        respVO.setBalance(balance);
        respVO.setRecords(expenseSubsidyList);
        return respVO;
    }

    @Override
    public PageResult<ExpenseSubsidyDO> getExpenseSubsidyPage(ExpenseSubsidyPageReqVO pageReqVO) {
        Page<ExpenseSubsidyDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<ExpenseSubsidyDO> list = expenseSubsidyMapper.getExpenseSubsidyPage(page, pageReqVO);
        for (ExpenseSubsidyDO expenseSubsidyDO : list) {
            TenantDO tenantDO = tenantMapper.selectById(expenseSubsidyDO.getTenantId());
            expenseSubsidyDO.setTenantName(tenantDO == null ? null : tenantDO.getName());
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    @Transactional
    public void importExpenseSubsidy(List<ExpenseSubsidyImportExcelVO> list) {
        List<ExpenseSubsidyImportExcelVO> errorResult = new ArrayList<>();
        for (ExpenseSubsidyImportExcelVO expenseSubsidyImportExcelVO : list) {
            // 校验月份格式（yyyy-MM），不符合直接报错
            validateMonthFormat(expenseSubsidyImportExcelVO.getMonth(), "所属月份");
            validateMonthFormat(expenseSubsidyImportExcelVO.getDeductionBillMonth(), "账单抵扣月");

            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectOne(new LambdaQueryWrapperX<ElderlyInfoDO>()
                    .eq(ElderlyInfoDO::getElderName, expenseSubsidyImportExcelVO.getElderName())
                    .eq(ElderlyInfoDO::getInStatus,1)
                    .eqIfPresent(ElderlyInfoDO::getIdCard, expenseSubsidyImportExcelVO.getIdCard())
                    .eq(ElderlyInfoDO::getTenantId, TenantContextHolder.getTenantId()));

            if (elderlyInfo == null) {
                errorResult.add(expenseSubsidyImportExcelVO);
                continue;
            }

            ExpenseSubsidyAccountDO expenseSubsidyAccount = expenseSubsidyAccountMapper
                    .selectOne(new LambdaQueryWrapperX<ExpenseSubsidyAccountDO>()
                            .eq(ExpenseSubsidyAccountDO::getElderId, elderlyInfo.getId()));
            //生成长护险记录
            ExpenseSubsidyDO expenseSubsidyDO = new ExpenseSubsidyDO();
            if (expenseSubsidyAccount == null) {
                // 修复BeanUtils.copyProperties参数顺序
                org.springframework.beans.BeanUtils.copyProperties(expenseSubsidyImportExcelVO, expenseSubsidyDO);
                expenseSubsidyDO.setElderId(elderlyInfo.getId());
                expenseSubsidyDO.setTenantId(elderlyInfo.getTenantId());
                expenseSubsidyMapper.insert(expenseSubsidyDO);
                //生成长护险账户
                expenseSubsidyAccount = new ExpenseSubsidyAccountDO();
                expenseSubsidyAccount.setAmount(expenseSubsidyImportExcelVO.getAmount());
                expenseSubsidyAccount.setElderId(elderlyInfo.getId());
                expenseSubsidyAccount.setCreatedTime(new Date());
                expenseSubsidyAccount.setTenantId(elderlyInfo.getTenantId());
                expenseSubsidyAccount.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
                expenseSubsidyAccountMapper.insert(expenseSubsidyAccount);
            } else {
                // 修复BeanUtils.copyProperties参数顺序
                org.springframework.beans.BeanUtils.copyProperties(expenseSubsidyImportExcelVO, expenseSubsidyDO);
                expenseSubsidyDO.setElderId(elderlyInfo.getId());
                expenseSubsidyDO.setTenantId(elderlyInfo.getTenantId());
                expenseSubsidyDO.setCreatedTime(new Date());
                expenseSubsidyMapper.insert(expenseSubsidyDO);

                if (expenseSubsidyAccount.getAmount() == null){
                    expenseSubsidyAccount.setAmount(BigDecimal.ZERO);
                }
                expenseSubsidyAccount.setAmount(expenseSubsidyAccount.getAmount().add(expenseSubsidyImportExcelVO.getAmount()));
                expenseSubsidyAccountMapper.updateById(expenseSubsidyAccount);
            }
            updateExpenseOrder(expenseSubsidyDO);
            updateRefundOrder(expenseSubsidyDO,false,false);
        }
    }

    /**
     * 校验月份格式为 yyyy-MM,并返回yyyy-MM,避免输入2025-1,其他格式直接抛错
     */
    private void validateMonthFormat(String value, String fieldName) {
        if (StringUtils.isBlank(value)) {
            throw new ServiceException(ErrorCodeConstants.COMMON_ERROR.getCode(), fieldName + "不能为空，格式需为年-月，如2025-01");
        }
        try {
            // 转成 yyyy-MM-01 再解析，避免只校验长度不校验合法日期
            LocalDate.parse(value + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        } catch (DateTimeParseException ex) {
            throw new ServiceException(ErrorCodeConstants.COMMON_ERROR.getCode(), fieldName + "格式需为年-月，如2025-01");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteExpenseSubsidy(Long id) {
        // 1. 查询长护险记录
        ExpenseSubsidyDO expenseSubsidy = expenseSubsidyMapper.selectById(id);
        if (expenseSubsidy == null) {
            throw exception(ErrorCodeConstants.COMMON_NOT_FOUND);
        }

        // 2. 查找所有与该长护险记录相关的账单明细项
        List<ExpenseOrderItemDO> orderItems = expenseOrderItemMapper.selectList(
                new LambdaQueryWrapperX<ExpenseOrderItemDO>()
                        .eq(ExpenseOrderItemDO::getExpenseSource, BusinessConstants.LONG_TERM_CARE_INSURANCE)
                        .eq(ExpenseOrderItemDO::getSourceExpenseItemId, id)
        );
        // 该长护险是否已完成缴费
        boolean isPay = false;
        // 3. 删除所有相关的账单明细项并修正账单金额
        for (ExpenseOrderItemDO orderItem : orderItems) {
            // 获取关联的账单
            ExpenseOrderDO expenseOrder = expenseOrderMapper.selectById(orderItem.getExpenseOrderId());
            if (expenseOrder != null) {
                // 修正账单金额
                // 对于抵扣项（负数），删除后账单金额应该增加相应的抵扣金额（负负得正）
                BigDecimal newAmount = expenseOrder.getActualAmount().subtract(orderItem.getTotalAmount());
                expenseOrder.setActualAmount(newAmount);
                expenseOrderMapper.updateById(expenseOrder);
            }
            isPay = orderItem.getPayStatus().equals(BooleanEnum.TRUE.getValue());
            // 删除费用项
            expenseOrderItemMapper.deleteById(orderItem.getId());
        }
        updateRefundOrder(expenseSubsidy,true,isPay);
        // 4. 删除长护险主记录
        expenseSubsidyMapper.deleteById(id);
    }

    /**
     * 校验账单是否已确认
     *
     * @param expenseOrder 账单对象
     * @param isBatch 是否批量处理
     * @return true表示已确认，false表示未确认
     * @throws ServiceException 如果是单个处理且账单已确认
     */
    private boolean validateExpenseOrderNotConfirmedAndNotLock(ExpenseOrderDO expenseOrder, boolean isBatch) {
        // 如果账单已确认
        if (Boolean.TRUE.equals(expenseOrder.getConfirmStatus())) {
            // 批量处理时直接返回true，表示需要跳过
            if (isBatch) {
                log.info("账单已确认，跳过处理, 账单ID:{}", expenseOrder.getId());
                return true;
            } else {
                // 单个处理时报错
                throw exception(EXPENSE_ORDER_ALREADY_CONFIRMED);
            }
        }
        if(expenseOrder.getIsLock()){
            // 批量处理时直接返回true，表示需要跳过
            if (isBatch) {
                log.info("账单已锁定，跳过处理, 账单ID:{}", expenseOrder.getId());
                return true;
            } else {
                // 单个处理时报错
                throw exception(EXPENSE_ORDER_ALREADY_LOCK);
            }
        }
        return false;
    }

    /**
     * 校验账单是否已确认（默认为单个处理）
     *
     * @param expenseOrder 账单对象
     * @return true表示已确认，false表示未确认
     * @throws ServiceException 如果账单已确认
     */
    private boolean validateExpenseOrderNotConfirmedAndNotLock(ExpenseOrderDO expenseOrder) {
        return validateExpenseOrderNotConfirmedAndNotLock(expenseOrder, false);
    }

    /**
     * 长护险录入对应未缴费的账单需要更新
     */
    private void updateExpenseOrder(ExpenseSubsidyDO createReqVO){
        //创建长护险的时候要把费用生成对应的账单里面
        // 查询对应月份的账单，如果不存在则创建
        ExpenseOrderDO expenseOrder = expenseOrderMapper.selectOne(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getElderId, createReqVO.getElderId())
                .eq(ExpenseOrderDO::getIsShow,BooleanEnum.TRUE.getValue())
                .eq(ExpenseOrderDO::getBillingMonth, createReqVO.getDeductionBillMonth())
                .ne(ExpenseOrderDO::getPayStatus,1)
                .eq(ExpenseOrderDO::getType, 2)); // 月度账单

        // 如果账单存在，更新长护险到账单里面
        if (expenseOrder != null) {
            // 校验账单是否已确认
            validateExpenseOrderNotConfirmedAndNotLock(expenseOrder);

            // 创建账单费用项
            ExpenseOrderItemDO orderItem = new ExpenseOrderItemDO();
            orderItem.setExpenseOrderId(expenseOrder.getId());
            orderItem.setSourceExpenseItemId(createReqVO.getId());
            orderItem.setExpenseSource(BusinessConstants.LONG_TERM_CARE_INSURANCE);
            orderItem.setCount(1);
            orderItem.setItemName("长护险抵扣");
            orderItem.setPrice(createReqVO.getAmount()); // 单价为负数表示抵扣
            orderItem.setActualPrice(createReqVO.getAmount()); // 实际单价
            orderItem.setTotalAmount(createReqVO.getAmount()); // 总金额为负数表示抵扣
            orderItem.setRoundAmount(orderItem.getTotalAmount().setScale(0, RoundingMode.HALF_UP));
            orderItem.setRoundTwoDecimalAmount(orderItem.getTotalAmount().setScale(2, RoundingMode.HALF_UP));
            orderItem.setCreatedTime(new Date());
            orderItem.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
            orderItem.setTenantId(createReqVO.getTenantId());
            orderItem.setPayStatus(0); // 未缴费状态
            expenseOrderItemMapper.insert(orderItem);

            // 更新账单总金额
            BigDecimal currentAmount = expenseOrder.getActualAmount() != null ? expenseOrder.getActualAmount() : BigDecimal.ZERO;
            BigDecimal newAmount = currentAmount.add(orderItem.getTotalAmount());
            expenseOrder.setActualAmount(newAmount);
            expenseOrderMapper.updateById(expenseOrder);

            //更新长护险状态
            createReqVO.setStatus(1);
            expenseSubsidyMapper.updateById(createReqVO);
        }
    }

    /**
     * 更新退住结算单
     */
    private void updateRefundOrder(ExpenseSubsidyDO expenseSubsidy,boolean isDelete,boolean isPay){
        if(isDelete){
            // 3. 查找所有与该长护险记录相关的退住账单明细项
            List<RefundSettlementOrderItemDO> refundOrderItems = refundSettlementOrderItemMapper.selectList(
                    new LambdaQueryWrapperX<RefundSettlementOrderItemDO>()
                            .like(RefundSettlementOrderItemDO::getItemName, "长护险")
                            .eq(RefundSettlementOrderItemDO::getSourceItemId, expenseSubsidy.getId()));
            // 4. 删除所有相关的退住账单明细项并修正账单金额
            for (RefundSettlementOrderItemDO refundOrderItem : refundOrderItems) {
                RefundSettlementOrderDO refundSettlementOrder = refundSettlementOrderMapper.selectById(refundOrderItem.getRefundSettlementOrderId());
                if(isPay){
                    refundOrderItem.setPrice(expenseSubsidy.getAmount());
                    refundOrderItem.setRefundAmount(expenseSubsidy.getAmount().subtract(refundOrderItem.getRefundAmount()));
                    refundOrderItem.setActualRefundAmount(expenseSubsidy.getAmount().subtract(refundOrderItem.getActualRefundAmount()));
                    if(refundSettlementOrder != null){
                        // 修正账单金额
                        // 对于抵扣项（负数），删除后账单金额应该增加相应的抵扣金额（负负得正）
                        BigDecimal newAmount = refundSettlementOrder.getRefundAmount().add(refundOrderItem.getRefundAmount());
                        refundSettlementOrder.setRefundAmount(newAmount);
                        refundSettlementOrderMapper.updateById(refundSettlementOrder);
                    }
                    refundSettlementOrderItemMapper.updateById(refundOrderItem);
                }else {
                    if(refundSettlementOrder != null){
                        // 修正账单金额
                        // 对于抵扣项（负数），删除后账单金额应该增加相应的抵扣金额（负负得正）
                        BigDecimal newAmount = refundSettlementOrder.getRefundAmount().subtract(refundOrderItem.getRefundAmount());
                        refundSettlementOrder.setRefundAmount(newAmount);
                        refundSettlementOrderMapper.updateById(refundSettlementOrder);
                    }
                    refundSettlementOrderItemMapper.deleteById(refundOrderItem);
                }
            }
        }else {
            //创建长护险的时候要把费用生成对应的账单里面
            // 查询对应退住的账单，如果不存在则返回
            List<RefundSettlementOrderDO> refundSettlementOrderDOList = refundSettlementOrderMapper.selectList(new LambdaQueryWrapperX<RefundSettlementOrderDO>()
                    .eq(RefundSettlementOrderDO::getElderId, expenseSubsidy.getElderId())
                    .orderByDesc(RefundSettlementOrderDO::getCreatedTime)); // 月度账单
            if(CollectionUtil.isEmpty(refundSettlementOrderDOList)){
                return;
            }
            RefundSettlementOrderDO refundSettlementOrderDO = refundSettlementOrderDOList.get(0);

            // 创建账单费用项
            RefundSettlementOrderItemDO orderItem = new RefundSettlementOrderItemDO();
            orderItem.setRefundSettlementOrderId(refundSettlementOrderDO.getId());
            orderItem.setType(2);
            orderItem.setCount(1);
            orderItem.setItemName("长护险抵扣");
            orderItem.setRemarks(expenseSubsidy.getRemarks());
            orderItem.setPrice(expenseSubsidy.getAmount()); // 单价为负数表示抵扣
            orderItem.setRefundAmount(expenseSubsidy.getAmount()); // 实际单价
            orderItem.setActualRefundAmount(expenseSubsidy.getAmount()); // 总金额为负数表示抵扣
            orderItem.setTenantId(expenseSubsidy.getTenantId());
            orderItem.setSourceItemId(expenseSubsidy.getId());
            refundSettlementOrderItemMapper.insert(orderItem);
            // 更新账单总金额
            BigDecimal currentAmount = refundSettlementOrderDO.getRefundAmount() != null ? refundSettlementOrderDO.getRefundAmount() : BigDecimal.ZERO;
            BigDecimal newAmount = currentAmount.add(orderItem.getRefundAmount());
            refundSettlementOrderDO.setRefundAmount(newAmount);
            refundSettlementOrderMapper.updateById(refundSettlementOrderDO);
            //更新长护险状态
            expenseSubsidy.setStatus(1);
            expenseSubsidyMapper.updateById(expenseSubsidy);
        }
    }
}