package com.diagbot.facade;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.diagbot.dto.BasDeptInfoDTO;
import com.diagbot.dto.BehospitalInfoAgeDTO;
import com.diagbot.dto.CheckWorkDTO;
import com.diagbot.dto.MedicalRecordDTO;
import com.diagbot.entity.MedBehospitalType;
import com.diagbot.entity.MedCheckInfo;
import com.diagbot.entity.SysTaskCron;
import com.diagbot.entity.SysUser;
import com.diagbot.enums.CheckJobTypeEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.impl.MedBehospitalTypeServiceImpl;
import com.diagbot.service.impl.MedCheckInfoServiceImpl;
import com.diagbot.service.impl.MedicalRecordServiceImpl;
import com.diagbot.util.DateUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.util.SysUserUtils;
import com.diagbot.vo.CheckWorkPageVO;
import com.diagbot.vo.MedCheckWorkAddVO;
import com.diagbot.vo.RecordTypeVO;
import com.diagbot.vo.SysUserBaseVO;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @author songxl
 * @since 2021-05-11
 */
@Slf4j
@Component
public class MedCheckWorkFacade {
    @Autowired
    SysUserFacade sysUserFacade;
    @Autowired
    private MedCheckInfoServiceImpl medCheckInfoServiceImpl;
    @Autowired
    private MedCheckInfoFacade medCheckInfoFacade;
    @Autowired
    private MedBehospitalTypeServiceImpl medBehospitalTypeServiceImpl;
    @Autowired
    private MedicalRecordServiceImpl medicalRecordServiceImpl;
    @Autowired
    private SysTaskCronFacade sysTaskCronFacade;
    @Autowired
    private BehospitalInfoFacade behospitalInfoFacade;

