package com.xinelu.manage.service.signpatientmanageroute.impl;

import com.xinelu.common.constant.TaskCreateTypeConstant;
import com.xinelu.common.core.domain.AjaxResult;
import com.xinelu.common.enums.NodeExecuteStatusEnum;
import com.xinelu.common.enums.TaskContentEnum;
import com.xinelu.common.enums.TaskCreateTypeEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.AgeUtil;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.manage.domain.patientquestionoptionresult.PatientQuestionOptionResult;
import com.xinelu.manage.domain.patientquestionsubjectresult.PatientQuestionSubjectResult;
import com.xinelu.manage.domain.patientquestionsubmitresult.PatientQuestionSubmitResult;
import com.xinelu.manage.domain.patienttaskexecuterecord.PatientTaskExecuteRecord;
import com.xinelu.manage.domain.signpatientmanageroute.SignPatientManageRoute;
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
import com.xinelu.manage.domain.signroutetriggercondition.SignRouteTriggerCondition;
import com.xinelu.manage.dto.manualfollowup.ManualFollowUpDTO;
import com.xinelu.manage.dto.patientquestionoptionresult.PatientQuestionOptionResultDTO;
import com.xinelu.manage.dto.patientquestionsubjectresult.PatientQuestionSubjectResultDTO;
import com.xinelu.manage.dto.patientquestionsubmitresult.PatientQuestionSubmitResultDTO;
import com.xinelu.manage.mapper.patientquestionoptionresult.PatientQuestionOptionResultMapper;
import com.xinelu.manage.mapper.patientquestionsubjectresult.PatientQuestionSubjectResultMapper;
import com.xinelu.manage.mapper.patientquestionsubmitresult.PatientQuestionSubmitResultMapper;
import com.xinelu.manage.mapper.patienttaskexecuterecord.PatientTaskExecuteRecordMapper;
import com.xinelu.manage.mapper.signpatientmanageroute.SignPatientManageRouteMapper;
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
import com.xinelu.manage.mapper.signroutetriggercondition.SignRouteTriggerConditionMapper;
import com.xinelu.manage.service.signpatientmanageroute.ISignPatientManageRouteService;
import com.xinelu.manage.vo.manualfollowup.ManualFollowPatientVO;
import com.xinelu.manage.vo.manualfollowup.ManualFollowUpVO;
import com.xinelu.manage.vo.signpatientmanageroute.SignPatientManageRouteVO;
import com.xinelu.manage.vo.signroutetriggercondition.SignRouteTriggerConditionVO;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;


/**
 * 签约患者管理任务路径Service业务层处理
 *
 * @author haown
 * @date 2024-03-18
 */
@Service
public class SignPatientManageRouteServiceImpl implements ISignPatientManageRouteService {
    @Resource
    private SignPatientManageRouteMapper signPatientManageRouteMapper;
    @Resource
    private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
    @Resource
    private PatientTaskExecuteRecordMapper patientTaskExecuteRecordMapper;
    @Resource
    private PatientQuestionSubmitResultMapper patientQuestionSubmitResultMapper;
    @Resource
    private PatientQuestionSubjectResultMapper patientQuestionSubjectResultMapper;
    @Resource
    private PatientQuestionOptionResultMapper patientQuestionOptionResultMapper;
    @Resource
    private SignRouteTriggerConditionMapper signRouteTriggerConditionMapper;

    /**
     * 查询签约患者管理任务路径
     *
     * @param id 签约患者管理任务路径主键
     * @return 签约患者管理任务路径
     */
    @Override
    public SignPatientManageRouteVO selectSignPatientManageRouteById(Long id) {
        return signPatientManageRouteMapper.selectSignPatientManageRoute(id);
    }

