package cn.iocoder.yudao.module.system.api.bpm;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.corp.CorpMsgUtil;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.object.ReflectUtils;
import cn.iocoder.yudao.framework.common.util.string.StringUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.system.api.bpm.vo.*;
import cn.iocoder.yudao.module.system.api.kingdee.KingdeeApi;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.api.notify.convert.message.UserMessageConvert;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.api.wechat.dto.CorpSendMessage;
import cn.iocoder.yudao.module.system.api.wechat.dto.CorpWechatTextcard;
import cn.iocoder.yudao.module.system.api.wechat.dto.WechatMessageSaveReq;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlyInformationStatistics;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.RelativesDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sys.BusinessParamsConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.*;
import cn.iocoder.yudao.module.system.dal.mysql.sys.BusinessParamsConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.system.enums.NoticeConstants;
import cn.iocoder.yudao.module.system.enums.change.BusinessTypeEnum;
import cn.iocoder.yudao.module.system.enums.common.BooleanEnum;
import cn.iocoder.yudao.module.system.enums.notice.NotieBusinessTypeEnum;
import cn.iocoder.yudao.module.system.enums.notice.NotifyPriorityEnum;
import cn.iocoder.yudao.module.system.enums.notice.NotifyTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.system.enums.NoticeConstants.*;
import static cn.iocoder.yudao.module.system.enums.oauth2.EnterpriseWeChatConstants.BPM_DETAIL_URL;
import static net.sf.jsqlparser.util.validation.metadata.NamedObject.index;
import static net.sf.jsqlparser.util.validation.metadata.NamedObject.user;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Collections;

/**
 * @Author: jinyd
 * @CreateTime: 2024/8/7  10:02
 * @Description: Bpm事件 API接口实现类
 * @Version: 4.0
 */


@Service
@Validated
@Slf4j
public class BpmElderlyApiImpl implements BpmElderlyApi {

    @Autowired
    private ElderlySyntheticAbilityMapper elderlySyntheticAbilityMapper;
    @Autowired
    private ElderlyCheckInRecordMapper elderlyCheckInRecordMapper;
    @Autowired
    private SysEvaluationProcessMapper sysEvaluationProcessMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private RelativesMapper relativesMapper;
    @Autowired
    private ElderlyInfoMapper elderlyInfoMapper;
    @Autowired
    private ElderlyRetreatRecordMapper retreatRecordMapper;
    @Autowired
    private BuildBedMapper buildBedMapper;
    @Autowired
    private NotifyMessageSendApi notifyMessageSendApi;
    @Autowired
    private TenantMapper tenantMapper;
    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private BusinessParamsConfigMapper businessParamsConfigMapper;


    @Resource
    private ElderlyContractMapper contractMapper;

    @Resource
    private ExpenseOrderMapper expenseOrderMapper;

    @Autowired
    private KingdeeApi kingdeeApi;

    @Resource
    @Lazy
    private BpmProcessInstanceApi bpmProcessInstanceApi;