    /**
     * @Author songxl
     * @Description 批量操作核查任务（增加和删除）
     * @Date 2021/5/11
     * @Param [medCheckWorkVO]
     * @Return java.lang.Boolean
     * @MethodName addCheck
     */
    public Boolean addCheckWork(MedCheckWorkAddVO medCheckWorkVO) {

        boolean flag = false;
        Date now = DateUtil.now();
        //获取核查任务类型(0-科室任务 1-院级 2-质控科)
        Integer workType = medCheckWorkVO.getJobType();
        //获取操作类型（0-取消，1-添加）
        Integer checkStatus = medCheckWorkVO.getCheckStatus();
        Long hospitalId = Long.parseLong(SysUserUtils.getCurrentHospitalID());
        Long principleId = Long.valueOf(SysUserUtils.getCurrentPrincipleID());
        SysUser user = sysUserFacade.getOne(new QueryWrapper<SysUser>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("id", principleId)
                .eq("status", 1));
        String principleName = user.getLinkman();
        //取消核查任务【操作类型（0-取消，1-添加）】
        if (checkStatus != null && checkStatus == 0) {
            //判断核查任务是否生成
            QueryWrapper<MedCheckInfo> medicalRecordQe = new QueryWrapper<>();
            medicalRecordQe.eq("hospital_id", hospitalId);
            medicalRecordQe.eq("is_deleted", IsDeleteEnum.N.getKey());
            if (medCheckWorkVO.getBehospitalCodeList().size() > 0) {
                medicalRecordQe.in("behospital_code", medCheckWorkVO.getBehospitalCodeList());
            }
            List<MedCheckInfo> list = medCheckInfoFacade.list(medicalRecordQe);
            if (ListUtil.isEmpty(list)) {
                throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL, "存在未生成核查任务！");
            }

            //创建用户集合
            Set<Long> creaters = list.stream().map(MedCheckInfo::getJobCreator).collect(Collectors.toSet());
            if (creaters != null) {
                //移除当前用户如果还有其他用户
                creaters.remove(principleId);
                if (creaters.size() > 0) {
                    throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL, "无法取消他人生成任务！");
                }
            }
            int i = medCheckInfoFacade.getBaseMapper().deleteBatchCodes(medCheckWorkVO.getBehospitalCodeList());
            if (i != 0) {
                return true;
            }
        } else if (checkStatus != null && checkStatus == 1) {
            //生成核查任务
            MedCheckInfo data = medCheckInfoFacade.getOne(new QueryWrapper<MedCheckInfo>()
                    .eq("is_deleted", IsDeleteEnum.N.getKey())
                    .eq("hospital_id", hospitalId)
                    .in("behospital_code", medCheckWorkVO.getBehospitalCodeList())
            );
            //任务是否存在
            if (data != null) {
                throw new CommonException(CommonErrorCode.UPDATE_INFO_FAIL, "核查任务已存在！");
            }

            //该病历没有核查的时候， 就添加核查记录
            List<MedCheckInfo> medCheckInfoList = new ArrayList<>();
            for (String behospitalCode : medCheckWorkVO.getBehospitalCodeList()) {
                MedCheckInfo medCheckInfo = new MedCheckInfo();
                medCheckInfo.setIsDeleted(IsDeleteEnum.N.getKey());
                medCheckInfo.setGmtCreate(now);
                medCheckInfo.setBehospitalCode(behospitalCode);
                medCheckInfo.setHospitalId(hospitalId);
                medCheckInfo.setCheckType(medCheckWorkVO.getCheckType());
                medCheckInfo.setJobCreator(principleId);
                medCheckInfo.setJobCreatorName(principleName);
                medCheckInfo.setJobCreateTime(now);
                medCheckInfo.setJobType(medCheckWorkVO.getJobType());
                medCheckInfoList.add(medCheckInfo);
            }
            flag = medCheckInfoServiceImpl.saveBatch(medCheckInfoList);
        }
        return flag;
    }

    /**
     * @Author songxl
     * @Description 获取每日住院患者的类型（出院、病危、抢救。。。）
     * @Date 2021/5/11
     * @Param [param]
     * @Return void
     * @MethodName execute
     */
    public void execute(String param) {
        JSONObject paramJson = JSONObject.parseObject(param);
        JSONObject typeValue = paramJson.getJSONObject("typeVal");
        JSONObject typeName = paramJson.getJSONObject("typeName");
        int searchSize = paramJson.getInteger("searchSize");
        int batchSize = paramJson.getInteger("batchSize");


        //定义批量插入的集合
        HashMap<String, MedBehospitalType> medBehospitalTypeMap = new HashMap<>();
        //1.获取有指定文书、没有患者类型的患者数据
        RecordTypeVO recordContentVO = new RecordTypeVO();
        recordContentVO.setModeList(new ArrayList<>(typeValue.keySet()));
        List<MedicalRecordDTO> medicalRecordList = medicalRecordServiceImpl.getMedicalRecord(recordContentVO);
        if (medicalRecordList != null && !medicalRecordList.isEmpty()) {
            getPatientRecordType(medBehospitalTypeMap, medicalRecordList, typeValue, typeName);
        }
        //2.批量执行插入操作
        try {
            if (medBehospitalTypeMap != null && medBehospitalTypeMap.size() > 0) {
                List<MedBehospitalType> medBehospitalTypeList = new ArrayList<>(medBehospitalTypeMap.values());
                medBehospitalTypeServiceImpl.saveOrUpdateBatch(medBehospitalTypeList, batchSize);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    /**
     * @Author songxl
     * @Description 获取患者类型存入批量插入map
     * @Date 2021/5/11
     * @Param [medBehospitalTypeMap, medicalRecordList, typeValue, typeName, hospiatlId]
     * @Return void
     * @MethodName getPatientRecordType
     */
    private void getPatientRecordType(HashMap<String, MedBehospitalType> medBehospitalTypeMap,
                                      List<MedicalRecordDTO> medicalRecordList,
                                      JSONObject typeValue,
                                      JSONObject typeName) {

        if (medicalRecordList == null || medicalRecordList.isEmpty()) {
            return;
        }
        //1.遍历查询出来的结果
        for (MedicalRecordDTO medicalRecordDTO : medicalRecordList) {
            //2.判断批量插入map中有没有这个患者
            if (medBehospitalTypeMap.containsKey(medicalRecordDTO.getBehospitalCode())) {
                //3.比较这两次的分值大小
                int lval = medBehospitalTypeMap.get(medicalRecordDTO.getBehospitalCode()).getValue();
                int nval = typeValue.getInteger(medicalRecordDTO.getModeId() + "");
                if (nval > lval) {
                    medBehospitalTypeMap.get(medicalRecordDTO.getBehospitalCode()).setValue(nval);
                    medBehospitalTypeMap.get(medicalRecordDTO.getBehospitalCode())
                            .setBehospitalType(typeName.getString(medicalRecordDTO.getModeId() + ""));
                }
            } else {
                //4.获取分值记录这个患者
                MedBehospitalType medBehospitalType = new MedBehospitalType();
                medBehospitalType.setBehospitalCode(medicalRecordDTO.getBehospitalCode());
                medBehospitalType.setBehospitalType(typeName.getString(medicalRecordDTO.getModeId() + ""));
                medBehospitalType.setValue(typeValue.getInteger(medicalRecordDTO.getModeId() + ""));
                medBehospitalType.setCreateTime(DateUtil.now());
                medBehospitalType.setHospitalId(medicalRecordDTO.getHospitalId());
                medBehospitalTypeMap.put(medicalRecordDTO.getBehospitalCode(), medBehospitalType);
            }
        }
    }


    /**
     * 分页
     *
     * @param checkWorkPageVO
     * @return
     */
    public IPage<CheckWorkDTO> pageFac(CheckWorkPageVO checkWorkPageVO) {
        checkWorkPageSet(checkWorkPageVO);
        IPage<CheckWorkDTO> res = medCheckInfoFacade.getBaseMapper().getCheckWorkPage(checkWorkPageVO);
        if (res == null || ListUtil.isEmpty(res.getRecords())) {
            return res;
        }

        List<String> behospitalCodes = res.getRecords().stream().map(CheckWorkDTO::getBehospitalCode).collect(Collectors.toList());
        Map<String, BehospitalInfoAgeDTO> ageMap = behospitalInfoFacade.getBehospitalInfoAge(checkWorkPageVO.getHospitalId(), behospitalCodes).stream().collect(Collectors.toMap(i -> i.getBehospitalCode(), i -> i));
        res.getRecords().forEach(i -> {
            i.setAge(ageMap.get(i.getBehospitalCode()) == null ? "" : ageMap.get(i.getBehospitalCode()).getAge());
        });

        //更新delFlag
        Long principleId = Long.valueOf(SysUserUtils.getCurrentPrincipleID());
        res.getRecords().stream().forEach(checkWorkDTO -> {
            if (principleId.equals(checkWorkDTO.getJobCreator())) {
                checkWorkDTO.setDelFlag(true);
            }
        });
        return res;
    }

    private void checkWorkPageSet(CheckWorkPageVO checkWorkPageVO) {
        //入参验证
        //出院时间
        if (null != checkWorkPageVO && null != checkWorkPageVO.getStartDate()) {
            checkWorkPageVO.setStartDate(DateUtil.getFirstTimeOfDay(checkWorkPageVO.getStartDate()));
        }
        if (null != checkWorkPageVO && null != checkWorkPageVO.getEndDate()) {
            checkWorkPageVO.setEndDate(DateUtil.getFirstTimeOfDay(DateUtil.addDay(checkWorkPageVO.getEndDate(), 1)));
        }
        if (null != checkWorkPageVO && null != checkWorkPageVO.getStartDate() && null != checkWorkPageVO.getEndDate()) {
            if (DateUtil.after(checkWorkPageVO.getStartDate(), checkWorkPageVO.getEndDate())) {
                throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "出院时间的开始时间必须小于结束时间！");
            }
        }
        //住院天数
        if (null != checkWorkPageVO && null != checkWorkPageVO.getSmallDay() && null != checkWorkPageVO.getBigDay()) {
            if (checkWorkPageVO.getSmallDay() > checkWorkPageVO.getBigDay()) {
                throw new CommonException(CommonErrorCode.PARAM_IS_ERROR, "住院天数区间有误！");
            }
        }
        checkWorkPageVO.setHospitalId(Long.parseLong(SysUserUtils.getCurrentHospitalID()));

        if (StringUtil.isNotBlank(checkWorkPageVO.getJobType()) && (CheckJobTypeEnum.DEPT_SUPERVISOR.getKey() + "").equals(checkWorkPageVO.getJobType())) {
            SysUserBaseVO sysUserBaseVO = new SysUserBaseVO();
            sysUserBaseVO.setUserId(Long.parseLong(SysUserUtils.getCurrentPrincipleID()));
            List<String> deptIds = Lists.newArrayList();
            List<BasDeptInfoDTO> selDepts = sysUserFacade.getUserDepts(sysUserBaseVO).getSelDepts();
            if (ListUtil.isNotEmpty(selDepts)) {
                deptIds = selDepts.stream().map(i -> i.getDeptId()).collect(Collectors.toList());
            }
            if (ListUtil.isNotEmpty(checkWorkPageVO.getDepartment())) {
                deptIds.retainAll(checkWorkPageVO.getDepartment());
            }
            if (ListUtil.isEmpty(deptIds)) {
                deptIds.add("999999999999");
            }
            checkWorkPageVO.setDepartment(deptIds);
        }
    }

    public boolean createMedBeHospitalInfoType() {
        //1.获取定时任务
        SysTaskCron task = sysTaskCronFacade.getOne(new QueryWrapper<SysTaskCron>()
                .eq("cron_code", "TASK019"), false);
        //2.执行定时任务
        if (null != task && StringUtil.isNotBlank(task.getCron())) {
            try {
                execute(task.getParam());
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
        return false;
    }
}