    /**
     * 查询签约患者管理任务路径列表
     *
     * @param signPatientManageRoute 签约患者管理任务路径
     * @return 签约患者管理任务路径
     */
    @Override
    public List<SignPatientManageRoute> selectSignPatientManageRouteList(SignPatientManageRoute signPatientManageRoute) {
        return signPatientManageRouteMapper.selectSignPatientManageRouteList(signPatientManageRoute);
    }

    /**
     * 新增签约患者管理任务路径
     *
     * @param signPatientManageRoute 签约患者管理任务路径
     * @return 结果
     */
    @Override
    public AjaxResult insertSignPatientManageRoute(SignPatientManageRouteVO signPatientManageRoute) {
        //新增主表
        signPatientManageRoute.setTaskCreateType(TaskCreateTypeEnum.MANUAL_CREATE.getInfo());
        signPatientManageRoute.setCreateBy(SecurityUtils.getUsername());
        signPatientManageRoute.setCreateTime(LocalDateTime.now());
        int insertRoute = signPatientManageRouteMapper.insertSignPatientManageRoute(signPatientManageRoute);
        if (insertRoute < 0) {
            return AjaxResult.error("新增签约患者管理任务路径失败！请联系管理员！");
        }
        //新增节点表
        List<SignPatientManageRouteNode> signPatientManageRouteNodes = new ArrayList<>();
        SignPatientManageRouteNode signPatientManageRouteNode = new SignPatientManageRouteNode();
        for (SignPatientManageRouteNode routeNode : signPatientManageRoute.getRouteNodeList()) {
            extracted(signPatientManageRoute, signPatientManageRouteNodes, signPatientManageRouteNode, routeNode);
        }
        int insertBatchCount = signPatientManageRouteNodeMapper.insertBatch(signPatientManageRouteNodes);
        if (insertBatchCount < 0) {
            return AjaxResult.error("新增签约患者管理任务路径失败！请联系管理员！");
        }
        List<SignRouteTriggerCondition> signRouteTriggerConditions = new ArrayList<SignRouteTriggerCondition>();
        for (SignRouteTriggerConditionVO signRouteTriggerCondition : signPatientManageRoute.getTriggerConditionList()) {
            SignRouteTriggerCondition triggerCondition = new SignRouteTriggerCondition();
            signRouteTriggerCondition.setPatientManageRouteId(signPatientManageRoute.getId());
            signRouteTriggerCondition.setCreateTime(LocalDateTime.now());
            signRouteTriggerCondition.setCreateBy(SecurityUtils.getUsername());
            BeanUtils.copyBeanProp(triggerCondition, signRouteTriggerCondition);
            signRouteTriggerConditions.add(triggerCondition);
        }
        int insertTriggerCondition = signRouteTriggerConditionMapper.insertBatch(signRouteTriggerConditions);
        if (insertTriggerCondition < 0) {
            return AjaxResult.error("新增签约患者管理任务路径失败！请联系管理员！");
        }
        return AjaxResult.success();
    }