    @Override
    @TenantIgnore
    public void generateAdmissionAssessment(Long elderId, Long startTenantId) {
        //查询入院评估
        List<SysEvaluationProcessDO> sysEvaluationProcessEntities = sysEvaluationProcessMapper.selectList(new LambdaQueryWrapper<SysEvaluationProcessDO>()
                .eq(SysEvaluationProcessDO::getType, 1).eq(SysEvaluationProcessDO::getTenantId, startTenantId)
                .orderByDesc(SysEvaluationProcessDO::getCreatedTime));

        ElderlySyntheticAbilityDO elderlySyntheticAbility = new ElderlySyntheticAbilityDO();
        if (sysEvaluationProcessEntities != null && !sysEvaluationProcessEntities.isEmpty()) {
            SysEvaluationProcessDO sysEvaluationProcess = sysEvaluationProcessEntities.stream().findFirst().get();



            elderlySyntheticAbility.setElderId(elderId);
            elderlySyntheticAbility.setQuestionnaireId(sysEvaluationProcess.getId().toString());
            elderlySyntheticAbility.setQuestionnaireName(sysEvaluationProcess.getProcessName());
            elderlySyntheticAbility.setEvaluationAgency("1");
            elderlySyntheticAbility.setQuestionnaireType(sysEvaluationProcess.getType());
            elderlySyntheticAbility.setCreateDate(LocalDateTime.now());
            elderlySyntheticAbility.setOrgType(sysEvaluationProcess.getOrgType());

            String redisKey = "REDIS_EVALUATION_CODE:" + TenantContextHolder.getTenantId();
            redisTemplate.opsForValue().increment(redisKey, 1);
            Integer incrementalCode = (Integer) redisTemplate.opsForValue().get(redisKey);
            String evaluationCode = "NLPG" + DateUtils.getYear() + DateUtils.getMonth() + DateUtils.getDay() + String.format("%04d", incrementalCode);
            elderlySyntheticAbility.setEvaluationCode(evaluationCode);
            elderlySyntheticAbility.setSignType(0);
            elderlySyntheticAbility.setTenantId(startTenantId);
            elderlySyntheticAbilityMapper.insert(elderlySyntheticAbility);
        }

        //生成入住申请
        ElderlyCheckInRecordDO elderlyCheckInRecord = new ElderlyCheckInRecordDO();
        elderlyCheckInRecord.setCreatedTime(new Date());
        elderlyCheckInRecord.setStatus(1);
        elderlyCheckInRecord.setElderId(Long.valueOf(elderId));
        elderlyCheckInRecord.setTenantId(startTenantId);
        elderlyCheckInRecord.setOrgType(elderlyInfoMapper.selectById(elderId).getOrgType());
        elderlyCheckInRecordMapper.insert(elderlyCheckInRecord);

        ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectById(elderId);
        // TODO 暂时写定获取默认审批人
//        Long messageUserId = 1l;
//        AdminUserDO adminUserDO = userMapper.selectById(messageUserId);
//        String corpUserId = null == adminUserDO.getCorpUserId() ? "" : adminUserDO.getCorpUserId();
//        Long tenantId = adminUserDO.getTenantId();
//        TenantDO tenantDO = tenantMapper.selectById(tenantId);

        Map<String, Object> templateParams = new HashMap<>();
        templateParams.put("elderName", elderlyInfoDO.getElderName());

        List<BusinessParamsConfigDO> businessParamsConfigDOS = businessParamsConfigMapper.selectList(new LambdaQueryWrapperX<BusinessParamsConfigDO>()
                .in(BusinessParamsConfigDO::getConfigName,
                        NoticeConstants.APPLY_ACCOMMODATION_NAME,
                        NoticeConstants.SYNTHETIC_ABILITY_HANDLE_NAME)
                .eq(BusinessParamsConfigDO::getTenantId, startTenantId));

        String title = CorpMsgUtil.TITLE_TODO;
        CorpSendMessage corpSendMessage = new CorpSendMessage();
        WechatMessageSaveReq wechatMessageSaveReq = new WechatMessageSaveReq();
        CorpWechatTextcard corpTextCard = new CorpWechatTextcard();
        corpTextCard.setTitle(title);
        corpTextCard.setBtntxt(CorpMsgUtil.BTNTXT_DETAIL_NOTICE);
        corpTextCard.setUrl("");
        corpSendMessage.setTextcard(corpTextCard);
        corpSendMessage.setContentType(1);
        wechatMessageSaveReq.setTitle(title);
        wechatMessageSaveReq.setPkMessage(elderId.toString());
        wechatMessageSaveReq.setPkMessage2("");
        wechatMessageSaveReq.setApplyTime(DateUtils.localDateTimeToStr(LocalDateTime.now()));

        if (null == businessParamsConfigDOS || businessParamsConfigDOS.size() == 0) return;
        businessParamsConfigDOS.forEach(businessParamsConfigDO -> {
            wechatMessageSaveReq.setTypeName(businessParamsConfigDO.getConfigName());
            corpSendMessage.setWechatMessageSaveReq(wechatMessageSaveReq);
            List<MessgeUserRespVO> userList = new ArrayList<>();
            List<MessgeUserRespVO> deptList = new ArrayList<>();
            if (StringUtil.isNotEmptyORNull(businessParamsConfigDO.getValue())) {
                String[] split = businessParamsConfigDO.getValue().split(",");
                Set<Long> userIds = new HashSet<>();
                for (String s : split) {
                    userIds.add(Long.parseLong(s));
                }
                userList = userMapper.selectMessageUserByIds(userIds, 0);
            }
            if (StringUtil.isNotEmptyORNull(businessParamsConfigDO.getValue2())) {
                String[] split = businessParamsConfigDO.getValue2().split(",");
                Set<Long> deptIds = new HashSet<>();
                for (String s : split) {
                    deptIds.add(Long.parseLong(s));
                }
                deptList = userMapper.selectMessageUserByIds(deptIds, 1);
            }
            List<MessgeUserRespVO> mergeList = new ArrayList<>();
            Map<Long, Long> map = new HashMap<>();
            for (int i = 0; i < userList.size(); i++) {
                MessgeUserRespVO messgeUserRespVO = userList.get(i);
                map.put(messgeUserRespVO.getId(), messgeUserRespVO.getId());
                mergeList.add(messgeUserRespVO);
            }
            for (int i = 0; i < deptList.size(); i++) {
                if (!map.containsKey(deptList.get(i).getId())) {
                    mergeList.add(deptList.get(i));
                }
            }
            String templateCode = "";
            String url = "";
            if (NoticeConstants.APPLY_ACCOMMODATION_NAME.equals(businessParamsConfigDO.getConfigName())) {
                url = String.format(APPLY_ACCOMMODATION_URL, elderId, startTenantId);
                templateCode = BpmMessageEnum.CHECK_IN_HANDLE.getTemplateCode();
            }
            if (NoticeConstants.SYNTHETIC_ABILITY_HANDLE_NAME.equals(businessParamsConfigDO.getConfigName())) {
                url = String.format(SYNTHETIC_ABILITY_HANDLE_URL, elderlySyntheticAbility.getId(), startTenantId);
                templateCode = BpmMessageEnum.SYNTHETIC_ABILITY_HANDLE.getTemplateCode();
            }
            for (int i = 0; i < mergeList.size(); i++) {
                MessgeUserRespVO messgeUserRespVO = mergeList.get(i);
                NotifySendSingleToUserReqDTO checkInHandleReqdto = UserMessageConvert.INSTANCE.messageConvert(messgeUserRespVO.getId(),
                        elderId.toString(), null, url, templateCode, templateParams,
                        NotieBusinessTypeEnum.ORDINARY.getValue(), NotifyTypeEnum.NOTIFY_TODO.getValue(),
                        NotifyPriorityEnum.HIGH.getValue(), 0, messgeUserRespVO.getTenantId());
                corpSendMessage.setTouser(messgeUserRespVO.getCorpUserId());
                wechatMessageSaveReq.setCorpUserId(messgeUserRespVO.getCorpUserId());
                wechatMessageSaveReq.setStartTenantId(messgeUserRespVO.getTenantId());
                wechatMessageSaveReq.setTenantName(messgeUserRespVO.getAbbreviation());
                notifyMessageSendApi.sendMessageAndCorpMessage(checkInHandleReqdto, corpSendMessage);
            }
        });


    }

