package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.diagbot.dto.BehospitalInfoAgeDTO;
import com.diagbot.dto.CheckedRecordListDTO;
import com.diagbot.dto.SysUserDeptDTO;
import com.diagbot.entity.BasDeptInfo;
import com.diagbot.entity.MedAppealInfo;
import com.diagbot.entity.MedBehospitalType;
import com.diagbot.entity.MedCheckInfo;
import com.diagbot.entity.SysUserDept;
import com.diagbot.entity.SysUserRole;
import com.diagbot.enums.CheckJobTypeEnum;
import com.diagbot.enums.CheckStatusEnum;
import com.diagbot.enums.CheckTypeEnum;
import com.diagbot.enums.CheckerRoleEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.MedQcresultDetailService;
import com.diagbot.service.impl.MedBehospitalTypeServiceImpl;
import com.diagbot.util.DateUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.util.SysUserUtils;
import com.diagbot.vo.CheckedRecordListVO;
import com.diagbot.vo.MedCheckInfoAddVO;
import com.diagbot.vo.RecordCheckVO;
import com.diagbot.vo.SysUserBaseVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @author: rengb
 * @time: 2021/5/17 18:43
 */
@Component
public class RecordCheckFacade {

    @Autowired
    SysUserFacade sysUserFacade;
    @Autowired
    SysUserDeptFacade sysUserDeptFacade;
    @Autowired
    SysUserRoleFacade sysUserRoleFacade;
    @Autowired
    MedCheckInfoFacade medCheckInfoFacade;
    @Autowired
    MedQcresultDetailService medQcresultDetailService;
    @Autowired
    BehospitalInfoFacade behospitalInfoFacade;
    @Autowired
    BasDeptInfoFacade basDeptInfoFacade;
    @Autowired
    MedBehospitalTypeServiceImpl medBehospitalTypeServiceImpl;
    @Autowired
    private SysHospitalSetFacade sysHospitalSetFacade;
    @Autowired
    private MedAppealInfoManagementFacade appealInfoManagementFacade;