    /**
     * 修改签约患者管理任务路径
     *
     * @param signPatientManageRoute 签约患者管理任务路径
     * @return 结果
     */
    @Override
    public AjaxResult updateSignPatientManageRoute(SignPatientManageRouteVO signPatientManageRoute) {
        int deleteRouteNodeCount = signPatientManageRouteNodeMapper.deleteRouteNodeByManageRouteId(signPatientManageRoute.getSignPatientManageRouteId());
        if (deleteRouteNodeCount < 0) {
            return AjaxResult.error("修改签约患者管理任务路径失败！请联系管理员！");
        }
        int deleteConditionCount = signRouteTriggerConditionMapper.deleteConditionByPatientManageRouteId(signPatientManageRoute.getSignPatientManageRouteId());
        if (deleteConditionCount < 0) {
            return AjaxResult.error("修改签约患者管理任务路径失败！请联系管理员！");
        }
        signPatientManageRoute.setUpdateBy(SecurityUtils.getUsername());
        signPatientManageRoute.setUpdateTime(LocalDateTime.now());
        int updateCount = signPatientManageRouteMapper.updateSignPatientManageRoute(signPatientManageRoute);
        if (updateCount < 0) {
            return AjaxResult.error("修改签约患者管理任务路径失败！请联系管理员！");
        }
        List<SignPatientManageRouteNode> routeNodeList = signPatientManageRoute.getRouteNodeList();
        for (SignPatientManageRouteNode signPatientManageRouteNode : routeNodeList) {
            signPatientManageRouteNode.setManageRouteId(signPatientManageRoute.getSignPatientManageRouteId());
            signPatientManageRouteNode.setCreateTime(LocalDateTime.now());
            signPatientManageRouteNode.setCreateBy(SecurityUtils.getUsername());
        }
        int insertBatchCount = signPatientManageRouteNodeMapper.insertBatch(routeNodeList);
        if (insertBatchCount < 0) {
            return AjaxResult.error("新增签约患者管理任务路径失败！请联系管理员！");
        }
        List<SignRouteTriggerCondition> signRouteTriggerConditions = new ArrayList<>();
        for (SignRouteTriggerConditionVO signRouteTriggerCondition : signPatientManageRoute.getTriggerConditionList()) {
            SignRouteTriggerCondition triggerCondition = new SignRouteTriggerCondition();
            signRouteTriggerCondition.setCreateTime(LocalDateTime.now());
            signRouteTriggerCondition.setPatientManageRouteId(signPatientManageRoute.getId());
            signRouteTriggerCondition.setCreateBy(SecurityUtils.getUsername());
            BeanUtils.copyBeanProp(triggerCondition, signRouteTriggerCondition);
            signRouteTriggerConditions.add(triggerCondition);
        }
        int insertTriggerCondition = signRouteTriggerConditionMapper.insertBatch(signRouteTriggerConditions);
        if (insertTriggerCondition < 0) {
            return AjaxResult.error("新增签约患者管理任务路径失败！请联系管理员！");
        }
        return AjaxResult.success();
    }

    /**
     * 批量删除签约患者管理任务路径
     *
     * @param ids 需要删除的签约患者管理任务路径主键
     * @return 结果
     */
    @Override
    public int deleteSignPatientManageRouteByIds(Long[] ids) {
        return signPatientManageRouteMapper.deleteSignPatientManageRouteByIds(ids);
    }

    /**
     * 删除签约患者管理任务路径信息
     *
     * @param id 签约患者管理任务路径主键
     * @return 结果
     */
    @Override
    public int deleteSignPatientManageRouteById(Long id) {
        return signPatientManageRouteMapper.deleteSignPatientManageRouteById(id);
    }

    /**
     * 查询人工随访代办列表
     *
     * @param manualFollowUpDTO 人工随访查询DTO
     * @return ManualFollowUpVO 人工随访代办VO
     */
    @Override
    public List<ManualFollowUpVO> selectManualFollowUpList(ManualFollowUpDTO manualFollowUpDTO) {
        return signPatientManageRouteMapper.selectManualFollowUpList(manualFollowUpDTO);
    }

    /**
     * 查询人工随访患者基本信息
     *
     * @param id 签约患者管理任务表id
     * @return 人工随访患者基本信息VO
     */
    @Override
    public AjaxResult selectFollowPatientInfo(Long id) {
        ManualFollowPatientVO patientVO = signPatientManageRouteMapper.selectFollowPatientInfo(id);
        // 设置年龄
        patientVO.setAge(AgeUtil.getAgeMonth(patientVO.getBirthDate().toString()));
        if (ObjectUtils.isEmpty(patientVO)) {
            return AjaxResult.error("患者信息不存在！");
        }
        return AjaxResult.success(patientVO);
    }

