package cn.iocoder.yudao.module.system.service.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
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.enums.message.BpmMessageEnum;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.ElderlySyntheticAbilityPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.*;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.*;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum.CHECK_IN_HANDLE;
import static cn.iocoder.yudao.module.bpm.enums.message.BpmMessageEnum.SYNTHETIC_ABILITY_HANDLE;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.QR_CODE_HAS_BEEN_USED;

@Service
public class ElderlySyntheticAbilityServiceImpl implements ElderlySyntheticAbilityService {

    @Autowired
    private TenantMapper tenantMapper;
    @Autowired
    private ElderlyInfoMapper elderlyInfoMapper;
    @Autowired
    private ElderlySyntheticAbilityMapper elderlySyntheticAbilityMapper;
    @Autowired
    private ElderlySyntheticAbilityInfoMapper elderlySyntheticAbilityInfoMapper;
    @Autowired
    private SysEvaluationTemplatesMapper sysEvaluationTemplatesMapper;
    @Autowired
    private CheckInProcessSequenceMapper checkInProcessSequenceMapper;
    @Autowired
    private SysEvaluationProcessMapper sysEvaluationProcessMapper;
    @Autowired
    private ElderlyCheckInRecordMapper elderlyCheckInRecordMapper;
    @Autowired
    private ElderSyntheticAbilitySignMapper elderSyntheticAbilitySignMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private NotifyMessageSendApi notifyMessageSendApi;


    @Override
    public PageResult<ElderlySyntheticAbilityDO> queryPage(ElderlySyntheticAbilityPageReqVO pageVO) {
        Page<ElderlySyntheticAbilityDO> page = new Page<>(pageVO.getPageNo(), pageVO.getPageSize());
        List<ElderlySyntheticAbilityDO> list = elderlySyntheticAbilityMapper.queryPage(page, pageVO);
        for (ElderlySyntheticAbilityDO elderlySyntheticAbilityDO : list) {
            ElderlyInfoDO elderlyInfoDO = elderlyInfoMapper.selectById(elderlySyntheticAbilityDO.getElderId());
            if (elderlyInfoDO != null) {
                elderlySyntheticAbilityDO.setElder(elderlyInfoDO);
            }
        }
        return new PageResult<>(list, page.getTotal());

    }

    @Override
    public ElderlySyntheticAbilityDO getAdmissionAssessment(Long syntheticAbilityId) {
        ElderlySyntheticAbilityDO elderlySyntheticAbility = elderlySyntheticAbilityMapper.selectById(syntheticAbilityId);
        if (elderlySyntheticAbility != null) {
            if (StringUtils.isNotBlank(elderlySyntheticAbility.getQuestionnaireId())) {

                List<CheckInProcessSequenceDO> sequenceEntities = checkInProcessSequenceMapper.selectList(new LambdaQueryWrapper<CheckInProcessSequenceDO>()
                        .eq(CheckInProcessSequenceDO::getEvaluationProcessId, elderlySyntheticAbility.getQuestionnaireId())
                        .orderByAsc(CheckInProcessSequenceDO::getSort));

                if (CollectionUtil.isNotEmpty(sequenceEntities)) {
                    for (CheckInProcessSequenceDO sequenceEntity : sequenceEntities) {
                        SysEvaluationTemplatesDO templates = sysEvaluationTemplatesMapper.selectById(sequenceEntity.getTemplateId());
                        sequenceEntity.setTemplate(templates);
                    }
                }
                elderlySyntheticAbility.setProcessSequenceList(sequenceEntities);
            }

            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(Long.valueOf(elderlySyntheticAbility.getElderId()));
            if (elderlyInfo != null) {
//                elderlySyntheticAbility.setElderName(elderlyInfo.getElderName());
//                elderlySyntheticAbility.setElderSex(elderlyInfo.getElderSex() == null ? null : elderlyInfo.getElderSex());
//                elderlySyntheticAbility.setElderAge(elderlyInfo.getElderAge() == null ? null : elderlyInfo.getElderAge());
//                elderlySyntheticAbility.setBirthday(elderlyInfo.getBirthday() == null ? null : elderlyInfo.getBirthday());
//                elderlySyntheticAbility.setIdCard(elderlyInfo.getIdCard() == null ? null : elderlyInfo.getIdCard());

                elderlySyntheticAbility.setElder(elderlyInfo);
            }

            List<ElderlySyntheticAbilityInfoDO> elderlySyntheticAbilityInfoList = elderlySyntheticAbilityInfoMapper.selectList(new LambdaQueryWrapper<ElderlySyntheticAbilityInfoDO>().eq(ElderlySyntheticAbilityInfoDO::getSyntheticAbilityId, syntheticAbilityId));
            elderlySyntheticAbility.setSyntheticAbilityInfoList(elderlySyntheticAbilityInfoList);

        }
        return elderlySyntheticAbility;
    }

