package cn.iocoder.yudao.module.bpm.service.business;

import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.string.StringUtil;
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.aop.TenantIgnore;
import cn.iocoder.yudao.module.bpm.controller.admin.business.vo.*;
import cn.iocoder.yudao.module.bpm.dal.dataobject.business.BpmBusinessFormDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.business.BpmBusinessFormMapper;
import cn.iocoder.yudao.module.bpm.enums.BpmBusinessTypeEnum;
import cn.iocoder.yudao.module.system.api.bpm.BpmCheckInApi;
import cn.iocoder.yudao.module.system.api.bpm.BpmCheckInWaitApi;
import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyExpenseApi;
import cn.iocoder.yudao.module.system.api.bpm.vo.*;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.enums.change.ChangeTypeEnum;
import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyApi;
import cn.iocoder.yudao.module.system.api.bpm.BpmElderlyChangeApi;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.starter.annotation.LogRecord;
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.time.LocalDate;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.ELDERLY_ETREAT_DATE_CURRENT_NOT_EQUALS;
import static cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum.CHECK_IN_HANDLE;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.CONFIG_NOT_EXISTS;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.system.enums.LogRecordConstants.*;

/**
 * @Author: jinyd
 * @CreateTime: 2024/8/6  10:57
 * @Description: 老人申请入院 Service 实现类
 * @Version: 4.0
 */

@Service
@Validated
public class BpmElderlApplyServiceImpl implements BpmElderlApplyService {


    @Resource
    private BpmElderlyApi bpmElderlyApi;

    @Resource
    private BpmBusinessFormService bpmBusinessFormService;

    @Resource
    private BpmElderlyChangeApi elderlyChangeApi;
    @Resource
    private BpmCheckInApi checkInApi;

    @Resource
    private BpmCheckInWaitApi checkInWaitApi;

    @Resource
    private BpmBusinessFormMapper bpmBusinessFormMapper;

    @Autowired
    private NotifyMessageSendApi notifyMessageSendApi;