    @Override
    public Long addElder(ElderlyInfoReqVO elderlyInfoReqVO) {
        ElderlyInfoDO elderlyInfo = BeanUtils.toBean(elderlyInfoReqVO, ElderlyInfoDO.class);
        elderlyInfo.setCreateTime(new Date());
        elderlyInfo.setUserSign(RandomUtil.randomString(18));
        elderlyInfo.setUpdateTime(new Date());

        StringBuilder fileNumber = new StringBuilder();
        String date = DateUtils.formatDate(new Date(), "yyyyMMdd");
        fileNumber.append(date);

        redisTemplate.opsForValue().increment(RedisKeyConstants.ELDERLY_FILE_INCREMENT_NUMBER_KEY);
        Integer incrementNum = (Integer) redisTemplate.opsForValue().get(RedisKeyConstants.ELDERLY_FILE_INCREMENT_NUMBER_KEY);
        fileNumber.append(String.format("%06d", incrementNum));
        elderlyInfo.setFileNumber(fileNumber.toString());
        elderlyInfo.setSourceType(2);
        elderlyInfo.setElderName(elderlyInfo.getElderName().trim());
        elderlyInfo.setIdCard(elderlyInfo.getIdCard().trim());
        elderlyInfoMapper.insert(elderlyInfo);
        updateElderlyKingdeeInfo(elderlyInfo);

        if (elderlyInfo.getRelativesList() != null) {
            for (RelativesDO relatives : elderlyInfo.getRelativesList()) {
                relatives.setPeopleId(elderlyInfo.getId());
                relatives.setPeopleName(elderlyInfo.getElderName());
                relatives.setStatus("0");
                relatives.setCreateDate(LocalDateTime.now());
                relatives.setTenantId(elderlyInfo.getTenantId());
                relativesMapper.insert(relatives);
            }
        }

        return elderlyInfo.getId();
    }

