package cn.iocoder.yudao.module.system.service.yk.impl;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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.yk.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.home.HomeElderlyFamilyDO;
import cn.iocoder.yudao.module.system.dal.dataobject.home.HomeElderlyInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.yk.*;
import cn.iocoder.yudao.module.system.dal.dataobject.home.HomeElderlyAccountDO;
import cn.iocoder.yudao.module.system.dal.mysql.home.HomeElderlyAccountMapper;
import cn.iocoder.yudao.module.system.dal.mysql.home.HomeElderlyFamilyMapper;
import cn.iocoder.yudao.module.system.dal.mysql.home.HomeElderlyInfoMapper;
import cn.iocoder.yudao.module.system.dal.mysql.yk.*;
import cn.iocoder.yudao.module.system.service.yk.YkElderlyInfoService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

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

/**
 * 颐康中心长者信息服务实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class YkElderlyInfoServiceImpl implements YkElderlyInfoService {

    @Resource
    private HomeElderlyInfoMapper homeElderlyInfoMapper;
    @Resource
    private HomeElderlyAccountMapper homeElderlyAccountMapper;

    @Resource
    private YkElderlyDeliveryMapper ykElderlyDeliveryMapper;
    @Resource
    private YkElderlyExpenseRecordMapper ykElderlyExpenseRecordMapper;
    @Resource
    private YkDeliveryStaffInfoMapper deliveryPersonInfoMapper;
    @Resource
    private YkElderlyPaymentRecordMapper ykElderlyPaymentRecordMapper;

    @Autowired
    private HomeElderlyFamilyMapper homeElderlyFamilyMapper;


    @Override
    public Long createElderlyInfo(YkElderlyInfoSaveReqVO createReqVO) {
        HomeElderlyInfoDO existingElderlyInfo = homeElderlyInfoMapper.selectOne(new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                .eq(HomeElderlyInfoDO::getIdCard, createReqVO.getIdCard()));
        if (existingElderlyInfo != null) {
            updateElderlyInfoFromReq(existingElderlyInfo, createReqVO);
            return existingElderlyInfo.getId();
        }

        HomeElderlyInfoDO elderlyInfo = buildElderlyInfo(createReqVO);
        homeElderlyInfoMapper.insert(elderlyInfo);
        upsertEmergencyContact(elderlyInfo.getId(), elderlyInfo.getTenantId(), createReqVO);
        return elderlyInfo.getId();
    }

    private void updateElderlyInfoFromReq(HomeElderlyInfoDO existingElderlyInfo, YkElderlyInfoSaveReqVO reqVO) {
        BigDecimal originalDeliveryFee = existingElderlyInfo.getDeliveryFee();
        HomeElderlyInfoDO updateObj = buildElderlyInfo(reqVO);
        updateObj.setId(existingElderlyInfo.getId());
        updateObj.setDeliveryFee(originalDeliveryFee);
        updateObj.setCreator(existingElderlyInfo.getCreator());
        updateObj.setCreateTime(existingElderlyInfo.getCreateTime());
        updateObj.setUpdater(SecurityFrameworkUtils.getLoginUserNickname());
        updateObj.setUpdateTime(LocalDateTime.now());
        updateObj.setTenantId(resolveTenantId(reqVO.getTenantId()));
        homeElderlyInfoMapper.updateById(updateObj);
        upsertEmergencyContact(updateObj.getId(), updateObj.getTenantId(), reqVO);
    }

    private HomeElderlyInfoDO buildElderlyInfo(YkElderlyInfoSaveReqVO reqVO) {
        HomeElderlyInfoDO elderlyInfo = BeanUtils.toBean(reqVO, HomeElderlyInfoDO.class);
        elderlyInfo.setIsSubsidize("生效中".equals(reqVO.getSupportStatus()) ? 1 : 0);
        elderlyInfo.setHouseholdArea(reqVO.getHouseholdDistrict() + "/" + reqVO.getHouseholdStreet());
        elderlyInfo.setCurrentLiveArea(reqVO.getResidenceDistrict() + "/" + reqVO.getResidenceStreet());
        elderlyInfo.setCurrentLiveAddress(reqVO.getCurrentAddress());
        elderlyInfo.setPhone(reqVO.getPersonalPhone());
        elderlyInfo.setTenantId(resolveTenantId(reqVO.getTenantId()));
        if (elderlyInfo.getId() == null) {
            elderlyInfo.setCreator(SecurityFrameworkUtils.getLoginUserNickname());
            elderlyInfo.setCreateTime(LocalDateTime.now());
        }
        return elderlyInfo;
    }

    private void upsertEmergencyContact(Long elderlyId, Long tenantId, YkElderlyInfoSaveReqVO reqVO) {
        if (StringUtils.isBlank(reqVO.getEmergencyContact()) || StringUtils.isBlank(reqVO.getEmergencyContactPhone())) {
            return;
        }
        HomeElderlyFamilyDO homeElderlyFamilyDO = homeElderlyFamilyMapper.selectOne(new LambdaQueryWrapperX<HomeElderlyFamilyDO>()
                .eq(HomeElderlyFamilyDO::getHomeElderId, elderlyId)
                .eq(HomeElderlyFamilyDO::getIsEmergency, 1));
        if (homeElderlyFamilyDO == null) {
            homeElderlyFamilyDO = new HomeElderlyFamilyDO();
            homeElderlyFamilyDO.setHomeElderId(elderlyId);
            homeElderlyFamilyDO.setIsEmergency(1);
            homeElderlyFamilyDO.setTenantId(tenantId);
            homeElderlyFamilyDO.setContactName(reqVO.getEmergencyContact());
            homeElderlyFamilyDO.setPhone(reqVO.getEmergencyContactPhone());
            homeElderlyFamilyMapper.insert(homeElderlyFamilyDO);
            return;
        }
        homeElderlyFamilyDO.setContactName(reqVO.getEmergencyContact());
        homeElderlyFamilyDO.setPhone(reqVO.getEmergencyContactPhone());
        homeElderlyFamilyMapper.updateById(homeElderlyFamilyDO);
    }

    private Long resolveTenantId(Long tenantId) {
        return tenantId == null ? TenantContextHolder.getTenantId() : tenantId;
    }

    @Override
    public void updateElderlyInfo(YkElderlyInfoSaveReqVO updateReqVO) {
        // 校验存在
        validateElderlyInfoExists(updateReqVO.getId());
        // 更新
        HomeElderlyInfoDO updateObj = BeanUtils.toBean(updateReqVO, HomeElderlyInfoDO.class);
        homeElderlyInfoMapper.updateById(updateObj);
    }

    @Override
    public void deleteElderlyInfo(Long id) {
        // 校验存在
        validateElderlyInfoExists(id);
        // 删除
        homeElderlyInfoMapper.deleteById(id);
    }

    private void validateElderlyInfoExists(Long id) {
        if (homeElderlyInfoMapper.selectById(id) == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }
    }

    @Override
    public HomeElderlyInfoDO getElderlyInfo(Long id) {
        HomeElderlyInfoDO elderlyInfo = homeElderlyInfoMapper.selectById(id);
        fillBalanceFromAccount(elderlyInfo);
        return elderlyInfo;
    }

    @Override
    public PageResult<HomeElderlyInfoDO> getElderlyInfoPage(YkElderlyInfoPageReqVO pageReqVO) {
        PageResult<HomeElderlyInfoDO> pageResult = homeElderlyInfoMapper.selectPage(pageReqVO, new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                .likeIfPresent(HomeElderlyInfoDO::getElderName, pageReqVO.getElderName())
                .eqIfPresent(HomeElderlyInfoDO::getIdCard, pageReqVO.getIdCard())
                .eqIfPresent(HomeElderlyInfoDO::getTenantId, pageReqVO.getTenantId())
                .orderByDesc(HomeElderlyInfoDO::getId));
        fillBalanceFromAccount(pageResult.getList());
        return pageResult;
    }

    @Override
    public List<HomeElderlyInfoDO> getElderlyInfoList(YkElderlyInfoExportReqVO exportReqVO) {
        List<HomeElderlyInfoDO> list = homeElderlyInfoMapper.selectList(new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                .likeIfPresent(HomeElderlyInfoDO::getElderName, exportReqVO.getElderName())
                .eqIfPresent(HomeElderlyInfoDO::getIdCard, exportReqVO.getIdCard())
                .eqIfPresent(HomeElderlyInfoDO::getTenantId, TenantContextHolder.getTenantId())
                .orderByDesc(HomeElderlyInfoDO::getId));
        fillBalanceFromAccount(list);
        return list;
    }

    @Override
    public PageResult<YkElderlyMealRespVO> getElderlyMealPage(YkElderlyMealPageReqVO pageReqVO) {
        Page<YkElderlyMealRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<YkElderlyMealRespVO> ykElderlyMealRespVOPageResult = homeElderlyInfoMapper.selectElderlyMealPage(page, pageReqVO);
        return new PageResult<>(ykElderlyMealRespVOPageResult, page.getTotal());
    }

    @Override
    public void batchConfirm(YkMealBatchConfirmReqVO reqVO) {
        Long tenantId = reqVO.getTenantId();
        List<HomeElderlyInfoDO> homeElderlyInfoList = homeElderlyInfoMapper.selectList(new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                .eqIfPresent(HomeElderlyInfoDO::getTenantId, tenantId));
        List<HomeElderlyInfoDO> filteredList = homeElderlyInfoList.stream()
                .filter(elderlyInfo -> !reqVO.getIds().contains(elderlyInfo.getId()))
                .collect(Collectors.toList());
        //生成送餐记录
        for (HomeElderlyInfoDO homeElderlyInfoDO : filteredList) {
            YkDeliveryStaffInfoDO ykDeliveryStaffInfoDO = deliveryPersonInfoMapper.selectOne(new LambdaQueryWrapperX<YkDeliveryStaffInfoDO>()
                    .likeIfPresent(YkDeliveryStaffInfoDO::getElderlyIds, String.valueOf(homeElderlyInfoDO.getId())));
            YkElderlyDeliveryDO ykElderlyDeliveryDO = new YkElderlyDeliveryDO();
            ykElderlyDeliveryDO.setYkElderId(homeElderlyInfoDO.getId());
            ykElderlyDeliveryDO.setYkElderName(homeElderlyInfoDO.getElderName());
            ykElderlyDeliveryDO.setPhone(homeElderlyInfoDO.getPhone());
            ykElderlyDeliveryDO.setDeliveryAddress(homeElderlyInfoDO.getCurrentLiveAddress());
            ykElderlyDeliveryDO.setDeliveryDate(reqVO.getDate());
            ykElderlyDeliveryDO.setMealStandard(reqVO.getMealStandard());
            ykElderlyDeliveryDO.setMealType(reqVO.getMealType());
            ykElderlyDeliveryDO.setTenantId(tenantId);
            ykElderlyDeliveryDO.setCreatedTime(new Date());
            if (ykDeliveryStaffInfoDO != null){
                ykElderlyDeliveryDO.setDeliveryPersonId(ykDeliveryStaffInfoDO.getId());
                ykElderlyDeliveryDO.setDeliveryPersonName(ykDeliveryStaffInfoDO.getName());
            }
            ykElderlyDeliveryMapper.insert(ykElderlyDeliveryDO);
            //生成费用变动记录
            YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
            recordDO.setType(2);
            recordDO.setExpenseType(1);
            recordDO.setYkElderId(homeElderlyInfoDO.getId());
            recordDO.setAmount(ykElderlyDeliveryDO.getMealStandard());
            BigDecimal accountAmount = getElderlyAccountAmount(homeElderlyInfoDO.getId());
            recordDO.setBalance(accountAmount.subtract(recordDO.getAmount()));
            recordDO.setRemarks("长者送餐");
            recordDO.setCreatedTime(new Date());
            recordDO.setTenantId(tenantId);
            ykElderlyExpenseRecordMapper.insert(recordDO);
        }
    }

    @Override
    public PageResult<YkElderlyDeliveryDO> getDeliveryHistoryPage(YkElderlyDeliveryHistoryPageReqVO pageReqVO) {
        PageResult<YkElderlyDeliveryDO> pageResult = ykElderlyDeliveryMapper.selectPage(pageReqVO);
        return pageResult;
    }


    @Override
    public List<YkElderlyDeliveryHistoryRespVO> getTodayMealList() {
        List<YkElderlyDeliveryDO> ykElderlyDeliveryList = ykElderlyDeliveryMapper.selectList(new LambdaQueryWrapperX<YkElderlyDeliveryDO>()
                .apply("DATE(delivery_date) = CURDATE()"));
        return BeanUtils.toBean(ykElderlyDeliveryList, YkElderlyDeliveryHistoryRespVO.class);
    }

    @Override
    public void recordDeliveryFee(YkDeliveryFeeRecordReqVO reqVO) {
        // 查询送餐记录
        YkElderlyDeliveryDO delivery = ykElderlyDeliveryMapper.selectById(reqVO.getMealId());
        if (delivery == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }

        // 更新送工费字段
        delivery.setDeliveryFee(reqVO.getAmount());
        ykElderlyDeliveryMapper.updateById(delivery);

        HomeElderlyInfoDO ykElderlyInfoDO = homeElderlyInfoMapper.selectById(delivery.getYkElderId());
        BigDecimal deliveryFee = ykElderlyInfoDO.getDeliveryFee();
        BigDecimal afterAmount = deliveryFee.add(reqVO.getAmount());
        ykElderlyInfoDO.setDeliveryFee(afterAmount);
        homeElderlyInfoMapper.updateById(ykElderlyInfoDO);

        //生成费用变动记录
        YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
        recordDO.setType(2);  //消费
        recordDO.setExpenseType(2);  //工费
        recordDO.setYkElderId(delivery.getYkElderId());
        recordDO.setAmount(reqVO.getAmount());
        recordDO.setMealType(String.valueOf(delivery.getMealType()));
        recordDO.setBalance(afterAmount);
        recordDO.setRemarks("送工费");
        recordDO.setPayType(reqVO.getPaymentType());
        recordDO.setMealTime(delivery.getDeliveryDate().atStartOfDay());
        recordDO.setCreatedTime(new Date());
        recordDO.setTenantId(delivery.getTenantId());
        ykElderlyExpenseRecordMapper.insert(recordDO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importExpenseRecord(List<YkElderlyExpenseRecordImportVO> importVOList) {
        int successCount = 0;
        int updateCount = 0;
        int skipCount = 0;
        int failCount = 0;
        StringBuilder errorMsg = new StringBuilder();
        importVOList = importVOList.stream()
                .sorted(Comparator.comparing(YkElderlyExpenseRecordImportVO::getMealTime))
                .collect(Collectors.toList());
        for (int i = 0; i < importVOList.size(); i++) {
            YkElderlyExpenseRecordImportVO importVO = importVOList.get(i);
            try {
                //查询长者
                HomeElderlyInfoDO ykElderlyInfoDO = homeElderlyInfoMapper.selectOne(new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                        .eq(HomeElderlyInfoDO::getElderName, importVO.getServiceObj())
                        .eq(HomeElderlyInfoDO::getIdCard, importVO.getIdCard()));

                if (ykElderlyInfoDO == null) {
                    failCount++;
                    errorMsg.append("第").append(i + 1).append("行，服务对象不存在，请检查！\n");
                    continue;
                }

                // 检查是否已存在相同长者、相同日期的记录
                YkElderlyExpenseRecordDO existingRecord = ykElderlyExpenseRecordMapper.selectOne(
                        new LambdaQueryWrapperX<YkElderlyExpenseRecordDO>()
                                .eq(YkElderlyExpenseRecordDO::getYkElderId, ykElderlyInfoDO.getId())
                                .eq(YkElderlyExpenseRecordDO::getMealTime, importVO.getMealTime())
                );

                if (existingRecord != null) {
                    // 如果存在相同记录，检查金额是否一致
                    if (isAmountEqual(existingRecord, importVO)) {
                        // 金额一致，跳过导入
                        skipCount++;
                    } else {
                        // 金额不一致，更新记录
                        updateRecord(existingRecord, importVO);
                        ykElderlyExpenseRecordMapper.updateById(existingRecord);
                        updateCount++;
                    }
                } else {
                    // 不存在相同记录，新增记录
                    YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
                    recordDO.setType(2); // 消费类型
                    recordDO.setExpenseType(1); // 余额类型
                    recordDO.setYkElderId(ykElderlyInfoDO.getId());
                    recordDO.setAmount(importVO.getSelfPaidAmount());
                    recordDO.setBalance(importVO.getConsumptionAfter());
                    recordDO.setRemarks("费用导入");
                    recordDO.setCreatedTime(new Date());
                    recordDO.setTenantId(TenantContextHolder.getTenantId());
                    recordDO.setMealPeriod(importVO.getMealPeriod());
                    recordDO.setMealTime(importVO.getMealTime());
                    recordDO.setCitySubsidy(importVO.getCitySubsidy());
                    recordDO.setDistrictSubsidy(importVO.getDistrictSubsidy());
                    recordDO.setDistrictCharitySubsidy(importVO.getDistrictCharitySubsidy());
                    recordDO.setStreetSubsidy(importVO.getStreetSubsidy());
                    recordDO.setStreetCharitySubsidy(importVO.getStreetCharitySubsidy());
                    recordDO.setTotalSubsidyWithoutOperation(importVO.getTotalSubsidyWithoutOperation());
                    recordDO.setOperationSubsidyForElderly(importVO.getOperationSubsidyForElderly());
                    recordDO.setSelfPaidAmount(importVO.getSelfPaidAmount());
                    recordDO.setConsumptionBefore(importVO.getConsumptionBefore());
                    recordDO.setConsumptionAfter(importVO.getConsumptionAfter());
                    recordDO.setTotalConsumptionAmount(importVO.getTotalConsumptionAmount());
                    recordDO.setSerialNum(importVO.getSerialNum());
                    recordDO.setSubsidyType(importVO.getSubsidyType());
                    recordDO.setMealType(importVO.getMealType());
                    recordDO.setComboName(importVO.getComboName());
                    recordDO.setOrderStatus(importVO.getOrderStatus());
                    recordDO.setConsumptionTime(importVO.getConsumptionTime());
                    recordDO.setImportTime(LocalDateTime.now());
                    recordDO.setCityDeliverySubsidy(importVO.getCityDeliverySubsidy());
                    ykElderlyExpenseRecordMapper.insert(recordDO);
                    successCount++;

                    //更新长者账户余额
                    updateElderlyAccountAmount(ykElderlyInfoDO.getId(), recordDO.getBalance());

                    // 自动确认：查询该日期内是否有收款记录未确认，金额匹配则相互确认
                    String confirmMsg = autoConfirmExpenseRecord(recordDO);
                    if (confirmMsg != null) {
                        errorMsg.append("第").append(i + 1).append("行，").append(confirmMsg).append("\n");
                    }
                }
                // 自动核对金额是否一致
//                autoVerifyPaymentRecord(ykElderlyInfoDO.getId(), importVO.getConsumptionAfter());
            } catch (Exception e) {
                failCount++;
                errorMsg.append("第").append(i + 1).append("行数据导入失败：").append(e.getMessage()).append("\n");
            }
        }

        return String.format("导入完成，新增：%d条，更新：%d条，跳过：%d条，失败：%d条\n%s",
                successCount, updateCount, skipCount, failCount, errorMsg.toString());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importRecharge(List<YkElderlyExpenseRecordWeChatImportVO> importVOList) {
        int successCount = 0;
        int updateCount = 0;
        int skipCount = 0;
        int failCount = 0;
        StringBuilder errorMsg = new StringBuilder();
        importVOList = importVOList.stream()
                .sorted(Comparator.comparing(YkElderlyExpenseRecordWeChatImportVO::getConsumptionTime))
                .collect(Collectors.toList());
        for (int i = 0; i < importVOList.size(); i++) {
            YkElderlyExpenseRecordWeChatImportVO importVO = importVOList.get(i);
            try {
                //查询长者
                HomeElderlyInfoDO ykElderlyInfoDO = homeElderlyInfoMapper.selectOne(new LambdaQueryWrapperX<HomeElderlyInfoDO>()
                        .eq(HomeElderlyInfoDO::getElderName, importVO.getServiceObj())
                        .eq(HomeElderlyInfoDO::getIdCard, importVO.getIdCard()));

                if (ykElderlyInfoDO == null) {
                    failCount++;
                    errorMsg.append("第").append(i + 1).append("行，服务对象不存在，请检查！\n");
                    continue;
                }
                // 检查是否已存在相同长者、相同日期的记录
                YkElderlyExpenseRecordDO existingRecord = ykElderlyExpenseRecordMapper.selectOne(
                        new LambdaQueryWrapperX<YkElderlyExpenseRecordDO>()
                                .eq(YkElderlyExpenseRecordDO::getYkElderId, ykElderlyInfoDO.getId())
                                .eq(YkElderlyExpenseRecordDO::getMealTime, importVO.getConsumptionTime()));
                if (existingRecord != null) {
                    // 如果存在相同记录，检查金额是否一致
                    if (isAmountEqual(existingRecord, importVO)) {
                        // 金额一致，跳过导入
                        skipCount++;
                    } else {
                        // 金额不一致，更新记录
                        updateRecord(existingRecord, importVO);
                        ykElderlyExpenseRecordMapper.updateById(existingRecord);
                        updateCount++;
                    }
                }else {
                    YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
                    recordDO.setType(1); // 消费类型
                    recordDO.setExpenseType(1); // 余额类型
                    recordDO.setYkElderId(ykElderlyInfoDO.getId());
                    recordDO.setAmount(importVO.getSelfPaidAmount());
                    recordDO.setBalance(importVO.getConsumptionAfter());
                    recordDO.setRemarks("费用导入");
                    recordDO.setCreatedTime(new Date());
                    recordDO.setTenantId(TenantContextHolder.getTenantId());
                    recordDO.setSelfPaidAmount(importVO.getSelfPaidAmount());
                    recordDO.setConsumptionBefore(importVO.getConsumptionBefore());
                    recordDO.setConsumptionAfter(importVO.getConsumptionAfter());
                    recordDO.setSerialNum(importVO.getSerialNum());
                    recordDO.setSubsidyType(importVO.getSubsidyType());
                    recordDO.setConsumptionTime(importVO.getConsumptionTime());
                    recordDO.setImportTime(LocalDateTime.now());
                    recordDO.setMealTime(importVO.getConsumptionTime());
                    recordDO.setTotalConsumptionAmount(importVO.getSelfPaidAmount());
                    ykElderlyExpenseRecordMapper.insert(recordDO);
                    successCount++;

                    //更新长者账户余额
                    updateElderlyAccountAmount(ykElderlyInfoDO.getId(), recordDO.getBalance());

                    // 自动确认：查询该日期内是否有收款记录未确认，金额匹配则相互确认
                    String confirmMsg = autoConfirmExpenseRecord(recordDO);
                    if (confirmMsg != null) {
                        errorMsg.append("第").append(i + 1).append("行，").append(confirmMsg).append("\n");
                    }
                }
                // 自动核对金额是否一致
//                autoVerifyPaymentRecord(ykElderlyInfoDO.getId(), importVO.getConsumptionAfter());
            } catch (Exception e) {
                failCount++;
                errorMsg.append("第").append(i + 1).append("行数据导入失败：").append(e.getMessage()).append("\n");
            }
        }

        return String.format("导入完成，新增：%d条，更新：%d条，跳过：%d条，失败：%d条\n%s",
                successCount, updateCount, skipCount, failCount, errorMsg.toString());
    }

//    /**
//     * 自动核对费用记录与支付记录的金额是否一致
//     *
//     * @param elderlyId 长者ID
//     * @param importedAmount 导入的金额
//     */
//    private void autoVerifyPaymentRecord(Long elderlyId, BigDecimal importedAmount) {
//        // 查询yk_elderly_payment_record表中该长者的上传费用记录
//        List<YkElderlyPaymentRecordDO> paymentRecords = ykElderlyPaymentRecordMapper.selectList(
//                new LambdaQueryWrapperX<YkElderlyPaymentRecordDO>()
//                        .eq(YkElderlyPaymentRecordDO::getYkElderId, elderlyId)
//        );
//
//        // 查找金额一致的支付记录
//        for (YkElderlyPaymentRecordDO paymentRecord : paymentRecords) {
//            if (paymentRecord.getAmount() != null && paymentRecord.getAmount().compareTo(importedAmount) == 0) {
//                // 金额一致，更新费用变动记录的支付方式和状态
//                YkElderlyExpenseRecordDO expenseRecord = ykElderlyExpenseRecordMapper.selectOne(
//                        new LambdaQueryWrapperX<YkElderlyExpenseRecordDO>()
//                                .eq(YkElderlyExpenseRecordDO::getYkElderId, elderlyId)
//                                .eq(YkElderlyExpenseRecordDO::getBalance, importedAmount)
//                                .eq(YkElderlyExpenseRecordDO::getStatus, 0)
//                                .orderByDesc(YkElderlyExpenseRecordDO::getCreatedTime)
//                                .last("LIMIT 1")
//                );
//
//                if (expenseRecord != null) {
//                    // 更新费用变动记录的支付方式和备注
//                    expenseRecord.setPayType(paymentRecord.getPaymentType());
//                    expenseRecord.setRemarks(expenseRecord.getRemarks() + "，已自动核对");
//                    expenseRecord.setStatus(1); // 已核对状态
//                    ykElderlyExpenseRecordMapper.updateById(expenseRecord);
//                    break; // 只处理一条匹配记录
//                }
//            }
//        }
//    }




    /**
     * 检查记录金额是否相等
     */
    private boolean isAmountEqual(YkElderlyExpenseRecordDO record, YkElderlyExpenseRecordImportVO importVO) {
        return Objects.equals(record.getSelfPaidAmount(), importVO.getSelfPaidAmount()) &&
                Objects.equals(record.getConsumptionAfter(), importVO.getConsumptionAfter()) &&
                Objects.equals(record.getTotalConsumptionAmount(), importVO.getTotalConsumptionAmount());
    }

    /**
     * 检查记录金额是否相等
     */
    private boolean isAmountEqual(YkElderlyExpenseRecordDO record, YkElderlyExpenseRecordWeChatImportVO importVO) {
        return Objects.equals(record.getSelfPaidAmount(), importVO.getSelfPaidAmount()) &&
                Objects.equals(record.getConsumptionAfter(), importVO.getConsumptionAfter()) &&
                Objects.equals(record.getTotalConsumptionAmount(), importVO.getSelfPaidAmount());
    }

    /**
     * 更新记录信息
     */
    private void updateRecord(YkElderlyExpenseRecordDO record, YkElderlyExpenseRecordImportVO importVO) {
        record.setAmount(importVO.getSelfPaidAmount());
        record.setBalance(importVO.getConsumptionAfter());
        record.setRemarks("费用导入(更新)");
        record.setCitySubsidy(importVO.getCitySubsidy());
        record.setDistrictSubsidy(importVO.getDistrictSubsidy());
        record.setDistrictCharitySubsidy(importVO.getDistrictCharitySubsidy());
        record.setStreetSubsidy(importVO.getStreetSubsidy());
        record.setStreetCharitySubsidy(importVO.getStreetCharitySubsidy());
        record.setTotalSubsidyWithoutOperation(importVO.getTotalSubsidyWithoutOperation());
        record.setOperationSubsidyForElderly(importVO.getOperationSubsidyForElderly());
        record.setSelfPaidAmount(importVO.getSelfPaidAmount());
        record.setConsumptionBefore(importVO.getConsumptionBefore());
        record.setConsumptionAfter(importVO.getConsumptionAfter());
        record.setTotalConsumptionAmount(importVO.getTotalConsumptionAmount());
        record.setSelfPaidAmount(importVO.getSelfPaidAmount());
        record.setConsumptionBefore(importVO.getConsumptionBefore());
        record.setConsumptionAfter(importVO.getConsumptionAfter());
        record.setTotalConsumptionAmount(importVO.getTotalConsumptionAmount());
        record.setSerialNum(importVO.getSerialNum());
        record.setSubsidyType(importVO.getSubsidyType());
        record.setMealType(importVO.getMealType());
        record.setComboName(importVO.getComboName());
        record.setOrderStatus(importVO.getOrderStatus());
        record.setConsumptionTime(importVO.getConsumptionTime());
        record.setImportTime(LocalDateTime.now());
        record.setCityDeliverySubsidy(importVO.getCityDeliverySubsidy());
        record.setImportTime(LocalDateTime.now());
    }

    /**
     * 更新记录信息
     */
    private void updateRecord(YkElderlyExpenseRecordDO record, YkElderlyExpenseRecordWeChatImportVO importVO) {
        record.setAmount(importVO.getSelfPaidAmount());
        record.setBalance(importVO.getConsumptionAfter());
        record.setRemarks("费用导入(更新)");
        record.setCreatedTime(new Date());
        record.setTenantId(TenantContextHolder.getTenantId());
        record.setSelfPaidAmount(importVO.getSelfPaidAmount());
        record.setConsumptionBefore(importVO.getConsumptionBefore());
        record.setConsumptionAfter(importVO.getConsumptionAfter());
        record.setSerialNum(importVO.getSerialNum());
        record.setSubsidyType(importVO.getSubsidyType());
        record.setConsumptionTime(importVO.getConsumptionTime());
        record.setImportTime(LocalDateTime.now());
        record.setMealTime(importVO.getConsumptionTime());
        record.setImportTime(LocalDateTime.now());
    }


    @Override
    public void updateBalance(YkBalanceUpdateReqVO reqVO) {
        YkElderlyExpenseRecordDO ykElderlyExpenseRecordDO = ykElderlyExpenseRecordMapper.selectById(reqVO.getId());

        // 查询长者信息
        HomeElderlyInfoDO elderlyInfo = homeElderlyInfoMapper.selectById(ykElderlyExpenseRecordDO.getYkElderId());
        if (elderlyInfo == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }

        // 获取变更前余额
        BigDecimal balanceBefore = getElderlyAccountAmount(elderlyInfo.getId());
        // 设置变更后余额为指定值（不累加）
        BigDecimal balanceAfter = reqVO.getAmount();

        // 计算实际变动金额
        BigDecimal actualChangeAmount = balanceAfter.subtract(balanceBefore);

        // 创建费用变动记录
        YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
        recordDO.setType(actualChangeAmount.compareTo(BigDecimal.ZERO) > 0 ? 1 : 3); // 1:充值 3:退款
        recordDO.setExpenseType(1); // 余额类型
        recordDO.setYkElderId(elderlyInfo.getId());
        recordDO.setAmount(actualChangeAmount); // 保存绝对值
        recordDO.setConsumptionBefore(balanceBefore); // 变更前余额
        recordDO.setConsumptionAfter(balanceAfter); // 变更后余额
        recordDO.setBalance(balanceAfter); // 最终余额
        recordDO.setRemarks(reqVO.getUpdateReason());
        recordDO.setPayType(reqVO.getPaymentType());
        recordDO.setCreatedTime(new Date());
        recordDO.setTenantId(TenantContextHolder.getTenantId());
        recordDO.setMealTime(reqVO.getMealTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        recordDO.setMealType(ykElderlyExpenseRecordDO.getMealType());

        ykElderlyExpenseRecordMapper.insert(recordDO);

        // 更新长者账户余额为指定值（不累加）
        updateElderlyAccountAmount(elderlyInfo.getId(), balanceAfter);

    }

    @Override
    public void updateDeliveryFee(YkBalanceUpdateReqVO reqVO) {
        YkElderlyExpenseRecordDO ykElderlyExpenseRecordDO = ykElderlyExpenseRecordMapper.selectById(reqVO.getId());

        // 查询长者信息
        HomeElderlyInfoDO elderlyInfo = homeElderlyInfoMapper.selectById(ykElderlyExpenseRecordDO.getYkElderId());
        if (elderlyInfo == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }

        // 获取变更前送工费
        BigDecimal feeBefore = elderlyInfo.getDeliveryFee() != null ? elderlyInfo.getDeliveryFee() : BigDecimal.ZERO;
        // 设置变更后送工费为指定值
        BigDecimal feeAfter = reqVO.getAmount();


        // 创建费用变动记录
        YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
        recordDO.setType(feeAfter.compareTo(feeBefore) > 0 ? 1 : 3); // 1:增加 3:减少
        recordDO.setExpenseType(2); // 工费类型
        recordDO.setYkElderId(elderlyInfo.getId());
        recordDO.setAmount(feeAfter);
        recordDO.setConsumptionBefore(feeBefore); // 变更前送工费
        recordDO.setConsumptionAfter(feeAfter); // 变更后送工费
        recordDO.setRemarks(reqVO.getUpdateReason());
        recordDO.setBalance(feeAfter);
        recordDO.setPayType(reqVO.getPaymentType());
        recordDO.setCreatedTime(new Date());
        recordDO.setMealTime(ykElderlyExpenseRecordDO.getMealTime());
        recordDO.setMealType(ykElderlyExpenseRecordDO.getMealType());
        recordDO.setTenantId(TenantContextHolder.getTenantId());

        ykElderlyExpenseRecordMapper.insert(recordDO);


        elderlyInfo.setDeliveryFee(feeAfter);
        homeElderlyInfoMapper.updateById(elderlyInfo);
    }

    @Override
    public void confirmFinanceData(YkFinanceConfirmReqVO reqVO) {
        // 查询费用变动记录
        YkElderlyExpenseRecordDO expenseRecord = ykElderlyExpenseRecordMapper.selectById(reqVO.getId());
        if (expenseRecord == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }

        // 更新费用变动记录的支付方式和备注
        expenseRecord.setPayType(reqVO.getPaymentType());
        expenseRecord.setRemarks(reqVO.getRemark());
        expenseRecord.setStatus(1); //确认状态
        ykElderlyExpenseRecordMapper.updateById(expenseRecord);
    }

    @Override
    public PageResult<YkElderlyExpenseRecordDO> getBalanceRecordPage(YkBalanceRecordPageReqVO pageReqVO) {
        // 查询费用变动记录分页列表
        return ykElderlyExpenseRecordMapper.selectPage(pageReqVO);
    }
    @Override
    public void updateStandard(YkMealUpdateStandardReqVO reqVO) {
        YkElderlyDeliveryDO ykElderlyDeliveryDO = ykElderlyDeliveryMapper.selectById(reqVO.getMealId());

        // 查询长者信息
        HomeElderlyInfoDO elderlyInfo = homeElderlyInfoMapper.selectById(reqVO.getElderlyId());
        if (elderlyInfo == null) {
            throw exception(ELDERLY_INFO_NOT_EXISTS);
        }

        // 获取变更前餐标
        BigDecimal feeBefore = ykElderlyDeliveryDO.getMealStandard() != null ? ykElderlyDeliveryDO.getMealStandard() : BigDecimal.ZERO;
        // 设置变更后餐标为指定值
        BigDecimal feeAfter = reqVO.getMealStandard();
        BigDecimal updateFee = feeAfter.subtract(feeBefore);
        BigDecimal balanceBefore = getElderlyAccountAmount(elderlyInfo.getId());
        BigDecimal updateBalance = balanceBefore.subtract(updateFee);
        // 创建费用变动记录
        YkElderlyExpenseRecordDO recordDO = new YkElderlyExpenseRecordDO();
        recordDO.setType(feeAfter.compareTo(feeBefore) > 0 ? 1 : 3); // 1:增加 3:减少
        recordDO.setExpenseType(2); // 工费类型
        recordDO.setYkElderId(elderlyInfo.getId());
        recordDO.setAmount(feeAfter);
        recordDO.setConsumptionBefore(balanceBefore); // 变更前余额
        recordDO.setConsumptionAfter(updateBalance); // 变更后送工费
        recordDO.setRemarks(reqVO.getRemark());
        recordDO.setBalance(updateBalance);
        recordDO.setPayType(reqVO.getPayType());
        recordDO.setCreatedTime(new Date());
        recordDO.setMealTime(LocalDateTime.now());
        recordDO.setMealType(ykElderlyDeliveryDO.getMealType());
        recordDO.setTenantId(TenantContextHolder.getTenantId());

        ykElderlyExpenseRecordMapper.insert(recordDO);


        elderlyInfo.setDeliveryFee(feeAfter);
        homeElderlyInfoMapper.updateById(elderlyInfo);
    }
    private BigDecimal safeAmount(BigDecimal amount) {
        return amount == null ? BigDecimal.ZERO : amount;
    }

    private void fillBalanceFromAccount(HomeElderlyInfoDO elderlyInfo) {
        if (elderlyInfo == null) {
            return;
        }
        elderlyInfo.setBalance(getElderlyAccountAmount(elderlyInfo.getId()));
    }

    private void fillBalanceFromAccount(List<HomeElderlyInfoDO> elderlyInfoList) {
        if (elderlyInfoList == null || elderlyInfoList.isEmpty()) {
            return;
        }
        elderlyInfoList.forEach(this::fillBalanceFromAccount);
    }

    private BigDecimal getElderlyAccountAmount(Long elderlyId) {
        HomeElderlyAccountDO accountDO = homeElderlyAccountMapper.selectOne(
                new LambdaQueryWrapperX<HomeElderlyAccountDO>()
                        .eq(HomeElderlyAccountDO::getHomeElderId, elderlyId)
                        .last("limit 1")
        );
        return accountDO == null || accountDO.getAmount() == null ? BigDecimal.ZERO : accountDO.getAmount();
    }

    private void updateElderlyAccountAmount(Long elderlyId, BigDecimal amount) {
        HomeElderlyAccountDO accountDO = homeElderlyAccountMapper.selectOne(
                new LambdaQueryWrapperX<HomeElderlyAccountDO>()
                        .eq(HomeElderlyAccountDO::getHomeElderId, elderlyId)
                        .last("limit 1")
        );
        if (accountDO == null) {
            accountDO = new HomeElderlyAccountDO();
            accountDO.setHomeElderId(elderlyId);
            accountDO.setAmount(safeAmount(amount));
            accountDO.setTenantId(TenantContextHolder.getTenantId());
            homeElderlyAccountMapper.insert(accountDO);
            return;
        }
        accountDO.setAmount(safeAmount(amount));
        homeElderlyAccountMapper.updateById(accountDO);
    }

    @Override
    public void batchDeleteElderlyInfo(List<Long> ids) {
        homeElderlyInfoMapper.deleteBatchIds(ids);
    }

    @Override
    public void batchDeleteExpenseRecord(List<Long> ids) {
        ykElderlyExpenseRecordMapper.deleteBatchIds(ids);
    }

    @Override
    public void batchDeleteDeliveryRecord(List<Long> ids) {
        ykElderlyDeliveryMapper.deleteBatchIds(ids);
    }

    /**
     * 自动确认收款记录与财务变动记录
     * 当新增收款记录时，查询该日期内未确认的财务变动记录，按创建时间排序，金额匹配则相互确认
     *
     * @param paymentRecord 收款记录
     * @return 提示信息，如果确认成功返回null，否则返回提示信息
     */
    public String autoConfirmPaymentRecord(YkElderlyPaymentRecordDO paymentRecord) {
        if (paymentRecord == null || paymentRecord.getAmount() == null || paymentRecord.getYkElderId() == null) {
            return "收款记录信息不完整，无法自动确认";
        }

        // 获取收款记录所在日期
        LocalDateTime paymentDateTime = paymentRecord.getPaymentDateTime();
        if (paymentDateTime == null) {
            return "收款时间不能为空，无法自动确认";
        }
        LocalDate paymentDate = paymentDateTime.toLocalDate();
        LocalDateTime startDateTime = paymentDate.atStartOfDay();
        LocalDateTime endDateTime = paymentDate.atTime(23, 59, 59);

        // 查询该日期内未确认的财务变动记录，按创建时间排序
        List<YkElderlyExpenseRecordDO> expenseRecords = ykElderlyExpenseRecordMapper.selectList(
                new LambdaQueryWrapperX<YkElderlyExpenseRecordDO>()
                        .eq(YkElderlyExpenseRecordDO::getYkElderId, paymentRecord.getYkElderId())
                        .eq(YkElderlyExpenseRecordDO::getType,1)    //充值
                        .eq(YkElderlyExpenseRecordDO::getStatus, 0) // 未确认
                        .between(YkElderlyExpenseRecordDO::getMealTime, startDateTime, endDateTime)
                        .orderByAsc(YkElderlyExpenseRecordDO::getMealTime)
        );

        // 如果没有找到记录
        if (expenseRecords.isEmpty()) {
            return String.format("该日期（%s）内未找到未确认的财务变动记录，无法自动确认", paymentDate);
        }

        // 查找金额一致的财务变动记录
        boolean foundMatch = false;
        for (YkElderlyExpenseRecordDO expenseRecord : expenseRecords) {
            if (expenseRecord.getAmount() != null && expenseRecord.getAmount().compareTo(paymentRecord.getAmount()) == 0) {
                // 金额一致，相互确认
                // 更新财务变动记录
                expenseRecord.setPayType(paymentRecord.getPaymentType());
                if (expenseRecord.getRemarks() != null && !expenseRecord.getRemarks().contains("已自动确认")) {
                    expenseRecord.setRemarks(expenseRecord.getRemarks() + "，已自动确认");
                } else if (expenseRecord.getRemarks() == null) {
                    expenseRecord.setRemarks("已自动确认");
                }
                expenseRecord.setStatus(1); // 已确认
                ykElderlyExpenseRecordMapper.updateById(expenseRecord);

                // 更新收款记录
                if (paymentRecord.getStatus() == null || paymentRecord.getStatus() == 0) {
                    paymentRecord.setStatus(1); // 已确认
                    ykElderlyPaymentRecordMapper.updateById(paymentRecord);
                }
                return "自动确认成功"; // 确认成功，返回null
            }
        }

        // 如果找到了记录但金额不匹配
        if (!foundMatch) {
            StringBuilder amountInfo = new StringBuilder();
            for (YkElderlyExpenseRecordDO record : expenseRecords) {
                if (amountInfo.length() > 0) {
                    amountInfo.append("、");
                }
                amountInfo.append(record.getAmount() != null ? record.getAmount() : "0");
            }
            return String.format("该日期（%s）内存在财务变动记录，但金额不匹配。收款金额：%s，财务变动记录金额：%s，无法自动确认",
                    paymentDate, paymentRecord.getAmount(), amountInfo.toString());
        }
        return null;
    }

    /**
     * 自动确认财务变动记录与收款记录
     * 当新增财务变动记录时，查询该日期内未确认的收款记录，按创建时间排序，金额匹配则相互确认
     *
     * @param expenseRecord 财务变动记录
     * @return 提示信息，如果确认成功返回null，否则返回提示信息
     */
    public String autoConfirmExpenseRecord(YkElderlyExpenseRecordDO expenseRecord) {
        if (expenseRecord == null || expenseRecord.getAmount() == null || expenseRecord.getYkElderId() == null) {
            return "财务变动记录信息不完整，无法自动确认";
        }

        // 获取财务变动记录所在日期
        LocalDateTime mealTime = expenseRecord.getMealTime();
        if (mealTime == null) {
            return "就餐时间不能为空，无法自动确认";
        }
        LocalDate mealDate = mealTime.toLocalDate();
        LocalDateTime startDateTime = mealDate.atStartOfDay();
        LocalDateTime endDateTime = mealDate.atTime(23, 59, 59);

        // 查询该日期内未确认的收款记录，按创建时间排序
        List<YkElderlyPaymentRecordDO> paymentRecords = ykElderlyPaymentRecordMapper.selectList(
                new LambdaQueryWrapperX<YkElderlyPaymentRecordDO>()
                        .eq(YkElderlyPaymentRecordDO::getYkElderId, expenseRecord.getYkElderId())
                        .and(wrapper -> wrapper.eq(YkElderlyPaymentRecordDO::getStatus, 0).or().isNull(YkElderlyPaymentRecordDO::getStatus)) // 未确认或null
                        .between(YkElderlyPaymentRecordDO::getPaymentDateTime, startDateTime, endDateTime)
                        .orderByAsc(YkElderlyPaymentRecordDO::getPaymentDateTime)
        );

        // 如果没有找到记录
        if (paymentRecords.isEmpty()) {
            return String.format("该日期（%s）内未找到未确认的收款记录，无法自动确认", mealDate);
        }

        // 查找金额一致的收款记录
        for (YkElderlyPaymentRecordDO paymentRecord : paymentRecords) {
            if (paymentRecord.getAmount() != null && paymentRecord.getAmount().compareTo(expenseRecord.getAmount()) == 0) {
                // 金额一致，相互确认
                // 更新财务变动记录
                expenseRecord.setPayType(paymentRecord.getPaymentType());
                if (expenseRecord.getRemarks() != null && !expenseRecord.getRemarks().contains("已自动确认")) {
                    expenseRecord.setRemarks(expenseRecord.getRemarks() + "，已自动确认");
                } else if (expenseRecord.getRemarks() == null) {
                    expenseRecord.setRemarks("已自动确认");
                }
                expenseRecord.setStatus(1); // 已确认
                ykElderlyExpenseRecordMapper.updateById(expenseRecord);

                // 更新收款记录
                if (paymentRecord.getStatus() == null || paymentRecord.getStatus() == 0) {
                    paymentRecord.setStatus(1); // 已确认
                    ykElderlyPaymentRecordMapper.updateById(paymentRecord);
                }
                return null; // 确认成功，返回null
            }
        }

        // 如果找到了记录但金额不匹配
        StringBuilder amountInfo = new StringBuilder();
        for (YkElderlyPaymentRecordDO record : paymentRecords) {
            if (amountInfo.length() > 0) {
                amountInfo.append("、");
            }
            amountInfo.append(record.getAmount() != null ? record.getAmount() : "0");
        }
        return String.format("该日期（%s）内存在收款记录，但金额不匹配。财务变动记录金额：%s，收款记录金额：%s，无法自动确认",
                mealDate, expenseRecord.getAmount(), amountInfo.toString());

    }
}