    @Resource
    private BpmElderlyExpenseApi elderlyExpenseApi;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = DMISSION_DISCHARGE_TYPE, subType = DMISSION_ELDER_APPLY_SUB_TYPE, bizNo = "{{#elderId}}",
            success = DMISSION_ELDER_APPLY_SUCCESS, extra = "{{#elderId}}")
    public Long createApplyAccommodation(Long userId, String nickname, BpmApplyAccommodationCreateReqVO createReqVO) {
        ElderlyInfoReqVO elderlyInfo = BeanUtils.toBean(createReqVO, ElderlyInfoReqVO.class);
        ElderlyRetreatRecordRespVO elderlyRetreatRecordRespVO = new ElderlyRetreatRecordRespVO();
        Long elderId = null;
        if (elderlyInfo.getId() == null) {
            if (bpmElderlyApi.checkElderExist(createReqVO.getIdCard())) {
                throw exception(ELDER_RECORD_EXISTS);
            }
            // 新增
            elderId = bpmElderlyApi.addElder(elderlyInfo);

        } else {
            // 编辑
            bpmElderlyApi.update(elderlyInfo);
            elderId = elderlyInfo.getId();
            // 将原本的删除，再重新生成
            // TODO 为什么需要删除后新增，不能直接新增或者修改(把其他属性设置为空)，如果是新增可以通过最新创建时间来进行查询
            bpmElderlyApi.delectRetreatRecordByElderId(elderId, createReqVO.getOrgType(), createReqVO.getTenantId());
        }

        elderlyRetreatRecordRespVO.setElderlyId(elderId);
        elderlyRetreatRecordRespVO.setRetreatDate(LocalDate.now());
        elderlyRetreatRecordRespVO.setApplyType(0);
        elderlyRetreatRecordRespVO.setOrgType(createReqVO.getOrgType());
        elderlyRetreatRecordRespVO.setTenantId(createReqVO.getTenantId());
        // 生成入住申请记录
        Long id = bpmElderlyApi.addElderlyRetreatRecord(elderlyRetreatRecordRespVO);
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(elderId);
        LogRecordContext.putVariable("elderId", elderId);
        createReqVO.setId(null);

        createReqVO.setId(createReqVO.getApplyAccommodationId());

        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);

        return bpmBusinessFormService.create(businessFormCreateReqVO);

    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = DMISSION_RETREAT_TYPE, subType = DMISSION_ELDER_RETREAT_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = DMISSION_ELDER_RETREAT_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long createApplyRetreat(Long userId, BpmApplyRetreatCreateReqVO createReqVO) {
        // 判断是否存在未缴费账单以及外出登记未返院
        elderlyExpenseApi.applyRetreatCheck(createReqVO.getElderlyId(),createReqVO.getCostDeadlineDate());
        ElderlyRetreatRecordRespVO elderlyRetreatRecordRespVO = BeanUtils.toBean(createReqVO, ElderlyRetreatRecordRespVO.class);
        LocalDate currentDate = LocalDate.now();
        String currentDateStr = currentDate.getYear() + "-" + currentDate.getMonthValue();
        String retreatDateStr = elderlyRetreatRecordRespVO.getRetreatDate().getYear() + "-" + elderlyRetreatRecordRespVO.getRetreatDate().getMonthValue();

//        String message = bpmElderlyApi.selectUnprocessedBills(elderlyRetreatRecordRespVO.getElderlyId(), elderlyRetreatRecordRespVO.getCostDeadlineDate());
//        if (StringUtil.isNotEmptyORNull(message)) {
//            throw exception(new ErrorCode(2_001_201_009, message));
//        }


//        if (!currentDateStr.equals(retreatDateStr)) {
//            throw exception(ELDERLY_ETREAT_DATE_CURRENT_NOT_EQUALS);
//        }
        elderlyRetreatRecordRespVO.setApplyType(1);
        if (elderlyRetreatRecordRespVO.getId() == null) {
            // 生成退住申请记录
            Long id = bpmElderlyApi.addElderlyRetreatRecord(elderlyRetreatRecordRespVO);
            createReqVO.setBusinessId(id);
        } else {
            // 将原本的删除，再重新生成
            // TODO 同创建
            bpmElderlyApi.deleteElderlyRetreatRecord(elderlyRetreatRecordRespVO.getId());
            elderlyRetreatRecordRespVO.setId(null);
            Long id = bpmElderlyApi.addElderlyRetreatRecord(elderlyRetreatRecordRespVO);
            // 编辑
            createReqVO.setBusinessId(id);
        }
        createReqVO.setId(null);
        createReqVO.setBusinessId2(elderlyRetreatRecordRespVO.getElderlyId());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(elderlyRetreatRecordRespVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_BED_CHANGE_TYPE, subType = ELDER_BED_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_BED_CHANGE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long bedChangeCreate(Long loginUserId, BedChangeRecordCreateReqVO createReqVO) {
        ElderlyChangeRecordReqVO changeRecordReqVO = BeanUtils.toBean(createReqVO, ElderlyChangeRecordReqVO.class);
        changeRecordReqVO.setChangeType(ChangeTypeEnum.BED.getValue());
        Long id = null;
        if (changeRecordReqVO.getId() == null) {
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        } else {
            elderlyChangeApi.updateCurrentFlag(changeRecordReqVO.getId());
            changeRecordReqVO.setId(null);
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        }
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(changeRecordReqVO.getElderlyId());
        createReqVO.setId(null);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(changeRecordReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_NURSE_CHANGE_TYPE, subType = ELDER_NURSE_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_NURSE_CHANGE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long nurseChangeCreate(Long loginUserId, NurseChangeRecordCreateReqVO createReqVO) {
        ElderlyChangeRecordReqVO changeRecordReqVO = BeanUtils.toBean(createReqVO, ElderlyChangeRecordReqVO.class);
        changeRecordReqVO.setChangeType(ChangeTypeEnum.NURSE.getValue());
        Long id = null;
        LocalDate changeDate = createReqVO.getChangeDate();
        // 判断是不是当前月份
//        if (changeDate.getMonthValue() != LocalDate.now().getMonthValue()) {
//            throw exception(NURSE_CHANGE_NOT_CURRENT_MONTH);
//        }
        if (changeRecordReqVO.getId() == null) {
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        } else {
            elderlyChangeApi.updateCurrentFlag(changeRecordReqVO.getId());
            changeRecordReqVO.setId(null);
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        }
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(changeRecordReqVO.getElderlyId());
        createReqVO.setId(null);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(changeRecordReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_CATERING_CHANGE_TYPE, subType = ELDER_CATERING_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_CATERING_CHANGE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long cateringChangeCreate(Long loginUserId, CateringChangeRecordCreateReqVO createReqVO) {
        ElderlyChangeRecordReqVO changeRecordReqVO = BeanUtils.toBean(createReqVO, ElderlyChangeRecordReqVO.class);
        changeRecordReqVO.setChangeType(ChangeTypeEnum.CATERING.getValue());
        Long id = null;
        if (changeRecordReqVO.getId() == null) {
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        } else {
            elderlyChangeApi.updateCurrentFlag(changeRecordReqVO.getId());
            changeRecordReqVO.setId(null);
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        }
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(changeRecordReqVO.getElderlyId());
        createReqVO.setId(null);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(changeRecordReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_PRICE_CHANGE_TYPE, subType = ELDER_PRICE_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_PRICE_CHANGE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long priceChangeCreate(Long loginUserId, PriceChangeRecordCreateReqVO createReqVO) {
        ElderlyChangeRecordReqVO changeRecordReqVO = BeanUtils.toBean(createReqVO, ElderlyChangeRecordReqVO.class);
        changeRecordReqVO.setChangeType(ChangeTypeEnum.PRICE.getValue());
        Long id = null;
        if (changeRecordReqVO.getId() == null) {
            Boolean checkResult = elderlyChangeApi.checkRepeat(createReqVO.getElderlyId(), createReqVO.getChangeDate(),
                    ChangeTypeEnum.PRICE.getValue(), createReqVO.getTenantId());
            if (checkResult) {
                throw exception(PRICE_CHANGE_RECORD_EXISTS);
            }
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        } else {
            elderlyChangeApi.updateCurrentFlag(changeRecordReqVO.getId());
            changeRecordReqVO.setId(null);
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
            elderlyChangeApi.delectPriceChange(id, changeRecordReqVO.getTenantId());
        }
        if (null != createReqVO.getPriceChangeList() && createReqVO.getPriceChangeList().size() > 0) {
            elderlyChangeApi.batchInsertOrUpdatePriceChange(createReqVO.getPriceChangeList(), id, changeRecordReqVO.getTenantId());
        }
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(changeRecordReqVO.getElderlyId());
        createReqVO.setId(null);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(changeRecordReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_TRANSFER_CHANGE_TYPE, subType = ELDER_TRANSFER_CHANGE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_TRANSFER_CHANGE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long transferChangeCreate(Long loginUserId, TransferChangeRecordCreateReqVO createReqVO) {
        ElderlyChangeRecordReqVO changeRecordReqVO = BeanUtils.toBean(createReqVO, ElderlyChangeRecordReqVO.class);
        changeRecordReqVO.setTenantId(createReqVO.getExpectId());
        createReqVO.setTenantId(createReqVO.getOriginalId());
        changeRecordReqVO.setChangeType(ChangeTypeEnum.TRANSFER.getValue());
        Long id = null;
        if (changeRecordReqVO.getId() == null) {
            Boolean checkResult = elderlyChangeApi.checkRepeat(createReqVO.getElderlyId(), createReqVO.getChangeDate(),
                    ChangeTypeEnum.TRANSFER.getValue(), createReqVO.getTenantId());
            if (checkResult) {
                throw exception(TRANSFER_CHANGE_RECORD_EXISTS);
            }
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
        } else {
            elderlyChangeApi.updateCurrentFlag(changeRecordReqVO.getId());
            changeRecordReqVO.setId(null);
            id = elderlyChangeApi.addElderlyBedChangeRecord(changeRecordReqVO);
            elderlyChangeApi.delectPriceChange(id, changeRecordReqVO.getTenantId());
        }
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(changeRecordReqVO.getElderlyId());
        createReqVO.setId(null);
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(changeRecordReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @LogRecord(type = ELDER_CHECK_IN_TYPE, subType = ELDER_CHECK_IN_CREATE_SUB_TYPE, bizNo = "{{#createReqVO.elderlyId}}",
            success = ELDER_CHECK_IN_CREATE_SUCCESS, extra = "{{#createReqVO.elderlyId}}")
    public Long checkInCreate(Long loginUserId, CheckInCreateReqVO createReqVO) {
        Long id = null;
//        Boolean checkResult = checkInApi.checkRepeat(createReqVO.getElderlyId());
//        if (checkResult) {
//            throw exception(CHECK_IN_RECORD_EXISTS);
//        }
        if (createReqVO.getId() == null) {
            checkInApi.updateCurrentFlagByElderId(createReqVO.getElderlyId());
            id = checkInApi.addCheckInRecord(createReqVO);

            // 床位绑定与释放
            checkInApi.bindBedByType(createReqVO, 0);
        } else {
            checkInApi.updateCurrentFlag(createReqVO.getId());
            createReqVO.setId(null);
            id = checkInApi.addCheckInRecord(createReqVO);
            checkInApi.bindBedByType(createReqVO, 1);
        }
        ElderlyInfoReqVO elderlyInfo = bpmElderlyApi.getElderlyInfo(createReqVO.getElderlyId());
        if (null != elderlyInfo) {
            LogRecordContext.putVariable("id", elderlyInfo.getId());
            LogRecordContext.putVariable("elderName", elderlyInfo.getElderName());
        }
        LogRecordContext.putVariable("nickname", SecurityFrameworkUtils.getLoginUserNickname());
        createReqVO.setBusinessId2(createReqVO.getElderlyId());
        createReqVO.setBusinessId(id);
        createReqVO.setType(BpmBusinessTypeEnum.CHECK_IN.getValue());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long checkInWaitCreate(Long loginUserId, String nickname, BpmCheckInWaitCreateReqVO createReqVO) {
        CheckInWaitCreateReqVO reqVO = BeanUtils.toBean(createReqVO, CheckInWaitCreateReqVO.class);
        reqVO.setStatus(1);
        Long id = checkInWaitApi.createCheckInWait(reqVO);
        createReqVO.setBusinessId(id);
        createReqVO.setBusinessId2(id);
        createReqVO.setType(BpmBusinessTypeEnum.CHECK_IN_WAIT.getValue());
        BpmBusinessFormCreateReqVO businessFormCreateReqVO = BeanUtils.toBean(createReqVO, BpmBusinessFormCreateReqVO.class);
        return bpmBusinessFormService.create(businessFormCreateReqVO);
    }
}