    @Override
    public void update(ElderlyInfoReqVO elderlyInfoReqVO) {
        ElderlyInfoDO elderlyInfoDO = BeanUtils.toBean(elderlyInfoReqVO, ElderlyInfoDO.class);
        elderlyInfoDO.setUpdateTime(new Date());
        elderlyInfoMapper.updateById(elderlyInfoDO);
    }

    @Override
    @TenantIgnore
    public ElderlyInfoReqVO getElderlyInfo(Long id) {
        ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectById(id);
        ElderlyInfoReqVO elderlyInfoReqVO = BeanUtils.toBean(elderlyInfoDO, ElderlyInfoReqVO.class);
        return elderlyInfoReqVO;
    }

    @Override
    @TenantIgnore
    public ElderlyInfoReqVO getElderlyInfoByRetreatId(Long id) {
        ElderlyRetreatRecordDO elderlyRetreatRecordDO = retreatRecordMapper.selectById(id);
        ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectById(elderlyRetreatRecordDO.getElderlyId());
        ElderlyInfoReqVO elderlyInfoReqVO = BeanUtils.toBean(elderlyInfoDO, ElderlyInfoReqVO.class);
        return elderlyInfoReqVO;
    }

    @Override
    public Long addElderlyRetreatRecord(ElderlyRetreatRecordRespVO elderlyRetreatRecord) {
        ElderlyRetreatRecordDO elderlyRetreatRecordDO = BeanUtils.toBean(elderlyRetreatRecord, ElderlyRetreatRecordDO.class);
        retreatRecordMapper.insert(elderlyRetreatRecordDO);

        //更新退住状态
        ElderlyCheckInRecordDO elderlyCheckInRecordDO = elderlyCheckInRecordMapper.selectOne(new LambdaQueryWrapperX<ElderlyCheckInRecordDO>()
                .eqIfPresent(ElderlyCheckInRecordDO::getElderId, elderlyRetreatRecord.getElderlyId())
                .eqIfPresent(ElderlyCheckInRecordDO::getTenantId, elderlyRetreatRecord.getTenantId())
                .eq(ElderlyCheckInRecordDO::getCurrentFlag,0));

        if (elderlyCheckInRecordDO != null){
            elderlyCheckInRecordDO.setStatus(3);
            elderlyCheckInRecordMapper.updateById(elderlyCheckInRecordDO);
        }

        return elderlyRetreatRecordDO.getId();
    }

    @Override
    public void updateElderlyRetreatRecord(ElderlyRetreatRecordRespVO elderlyRetreatRecord) {
        ElderlyRetreatRecordDO elderlyRetreatRecordDO = BeanUtils.toBean(elderlyRetreatRecord, ElderlyRetreatRecordDO.class);
        retreatRecordMapper.updateById(elderlyRetreatRecordDO);
    }