    public IPage<CheckedRecordListDTO> checkedRecordList(CheckedRecordListVO checkedRecordListVO) {
        Long hospitalId = Long.parseLong(SysUserUtils.getCurrentHospitalID());
        Long userId = Long.parseLong(SysUserUtils.getCurrentPrincipleID());
        SysUserBaseVO sysUserBaseVO = new SysUserBaseVO();
        sysUserBaseVO.setUserId(userId);
        List<Long> roleIds = sysUserFacade.getUserRoles(sysUserBaseVO).getSelRoles().stream().map(i -> i.getId()).collect(Collectors.toList());
        List<String> deptIds = Lists.newArrayList();
        SysUserDeptDTO sysUserDeptDTO = sysUserFacade.getUserDepts(sysUserBaseVO);
        if (ListUtil.isNotEmpty(sysUserDeptDTO.getSelDepts())) {
            deptIds.addAll(sysUserDeptDTO.getSelDepts().stream().map(i -> i.getDeptId()).collect(Collectors.toList()));
        }
        //1.2去除质管科
        BasDeptInfo deptInfo = basDeptInfoFacade.getOne(new QueryWrapper<BasDeptInfo>()
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .eq("hospital_id", hospitalId)
                .eq("station", "质管"));
        if (deptInfo == null || deptInfo.getDeptId() == null) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "科室质管科不存在,请联系管理员!");
        }
        List<Long> userIds = Lists.newArrayList();
        List<String> JobTypes = Lists.newArrayList();
        roleIds.forEach(roleId -> {
            if (roleId.intValue() == CheckerRoleEnum.HOSP_SUPERVISOR.getKey()
                    && (ListUtil.isEmpty(checkedRecordListVO.getCheckJobTypes()) || checkedRecordListVO.getCheckJobTypes().contains(CheckJobTypeEnum.HOSP_SUPERVISOR.getKey() + ""))) {
                userIds.addAll(getUserIdsOfRoleId(hospitalId, null, CheckerRoleEnum.HOSP_GENERAL.getKey()));
                JobTypes.add(CheckJobTypeEnum.HOSP_SUPERVISOR.getKey() + "");
            } else if (roleId.intValue() == CheckerRoleEnum.QUAT_SUPERVISOR.getKey()
                    && (ListUtil.isEmpty(checkedRecordListVO.getCheckJobTypes()) || checkedRecordListVO.getCheckJobTypes().contains(CheckJobTypeEnum.QUAT_SUPERVISOR.getKey() + ""))) {
                //添加质管科人员
                deptIds.add(deptInfo.getDeptId());
                userIds.addAll(getUserIdsOfRoleId(hospitalId, deptIds, CheckerRoleEnum.QUAT_GENERAL.getKey()));
                JobTypes.add(CheckJobTypeEnum.QUAT_SUPERVISOR.getKey() + "");
            } else if (roleId.intValue() == CheckerRoleEnum.DEPT_SUPERVISOR.getKey() && ListUtil.isNotEmpty(deptIds)
                    && (ListUtil.isEmpty(checkedRecordListVO.getCheckJobTypes()) || checkedRecordListVO.getCheckJobTypes().contains(CheckJobTypeEnum.DEPT_SUPERVISOR.getKey() + ""))) {
                //移除质管科人员
                deptIds.remove(deptInfo.getDeptId());
                JobTypes.add(CheckJobTypeEnum.DEPT_SUPERVISOR.getKey() + "");
                userIds.addAll(getUserIdsOfRoleId(hospitalId, deptIds, CheckerRoleEnum.DEPT_GENERAL.getKey()));
            } else if ((roleId.intValue() == CheckerRoleEnum.DEPT_GENERAL.getKey() && ListUtil.isNotEmpty(deptIds))
                    || roleId.intValue() == CheckerRoleEnum.QUAT_GENERAL.getKey() || roleId.intValue() == CheckerRoleEnum.HOSP_GENERAL.getKey()) {
                userIds.add(userId);
            }
        });

        //如果用户是质控科核查人员，在不传入任务类型的时候要添加质控科任务类型进行筛选
        if (roleIds.contains(CheckerRoleEnum.QUAT_GENERAL.getKey() * 1l)) {
            JobTypes.add(CheckJobTypeEnum.QUAT_SUPERVISOR.getKey() + "");
        }
        if (roleIds.contains(CheckerRoleEnum.DEPT_GENERAL.getKey() * 1l)) {
            JobTypes.add(CheckJobTypeEnum.DEPT_SUPERVISOR.getKey() + "");
        }
        if (roleIds.contains(CheckerRoleEnum.HOSP_GENERAL.getKey() * 1l)) {
            JobTypes.add(CheckJobTypeEnum.HOSP_SUPERVISOR.getKey() + "");
        }

        if (ListUtil.isEmpty(checkedRecordListVO.getCheckJobTypes())) {
            checkedRecordListVO.setCheckJobTypes(JobTypes);
        }
        if (ListUtil.isEmpty(userIds)) {
            userIds.add(999999999999999999l);
        }
        checkedRecordListVO.setCurrentDeptIds(String.join(",", deptIds));
        checkedRecordListVO.setCurrentGeneralUserIds(userIds);
        checkedRecordListVO.setHospitalId(hospitalId);
        IPage<CheckedRecordListDTO> iPage = medCheckInfoFacade.getBaseMapper().checkedRecordList(checkedRecordListVO);

        if (ListUtil.isNotEmpty(iPage.getRecords())) {
            List<String> behospitalCodes = iPage.getRecords().stream().map(i -> i.getBehospitalCode()).collect(Collectors.toList());
            Map<String, BehospitalInfoAgeDTO> ageMap = behospitalInfoFacade.getBehospitalInfoAge(hospitalId, behospitalCodes).stream().collect(Collectors.toMap(i -> i.getBehospitalCode(), i -> i));
            iPage.getRecords().forEach(i -> {
                i.setMonth(i.getJobDistributionTime());
                i.setStatus(CheckStatusEnum.getName(Integer.parseInt(i.getStatus())));
                i.setAge(ageMap.get(i.getBehospitalCode()) == null ? "" : ageMap.get(i.getBehospitalCode()).getAge());
            });
        }

        return iPage;
    }

    private List<Long> getUserIdsOfRoleId(Long hospitalId, List<String> deptIds, long roleId) {
        QueryWrapper<SysUserDept> sysUserDeptQueryWrapper = new QueryWrapper<>();
        sysUserDeptQueryWrapper.eq("hospital_id", hospitalId);
        sysUserDeptQueryWrapper.in(ListUtil.isNotEmpty(deptIds), "dept_id", deptIds);
        List<Long> userIds = sysUserDeptFacade.list(sysUserDeptQueryWrapper).stream().map(i -> i.getUserId()).collect(Collectors.toList());

        if (ListUtil.isEmpty(userIds)) {
            return null;
        }
        QueryWrapper<SysUserRole> sysUserRoleQueryWrapper = new QueryWrapper<>();
        sysUserRoleQueryWrapper.in("user_id", userIds);
        sysUserRoleQueryWrapper.eq("role_id", roleId);
        return sysUserRoleFacade.list(sysUserRoleQueryWrapper).stream().map(i -> i.getUserId()).collect(Collectors.toList());
    }

    public boolean recordCheck(RecordCheckVO recordCheckVO) {
        Long hospitalId = Long.parseLong(SysUserUtils.getCurrentHospitalID());
        Long userId = Long.parseLong(SysUserUtils.getCurrentPrincipleID());
        //获取核查与申诉是否相关配置（核查完成是否有申诉时的内容）
        checkAppealRelation(hospitalId,recordCheckVO);
        QueryWrapper<MedCheckInfo> medCheckInfoQueryWrapper = new QueryWrapper<>();
        medCheckInfoQueryWrapper.eq("behospital_code", recordCheckVO.getBehospitalCode());
        medCheckInfoQueryWrapper.eq("hospital_id", hospitalId);
        medCheckInfoQueryWrapper.eq("check_id", userId);
        medCheckInfoQueryWrapper.eq("check_type", CheckTypeEnum.ALL.getKey());
        MedCheckInfo medCheckInfo = medCheckInfoFacade.getOne(medCheckInfoQueryWrapper);
        if (medCheckInfo == null) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "该数据您暂无核查权限！");
        }

        medCheckInfo.setStatus(1);
        medCheckInfo.setCheckTime(DateUtil.now());
        medCheckInfoFacade.updateById(medCheckInfo);

        return true;
    }

    private void checkAppealRelation(Long hospitalId, RecordCheckVO recordCheckVO) {
        //获取核查与申诉是否相关配置（核查完成是否有申诉时的内容）
        String check_appeal_relation = sysHospitalSetFacade.getValue(hospitalId,"check_appeal_relation");
        if(StringUtil.isNotEmpty(check_appeal_relation)&&Boolean.parseBoolean(check_appeal_relation)){
            //获取该病例在待审核状态下的病历数量
            int count = appealInfoManagementFacade.count(new QueryWrapper<MedAppealInfo>()
                    .eq("work_flow_node_id","1")
                    .eq("behospital_code",recordCheckVO.getBehospitalCode())
                    .eq("is_deleted",IsDeleteEnum.N.getKey()));
            if(count>0){
                throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "当前缺陷列表存在待审核记录，无法完成核查。");
            }
        }

    }

    /**
     * @Author songxl
     * @Description获取当前用户的任务来源 和筛选分值
     * @Date 2021/5/28
     * @Param []
     * @Return java.util.Map<java.lang.String, java.lang.String>
     * @MethodName getCheckType
     */
    public Map<String, Object> getCheckType() {
        Map<String, Object> out = Maps.newLinkedHashMap();
        Map<Integer, String> checkTypes = Maps.newLinkedHashMap();
        Long userId = Long.parseLong(SysUserUtils.getCurrentPrincipleID());
        SysUserBaseVO sysUserBaseVO = new SysUserBaseVO();
        sysUserBaseVO.setUserId(userId);
        List<Long> roleIds = sysUserFacade.getUserRoles(sysUserBaseVO).getSelRoles().stream().map(i -> i.getId()).collect(Collectors.toList());
        roleIds.stream().forEach(roleId -> {
            if (roleId.intValue() == CheckerRoleEnum.DEPT_SUPERVISOR.getKey() || roleId.intValue() == CheckerRoleEnum.DEPT_GENERAL.getKey()) {
                checkTypes.put(CheckJobTypeEnum.DEPT_SUPERVISOR.getKey(), CheckJobTypeEnum.DEPT_SUPERVISOR.getName());
            }
            if (roleId.intValue() == CheckerRoleEnum.QUAT_SUPERVISOR.getKey() || roleId.intValue() == CheckerRoleEnum.QUAT_GENERAL.getKey()) {
                checkTypes.put(CheckJobTypeEnum.QUAT_SUPERVISOR.getKey(), CheckJobTypeEnum.QUAT_SUPERVISOR.getName());
            }
            if (roleId.intValue() == CheckerRoleEnum.HOSP_SUPERVISOR.getKey() || roleId.intValue() == CheckerRoleEnum.HOSP_GENERAL.getKey()) {
                checkTypes.put(CheckJobTypeEnum.HOSP_SUPERVISOR.getKey(), CheckJobTypeEnum.HOSP_SUPERVISOR.getName());
            }
        });
        Long hospitalId = Long.parseLong(SysUserUtils.getCurrentHospitalID());
        Map<String,Integer> valueMaps = medBehospitalTypeServiceImpl.list(new QueryWrapper<MedBehospitalType>()
                .eq("hospital_id", hospitalId)
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .isNotNull("value")
                .select("behospital_type,value")
                .groupBy("value")).stream().collect(Collectors.toMap(MedBehospitalType::getBehospitalType, MedBehospitalType::getValue,(k1, k2) -> k1,LinkedHashMap::new));
        out.put("source", checkTypes);
        out.put("value", valueMaps);
        return out;
    }
}