    /**
     * 人工随访代办处理
     *
     * @param dto 患者问卷提交结果信息表DTO
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult addPatientQuestionResult(PatientQuestionSubmitResultDTO dto) {
        String routeHandlePerson = dto.getRouteHandlePerson();
        LocalDateTime time = LocalDateTime.now();
        // 如果任务类型是电话外呼，更新节点任务表，新增患者管理任务执行记录
        if (dto.getTaskType().equals(TaskContentEnum.PHONE_OUTBOUND.getInfo())) {
            // 更新节点任务表
            updateSignPatientManageRouteNode(dto, routeHandlePerson, time);
            // 新增患者管理任务执行记录
            insertPatientTaskExecuteRecord(dto, routeHandlePerson, time);
        } else {
            // 如果任务类型不是电话外呼,更新节点任务表,新增患者管理任务执行记录,新增问卷提交结果表、题目表、选项表
            // 更新节点任务表
            updateSignPatientManageRouteNode(dto, routeHandlePerson, time);
            // 新增患者管理任务执行记录
            Long taskExecuteRecordId = insertPatientTaskExecuteRecord(dto, routeHandlePerson, time);
            PatientQuestionSubmitResult patientQuestionSubmitResult = new PatientQuestionSubmitResult();
            BeanUtils.copyBeanProp(patientQuestionSubmitResult, dto);
            patientQuestionSubmitResult.setCreateBy(routeHandlePerson);
            patientQuestionSubmitResult.setCreateTime(time);
            patientQuestionSubmitResult.setTaskExecuteRecordId(taskExecuteRecordId);
            // 新增患者问卷提交结果
            if (patientQuestionSubmitResultMapper.insertPatientQuestionSubmitResult(patientQuestionSubmitResult) <= 0) {
                throw new ServiceException("新增患者问卷提交结果失败");
            }
            // 获取到患者问卷题目提交结果信息DTO
            List<PatientQuestionSubjectResultDTO> subjectResultList = dto.getSubjectResultDTOList();
            // 初始化患者问卷题目提交结果信息
            List<PatientQuestionSubjectResult> patientQuestionSubjectResults = new ArrayList<>();
            // 获取到患者问卷题目选项提交结果DTO
            List<PatientQuestionOptionResultDTO> patientQuestionOptionResults = new ArrayList<>();
            for (PatientQuestionSubjectResultDTO questionSubjectResult : subjectResultList) {
                PatientQuestionSubjectResult saveQuestionSubject = new PatientQuestionSubjectResult();
                BeanUtils.copyBeanProp(saveQuestionSubject, questionSubjectResult);
                saveQuestionSubject.setQuestionSubmitResultId(patientQuestionSubmitResult.getId());
                saveQuestionSubject.setCreateBy(routeHandlePerson);
                saveQuestionSubject.setCreateTime(time);
                patientQuestionSubjectResults.add(saveQuestionSubject);
                patientQuestionOptionResults.addAll(questionSubjectResult.getOptionResultList());
            }
            // 新增患者问卷题目提交结果
            if (patientQuestionSubjectResultMapper.saveQuestionSubjectList(patientQuestionSubjectResults) <= 0) {
                throw new ServiceException("新增患者问卷题目提交结果失败");
            }
            // 初始化患者问卷题目选项提交结果
            List<PatientQuestionOptionResult> saveQuestionSubjectOptions = new ArrayList<>();
            for (PatientQuestionOptionResultDTO patientQuestionOptionResult : patientQuestionOptionResults) {
                PatientQuestionOptionResult saveQuestionOption = new PatientQuestionOptionResult();
                BeanUtils.copyBeanProp(saveQuestionOption, patientQuestionOptionResult);
                // 从已保存的患者问卷题目结果列表中查找当前选项所对应的题目结果
                PatientQuestionSubjectResult patientQuestionSubjectResult = patientQuestionSubjectResults.stream().filter(Objects::nonNull).filter(item -> Objects.nonNull(item.getQuestionNumber()) && patientQuestionOptionResult.getQuestionNumber().compareTo(item.getQuestionNumber()) == 0).findFirst().orElse(new PatientQuestionSubjectResult());
                saveQuestionOption.setQuestionSubjectResultId(patientQuestionSubjectResult.getId());
                saveQuestionOption.setCreateTime(time);
                saveQuestionOption.setCreateBy(routeHandlePerson);
                saveQuestionSubjectOptions.add(saveQuestionOption);
            }
            // 新增患者问卷题目选项提交结果
            if (patientQuestionOptionResultMapper.saveQuestionOptionList(saveQuestionSubjectOptions) <= 0) {
                throw new ServiceException("新增患者问卷题目选项提交结果失败");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 新增患者管理任务执行记录
     */
    private Long insertPatientTaskExecuteRecord(PatientQuestionSubmitResultDTO dto, String routeHandlePerson, LocalDateTime time) {
        PatientTaskExecuteRecord patientTaskExecuteRecord = new PatientTaskExecuteRecord();
        BeanUtils.copyProperties(dto, patientTaskExecuteRecord);
        patientTaskExecuteRecord.setTaskContent(dto.getTaskType());
        patientTaskExecuteRecord.setExecuteTime(time);
        patientTaskExecuteRecord.setExecutePerson(routeHandlePerson);
        patientTaskExecuteRecord.setExecuteType(TaskCreateTypeConstant.MANUAL_CREATE);
        patientTaskExecuteRecord.setCreateBy(routeHandlePerson);
        patientTaskExecuteRecord.setCreateTime(time);
        if (patientTaskExecuteRecordMapper.insertPatientTaskExecuteRecord(patientTaskExecuteRecord) > 0) {
            return patientTaskExecuteRecord.getId();
        } else {
            throw new ServiceException("新增患者管理任务记录失败");
        }
    }