    @Override
    public PageResult<ElderlyCheckinInfoRespVO> getCheckinRecordPage(ElderlyCheckinRecordPageReqVO pageVO) {
        Page<ElderlyCheckinInfoRespVO> page = new Page<>(pageVO.getPageNo(), pageVO.getPageSize());
        List<ElderlyCheckinInfoRespVO> list = elderlyInfoMapper.findBpmPage(page, pageVO);
        for (ElderlyCheckinInfoRespVO checkinInfoRespVO : list) {
            //统计信息完成度
            elderlyInfoStatistics(checkinInfoRespVO);
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public PageResult<ElderlyRetreatRecordRespVO> getRetreatRecordPage(ElderlyRetreatRecordPageReqApiVO pageReqVO) {
        Page<ElderlyRetreatRecordRespVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        pageReqVO.setType(BusinessTypeEnum.APPLY_RETREAT.getValue());
        List<ElderlyRetreatRecordRespVO> list = retreatRecordMapper.selectListPage(page, pageReqVO);
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public void deleteElderlyRetreatRecord(Long id) {
        ElderlyRetreatRecordDO elderlyRetreatRecordDO = new ElderlyRetreatRecordDO();
        elderlyRetreatRecordDO.setId(id);
        // 状态为1，表示不是最新的流程
        elderlyRetreatRecordDO.setCurrentFlag(1);
        retreatRecordMapper.updateById(elderlyRetreatRecordDO);
    }

    @Override
    @TenantIgnore
    public void releaseBed(Long retreatRecordId) {
        ElderlyRetreatRecordDO elderlyRetreatRecordDO = retreatRecordMapper.selectById(retreatRecordId);
        Long elderId = elderlyRetreatRecordDO.getElderlyId();
        ElderlyInfoDO originalElderlyInfoDO = elderlyInfoMapper.selectById(elderId);
        ElderlyInfoDO elderlyInfoDO = new ElderlyInfoDO();
        elderlyInfoDO.setId(elderId);
        Date checkOutTime = Date.from(elderlyRetreatRecordDO.getRetreatDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
        elderlyInfoDO.setCheckOutTime(checkOutTime);
        elderlyInfoDO.setInStatus(2);
        elderlyInfoMapper.updateById(elderlyInfoDO);

        BuildBedDO bedDO = buildBedMapper.selectById(originalElderlyInfoDO.getBedId());
        bedDO.setStatus(0);
        buildBedMapper.updateById(bedDO);
    }

    @Override
    public void delectRetreatRecordByElderId(Long elderId, Integer orgType, Long tenantId) {
        retreatRecordMapper.update(new LambdaUpdateWrapper<ElderlyRetreatRecordDO>()
                .eq(ElderlyRetreatRecordDO::getElderlyId, elderId)
                .eq(ElderlyRetreatRecordDO::getCurrentFlag, 0)
                .eq(ElderlyRetreatRecordDO::getOrgType, orgType)
                .eq(ElderlyRetreatRecordDO::getTenantId, tenantId)
                .set(ElderlyRetreatRecordDO::getCurrentFlag, 1));

    }

    public ElderlyCheckinInfoRespVO elderlyInfoStatistics(ElderlyCheckinInfoRespVO checkinInfoRespVO) {
        Field[] declaredFields = ElderlyInformationStatistics.class.getDeclaredFields();
        int total = declaredFields.length + 1;
        int count = 0;

        //对比基本信息
        for (Field declaredField : declaredFields) {
            Object fieldValue = ReflectUtils.getFieldValue(checkinInfoRespVO, declaredField.getName());
            if (fieldValue != null && !fieldValue.equals("")) {
                count++;
            }
        }


        //健康档案信息
//        List<ElderlyHealthRecord> elderlyHealthRecords = elderlyHealthRecordMapper.selectList(new LambdaQueryWrapper<ElderlyHealthRecord>().eq(ElderlyHealthRecord::getElderId, elderlyInfo.getId()).orderByDesc(ElderlyHealthRecord::getId));
//        if (!elderlyHealthRecords.isEmpty()) {
//            ElderlyHealthRecord elderlyHealthRecord = elderlyHealthRecords.stream().findFirst().get();
//            if (elderlyHealthRecord != null) {
//                for (Field declaredField : declaredFields) {
//                    Object fieldValue = ReflectUtils.getFieldValue(elderlyHealthRecord, declaredField.getName());
//                    if (fieldValue != null && !fieldValue.equals("")) {
//                        count++;
//                    }
//                }
//            }
//        }
//
//
        //获取亲属信息
        List<RelativesDO> relatives = relativesMapper.selectList(new LambdaQueryWrapper<RelativesDO>().eq(RelativesDO::getPeopleId, checkinInfoRespVO.getId()));
        if (relatives != null && !relatives.isEmpty()) {
            count = count + 1;
        }

        //统计结果
        NumberFormat numberFormat = NumberFormat.getInstance();
        //设备到小数点0位,不需要小数点
        numberFormat.setMaximumFractionDigits(0);
        String result = numberFormat.format((float) count / (float) total * 100);
        checkinInfoRespVO.setInfoPercentage(Integer.parseInt(result));
        checkinInfoRespVO.setInfoFieldCount(count);
        checkinInfoRespVO.setTotalInfoFieldCount(total);
        return checkinInfoRespVO;
    }


    @Override
    public Long generateApplyAccommodationData(Long elderId, Long startTenantId) {
        ElderlyRetreatRecordRespVO elderlyRetreatRecordRespVO = new ElderlyRetreatRecordRespVO();
        elderlyRetreatRecordRespVO.setElderlyId(elderId);
        elderlyRetreatRecordRespVO.setRetreatDate(LocalDate.now());
        elderlyRetreatRecordRespVO.setApplyType(0);
        elderlyRetreatRecordRespVO.setOrgType(1);
        elderlyRetreatRecordRespVO.setTenantId(startTenantId);
        Long id = addElderlyRetreatRecord(elderlyRetreatRecordRespVO);
        bpmProcessInstanceApi.insertBpmBusinessFormDO(id, elderId, startTenantId);
        generateAdmissionAssessment(elderId, startTenantId);
        return null;
    }


    @Override
    public String selectUnprocessedBills(Long elderlyId, LocalDate costDeadlineDate) {
        String message = "未生成账单月份：";
        List<ElderlyContractDO> elderlyContractDOS = contractMapper.selectList(new LambdaQueryWrapperX<ElderlyContractDO>().eq(ElderlyContractDO::getElderId, elderlyId));
        if (null == elderlyContractDOS || elderlyContractDOS.size() == 0) {
            return null;
        }
        ElderlyContractDO elderlyContractDO = elderlyContractDOS.get(0);
        Date beginTime = elderlyContractDO.getBeginTime();
        // 处理beginTime 为 2024-09的格式的字符串
        String beginTimeStr = DateUtil.format(beginTime, "yyyy-MM");
        // 处理costDeadlineDate 为 2024-09的格式的字符串
        String costDeadlineDateStr = DateUtil.format(costDeadlineDate.atStartOfDay(), "yyyy-MM");
        // 查询beginTime 到 costDeadlineDate 的所有费用单
        List<ExpenseOrderDO> expenseOrderDOS = expenseOrderMapper.selectList(new LambdaQueryWrapperX<ExpenseOrderDO>()
                .eq(ExpenseOrderDO::getElderId, elderlyId).ge(ExpenseOrderDO::getBillingMonth, beginTimeStr).le(ExpenseOrderDO::getBillingMonth, costDeadlineDateStr));
        if (null == expenseOrderDOS || expenseOrderDOS.size() == 0) {
            return "未生成费用账单";
        }

        LocalDate beginTimeLocalDate = beginTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        List<String> billingMonths = expenseOrderDOS.stream().map(ExpenseOrderDO::getBillingMonth).collect(Collectors.toList());
        List<String> monthsBetween = getMonthsBetween(beginTimeLocalDate, costDeadlineDate);
        // 比较billingMonths和monthsBetween，返回不存在的账单月份拼接成字符串
        List<String> result = monthsBetween.stream().filter(month -> !billingMonths.contains(month)).collect(Collectors.toList());

        message = message + String.join("、", result);
        return message;
    }


    public static List<String> getMonthsBetween(LocalDate start, LocalDate end) {
        // 处理日期为null或开始日期晚于结束日期的情况
        if (start == null || end == null || start.isAfter(end)) {
            return Collections.emptyList();
        }

        List<String> months = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");

        // 转换为YearMonth（自动去除日期部分）
        YearMonth startMonth = YearMonth.from(start);
        YearMonth endMonth = YearMonth.from(end);

        // 循环添加月份直到包含结束月份
        for (YearMonth month = startMonth;
             !month.isAfter(endMonth);
             month = month.plusMonths(1)) {
            months.add(month.format(formatter));
        }

        return months;
    }

    @Override
    public Boolean checkElderExist(String idCard){
        ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectOne(new LambdaQueryWrapperX<ElderlyInfoDO>()
                .eq(ElderlyInfoDO::getIdCard,idCard)
                .eq(ElderlyInfoDO::getTenantId,TenantContextHolder.getTenantId())
                .eq(ElderlyInfoDO::getInStatus, BooleanEnum.TRUE.getValue()));
        return elderlyInfoDO != null;
    }

    /**
     * 更新长者中金蝶相关字段的信息
     * @param elderlyInfoDO
     */
    private void updateElderlyKingdeeInfo(ElderlyInfoDO elderlyInfoDO){
        kingdeeApi.syncBDCustomer(TenantContextHolder.getTenantId(),elderlyInfoDO.getId());
    }
}