    @Override
    public Long addOrUpdate(ElderlySyntheticAbilityDO syntheticAbilityDO) {
        if (syntheticAbilityDO.getId() == null) {
            SysEvaluationProcessDO sysEvaluationProcess = sysEvaluationProcessMapper.selectById(syntheticAbilityDO.getQuestionnaireId());
            if (sysEvaluationProcess != null) {
                syntheticAbilityDO.setQuestionnaireType(sysEvaluationProcess.getType());
                syntheticAbilityDO.setQuestionnaireName(sysEvaluationProcess.getProcessName());
            } else {
                syntheticAbilityDO.setQuestionnaireType("2");
                syntheticAbilityDO.setQuestionnaireName("第三方评估");
            }

            String redisKey = "REDIS_EVALUATION_CODE:" + SecurityFrameworkUtils.getLoginUser().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);
            syntheticAbilityDO.setEvaluationCode(evaluationCode);
            syntheticAbilityDO.setStatus("0");
            syntheticAbilityDO.setCreateDate(LocalDateTime.now());
            elderlySyntheticAbilityMapper.insert(syntheticAbilityDO);


            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(syntheticAbilityDO.getElderId());
            if (elderlyInfo != null) {
                elderlyInfo.setElderHeight(syntheticAbilityDO.getElderHeight());
                elderlyInfo.setElderWeight(syntheticAbilityDO.getElderWeight());
                elderlyInfoMapper.updateById(elderlyInfo);
            }


            if (CollectionUtil.isNotEmpty(syntheticAbilityDO.getSyntheticAbilityInfoList())) {
                List<ElderlySyntheticAbilityInfoDO> syntheticAbilityInfoList = syntheticAbilityDO.getSyntheticAbilityInfoList();
                for (ElderlySyntheticAbilityInfoDO elderlySyntheticAbilityInfo : syntheticAbilityInfoList) {
                    elderlySyntheticAbilityInfo.setSyntheticAbilityId(syntheticAbilityDO.getId());
                    elderlySyntheticAbilityInfo.setCreatedTime(new Date());
                    elderlySyntheticAbilityInfoMapper.insert(elderlySyntheticAbilityInfo);
                }
            }

        } else {
            elderlySyntheticAbilityMapper.updateById(syntheticAbilityDO);
            if (CollectionUtil.isNotEmpty(syntheticAbilityDO.getSyntheticAbilityInfoList())) {
                elderlySyntheticAbilityInfoMapper.delete(new LambdaQueryWrapper<ElderlySyntheticAbilityInfoDO>().eq(ElderlySyntheticAbilityInfoDO::getSyntheticAbilityId, syntheticAbilityDO.getId()));

                List<ElderlySyntheticAbilityInfoDO> syntheticAbilityInfoList = syntheticAbilityDO.getSyntheticAbilityInfoList();
                for (ElderlySyntheticAbilityInfoDO elderlySyntheticAbilityInfo : syntheticAbilityInfoList) {
                    elderlySyntheticAbilityInfo.setSyntheticAbilityId(syntheticAbilityDO.getId());
                    elderlySyntheticAbilityInfo.setCreatedTime(new Date());
                    elderlySyntheticAbilityInfoMapper.insert(elderlySyntheticAbilityInfo);
                }
            }
            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(syntheticAbilityDO.getElderId());
            if (elderlyInfo != null) {
                elderlyInfo.setElderHeight(syntheticAbilityDO.getElderHeight());
                elderlyInfo.setElderWeight(syntheticAbilityDO.getElderWeight());
                elderlyInfoMapper.updateById(elderlyInfo);
            }
        }
        return syntheticAbilityDO.getId();
    }

    @Override
    @TenantIgnore
    public ElderlySyntheticAbilityDO getSyntheticAbilityInfoById(Long syntheticAbilityId) {
        ElderlySyntheticAbilityDO elderlySyntheticAbility = elderlySyntheticAbilityMapper.selectById(syntheticAbilityId);
        if (elderlySyntheticAbility != null) {
            List<ElderlySyntheticAbilityInfoDO> elderlySyntheticAbilityInfoList = elderlySyntheticAbilityInfoMapper
                    .selectList(new LambdaQueryWrapper<ElderlySyntheticAbilityInfoDO>()
                            .eq(ElderlySyntheticAbilityInfoDO::getSyntheticAbilityId, syntheticAbilityId));
            elderlySyntheticAbility.setSyntheticAbilityInfoList(elderlySyntheticAbilityInfoList);

            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(Long.valueOf(elderlySyntheticAbility.getElderId()));
            if (elderlyInfo != null) {
//                elderlySyntheticAbility.setElderName(elderlyInfo.getElderName());
//                elderlySyntheticAbility.setElderSex(elderlyInfo.getElderSex() == null ? null : elderlyInfo.getElderSex());
//                elderlySyntheticAbility.setElderAge(elderlyInfo.getElderAge() == null ? null : elderlyInfo.getElderAge());
//                elderlySyntheticAbility.setBirthday(elderlyInfo.getBirthday() == null ? null : elderlyInfo.getBirthday());
//                elderlySyntheticAbility.setIdCard(elderlyInfo.getIdCard() == null ? null : elderlyInfo.getIdCard());
                elderlySyntheticAbility.setElder(elderlyInfo);
            }
            List<CheckInProcessSequenceDO> sequenceEntities = checkInProcessSequenceMapper.selectList(new LambdaQueryWrapper<CheckInProcessSequenceDO>()
                    .eq(CheckInProcessSequenceDO::getEvaluationProcessId, elderlySyntheticAbility.getQuestionnaireId())
                    .orderByAsc(CheckInProcessSequenceDO::getSort));
            if (CollectionUtil.isNotEmpty(sequenceEntities)) {
                for (CheckInProcessSequenceDO sequenceEntity : sequenceEntities) {
                    SysEvaluationTemplatesDO templates = sysEvaluationTemplatesMapper.selectById(sequenceEntity.getTemplateId());
                    sequenceEntity.setTemplate(templates);
                }
            }
            elderlySyntheticAbility.setProcessSequenceList(sequenceEntities);
        }
        return elderlySyntheticAbility;
    }

    @Override
    public ElderlySyntheticAbilityInfoDO findElderlySyntheticAbilityInfo(Long syntheticAbilityInfoId) {
        return elderlySyntheticAbilityInfoMapper.selectById(syntheticAbilityInfoId);
    }

    @Override
    public Map<String, Object> generateSignInfo(Long syntheticAbilityId) {
        ElderlySyntheticAbilityDO elderlySyntheticAbility = elderlySyntheticAbilityMapper.selectById(syntheticAbilityId);
        String randomStr = RandomUtil.randomString(32);
        ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(Long.valueOf(elderlySyntheticAbility.getElderId()));

        Long tenantId = SecurityFrameworkUtils.getLoginUser().getTenantId();
        TenantDO tenantDO = tenantMapper.selectById(tenantId);

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("randomStr", randomStr);
        dataMap.put("syntheticAbilityId", syntheticAbilityId.toString());
        dataMap.put("elderName", elderlyInfo == null ? null : elderlyInfo.getElderName());
        dataMap.put("orgName", tenantDO == null ? null : tenantDO.getName());
        dataMap.put("type", 2);
        return dataMap;
    }

    @Override
    public Long addSignInfo(ElderSyntheticAbilitySignDO signDO) {
        signDO.setSignDate(new Date());
        elderSyntheticAbilitySignMapper.insert(signDO);

        Long elderSyntheticAbilityId = signDO.getElderSyntheticAbilityId();
        ElderlySyntheticAbilityDO elderlySyntheticAbility = elderlySyntheticAbilityMapper.selectById(elderSyntheticAbilityId);
        elderlySyntheticAbility.setSignType(1);
        elderlySyntheticAbilityMapper.updateById(elderlySyntheticAbility);

        notifyMessageSendApi.updateMessageByCodeAndPkMessage(BpmMessageEnum.SYNTHETIC_ABILITY_HANDLE.getTemplateCode(), elderlySyntheticAbility.getElderId());

        return signDO.getId();
    }

    @Override
    public void confirmSign(Long elderSyntheticAbilitySignId, String randomStr) {
        ElderSyntheticAbilitySignDO dbSign = elderSyntheticAbilitySignMapper.selectOne(new LambdaQueryWrapper<ElderSyntheticAbilitySignDO>()
                .eq(ElderSyntheticAbilitySignDO::getRandomStr, randomStr).eq(ElderSyntheticAbilitySignDO::getConfirmStatus, 1));
        if (dbSign != null) {
            throw exception(QR_CODE_HAS_BEEN_USED);
        }

        ElderSyntheticAbilitySignDO elderSyntheticAbilitySign = elderSyntheticAbilitySignMapper.selectOne(new LambdaQueryWrapper<ElderSyntheticAbilitySignDO>().eq(ElderSyntheticAbilitySignDO::getId, elderSyntheticAbilitySignId)
                .eq(ElderSyntheticAbilitySignDO::getRandomStr, randomStr));

        if (elderSyntheticAbilitySign != null) {
            elderSyntheticAbilitySign.setConfirmStatus(1);
            elderSyntheticAbilitySignMapper.updateById(elderSyntheticAbilitySign);

            ElderlySyntheticAbilityDO elderlySyntheticAbility = elderlySyntheticAbilityMapper.selectById(elderSyntheticAbilitySign.getElderSyntheticAbilityId());
            if (elderlySyntheticAbility != null) {
                elderlySyntheticAbility.setSignType(2);
                elderlySyntheticAbilityMapper.updateById(elderlySyntheticAbility);
            }
        }
    }

    @Override
    public ElderSyntheticAbilitySignDO getSignInfoById(Long syntheticAbilityId) {
        List<ElderSyntheticAbilitySignDO> elderSyntheticAbilitySigns = elderSyntheticAbilitySignMapper
                .selectList(new LambdaQueryWrapper<ElderSyntheticAbilitySignDO>()
                        .eq(ElderSyntheticAbilitySignDO::getElderSyntheticAbilityId, syntheticAbilityId).orderByDesc(ElderSyntheticAbilitySignDO::getSignDate));
        if (elderSyntheticAbilitySigns != null && !elderSyntheticAbilitySigns.isEmpty()) {
            return elderSyntheticAbilitySigns.stream().findFirst().get();
        }
        return null;
    }

    @Override
    public List<ElderlySyntheticAbilityDO> getByElderId(Long elderId, Integer evaluationAgencyType) {
        return elderlySyntheticAbilityMapper.selectList(new LambdaQueryWrapperX<ElderlySyntheticAbilityDO>()
                .eq(ElderlySyntheticAbilityDO::getElderId, elderId)
                .eqIfPresent(ElderlySyntheticAbilityDO::getEvaluationAgency, evaluationAgencyType));//根据类型查询
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        // 1) 先删明细
        elderlySyntheticAbilityInfoMapper.delete(new LambdaQueryWrapper<ElderlySyntheticAbilityInfoDO>()
                .eq(ElderlySyntheticAbilityInfoDO::getSyntheticAbilityId, id));
        // 2) 再删签名
        elderSyntheticAbilitySignMapper.delete(new LambdaQueryWrapper<ElderSyntheticAbilitySignDO>()
                .eq(ElderSyntheticAbilitySignDO::getElderSyntheticAbilityId, id));
        // 3) 最后删主表
        elderlySyntheticAbilityMapper.deleteById(id);
    }

    @Override
    public ElderlySyntheticAbilityDO findLatestByElderId(Long elderId) {
        Optional<ElderlySyntheticAbilityDO> optional = elderlySyntheticAbilityMapper.selectList(new LambdaQueryWrapperX<ElderlySyntheticAbilityDO>()
                .eq(ElderlySyntheticAbilityDO::getElderId, elderId)
                .orderByDesc(ElderlySyntheticAbilityDO::getCreateDate)).stream().findFirst();
        ElderlySyntheticAbilityDO elderlySyntheticAbilityDO = new ElderlySyntheticAbilityDO();
        if (optional.isPresent()) {
            elderlySyntheticAbilityDO = optional.get();
            List<ElderlySyntheticAbilityInfoDO> elderlySyntheticAbilityInfos = elderlySyntheticAbilityInfoMapper
                    .selectList(new LambdaQueryWrapperX<ElderlySyntheticAbilityInfoDO>()
                            .eq(ElderlySyntheticAbilityInfoDO::getSyntheticAbilityId, elderlySyntheticAbilityDO.getId()));
            elderlySyntheticAbilityDO.setSyntheticAbilityInfoList(elderlySyntheticAbilityInfos);

            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderId);
            elderlySyntheticAbilityDO.setElderName(elderlyInfo.getElderName());
            elderlySyntheticAbilityDO.setElderSex(elderlyInfo.getElderSex() == null ? null : elderlyInfo.getElderSex());
            elderlySyntheticAbilityDO.setElderAge(elderlyInfo.getElderAge() == null ? null : elderlyInfo.getElderAge());
            elderlySyntheticAbilityDO.setBirthday(elderlyInfo.getBirthday() == null ? null : elderlyInfo.getBirthday());
            elderlySyntheticAbilityDO.setIdCard(elderlyInfo.getIdCard() == null ? null : elderlyInfo.getIdCard());
            elderlySyntheticAbilityDO.setPapersType(elderlyInfo.getPapersType() == null ? null : elderlyInfo.getPapersType());
            return elderlySyntheticAbilityDO;
        } else {
            ElderlyInfoDO elderlyInfo = elderlyInfoMapper.selectById(elderId);
            elderlySyntheticAbilityDO.setElderName(elderlyInfo.getElderName());
            elderlySyntheticAbilityDO.setElderSex(elderlyInfo.getElderSex() == null ? null : elderlyInfo.getElderSex());
            elderlySyntheticAbilityDO.setElderAge(elderlyInfo.getElderAge() == null ? null : elderlyInfo.getElderAge());
            elderlySyntheticAbilityDO.setBirthday(elderlyInfo.getBirthday() == null ? null : elderlyInfo.getBirthday());
            elderlySyntheticAbilityDO.setIdCard(elderlyInfo.getIdCard() == null ? null : elderlyInfo.getIdCard());
            elderlySyntheticAbilityDO.setPapersType(elderlyInfo.getPapersType() == null ? null : elderlyInfo.getPapersType());
            return elderlySyntheticAbilityDO;
        }
    }
}