    /**
     * 更新节点任务表
     */
    private void updateSignPatientManageRouteNode(PatientQuestionSubmitResultDTO dto, String routeHandlePerson, LocalDateTime time) {
        SignPatientManageRouteNode signPatientManageRouteNode = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeById(dto.getManageRouteNodeId());
        signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.EXECUTED.toString());
        signPatientManageRouteNode.setRouteHandleRemark(dto.getRouteHandleRemark());
        signPatientManageRouteNode.setRouteHandleId(dto.getRouteHandleId());
        signPatientManageRouteNode.setRouteHandlePerson(routeHandlePerson);
        signPatientManageRouteNode.setUpdateBy(routeHandlePerson);
        signPatientManageRouteNode.setUpdateTime(time);
        // 更新节点任务表
        if (signPatientManageRouteNodeMapper.updateSignPatientManageRouteNode(signPatientManageRouteNode) <= 0) {
            throw new ServiceException("更新节点任务表失败");
        }
    }

    /**
     * 塞值
     */
    private static void extracted(SignPatientManageRouteVO signPatientManageRoute, List<SignPatientManageRouteNode> signPatientManageRouteNodes, SignPatientManageRouteNode signPatientManageRouteNode, SignPatientManageRouteNode routeNode) {
        if (Objects.nonNull(routeNode) && TaskContentEnum.PHONE_OUTBOUND.getInfo().equals(routeNode.getTaskType())) {
            signPatientManageRouteNode.setPhonePushSign(Objects.isNull(routeNode.getPhonePushSign()) ? null : routeNode.getPhonePushSign());
            signPatientManageRouteNode.setPhoneId(Objects.isNull(routeNode.getPhoneId()) ? null : routeNode.getPhoneId());
            signPatientManageRouteNode.setPhoneTemplateId(Objects.isNull(routeNode.getPhoneTemplateId()) ? null : routeNode.getPhoneTemplateId());
            signPatientManageRouteNode.setPhoneTemplateName(StringUtils.isBlank(routeNode.getPhoneTemplateName()) ? null : routeNode.getPhoneTemplateName());
            signPatientManageRouteNode.setPhoneNodeContent(StringUtils.isBlank(routeNode.getPhoneNodeContent()) ? null : routeNode.getPhoneNodeContent());
            signPatientManageRouteNode.setPhoneRedialTimes(StringUtils.isBlank(routeNode.getPhoneRedialTimes()) ? null : routeNode.getPhoneRedialTimes());
            signPatientManageRouteNode.setPhoneTimeInterval(Objects.isNull(routeNode.getPhoneTimeInterval()) ? null : routeNode.getPhoneTimeInterval());
        }
        if (Objects.nonNull(routeNode) && TaskContentEnum.QUESTIONNAIRE_SCALE.getInfo().equals(routeNode.getTaskType())) {
            signPatientManageRouteNode.setQuestionInfoId(Objects.isNull(routeNode.getQuestionInfoId()) ? null : routeNode.getQuestionInfoId());
            signPatientManageRouteNode.setQuestionnaireName(StringUtils.isBlank(routeNode.getQuestionnaireName()) ? null : routeNode.getQuestionnaireName());
            signPatientManageRouteNode.setQuestionnaireContent(StringUtils.isBlank(routeNode.getQuestionnaireContent()) ? null : routeNode.getQuestionnaireContent());
            signPatientManageRouteNode.setQuestionExpirationDate(Objects.isNull(routeNode.getQuestionExpirationDate()) ? null : routeNode.getQuestionExpirationDate());
        }
        if (Objects.nonNull(routeNode) && TaskContentEnum.PROPAGANDA_ARTICLE.getInfo().equals(routeNode.getTaskType())) {
            signPatientManageRouteNode.setPropagandaInfoId(Objects.isNull(routeNode.getPropagandaInfoId()) ? null : routeNode.getPropagandaInfoId());
            signPatientManageRouteNode.setPropagandaTitle(StringUtils.isBlank(routeNode.getPropagandaTitle()) ? null : routeNode.getPropagandaTitle());
            signPatientManageRouteNode.setPropagandaContent(StringUtils.isBlank(routeNode.getPropagandaContent()) ? null : routeNode.getPropagandaContent());
        }
        if (Objects.nonNull(routeNode) && TaskContentEnum.TEXT_REMIND.getInfo().equals(routeNode.getTaskType())) {
            signPatientManageRouteNode.setTextRemindContent(StringUtils.isBlank(routeNode.getTextRemindContent()) ? null : routeNode.getTextRemindContent());
        }
        if (Objects.nonNull(routeNode) && TaskContentEnum.ARTIFICIAL_FOLLOW_UP.getInfo().equals(routeNode.getTaskType())) {
            signPatientManageRouteNode.setFollowTemplateId(Objects.isNull(routeNode.getFollowTemplateId()) ? null : routeNode.getFollowTemplateId());
            signPatientManageRouteNode.setFollowContent(StringUtils.isBlank(routeNode.getFollowContent()) ? null : routeNode.getFollowContent());
            signPatientManageRouteNode.setFollowTemplateName(StringUtils.isBlank(routeNode.getFollowTemplateName()) ? null : routeNode.getFollowTemplateName());
        }
        signPatientManageRouteNode.setManageRouteId(signPatientManageRoute.getId());
        signPatientManageRouteNode.setManageRouteName(signPatientManageRoute.getRouteName());
        signPatientManageRouteNode.setNodeExecuteStatus(NodeExecuteStatusEnum.UNEXECUTED.getInfo());
        signPatientManageRouteNode.setTaskType(routeNode.getTaskType());
        signPatientManageRouteNode.setRouteNodeName(routeNode.getRouteNodeName());
        signPatientManageRouteNode.setRouteNodeDay(routeNode.getRouteNodeDay());
        signPatientManageRouteNode.setCreateTime(LocalDateTime.now());
        signPatientManageRouteNode.setCreateBy(SecurityUtils.getUsername());
        signPatientManageRouteNodes.add(signPatientManageRouteNode);
    }
}
