package com.diagbot.facade;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.diagbot.dto.CheckDeptDTO;
import com.diagbot.dto.CheckMedoupDTO;
import com.diagbot.dto.DeptCheckUserDTO;
import com.diagbot.dto.RejectPatientDTO;
import com.diagbot.entity.*;
import com.diagbot.enums.CheckTypeEnum;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.impl.MedExamineInfoServiceImpl;
import com.diagbot.util.DateUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.util.SysUserUtils;
import com.diagbot.vo.BehospitalcodeVO;
import com.diagbot.vo.MedAppealInfoVO;
import com.diagbot.vo.MedCheckInfoAddVO;
import com.diagbot.vo.RejectedVo;
import org.springframework.beans.BeanUtils;
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.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**
 * @author wangfeng
 * @Description:
 * @time: 2024-07-06 13:27
 */
@Component
public class MedExamineInfoFacade extends MedExamineInfoServiceImpl {

    @Autowired
    SysUserFacade sysUserFacade;
    @Autowired
    MedExamineInfoFacade medExamineInfoFacade;
    @Autowired
    private BehospitalInfoFacade behospitalInfoFacade;
    @Autowired
    private QcresultDetailFacade qcresultDetailFacade;
    @Autowired
    private MedRejectedInfoFacade medRejectedInfoFacade;
    @Autowired
    private MedAppealInfoFacade medAppealInfoFacade;

    public boolean passAudit(BehospitalcodeVO behospitalcodeVO) {
        Long hospitalId = Long.parseLong(SysUserUtils.getCurrentHospitalID());
        Long userId = Long.parseLong(SysUserUtils.getCurrentPrincipleID());

        UpdateWrapper<BehospitalInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("behospital_code", behospitalcodeVO.getBehospitalCode())
                .eq("hospital_id", behospitalcodeVO.getHospitalId())
                .eq("is_deleted", IsDeleteEnum.N)
                .set("status", "2");
        behospitalInfoFacade.update(updateWrapper);

        //获取判断是否有审核
        QueryWrapper<MedExamineInfo> medExamineInfoQueryWrapper = new QueryWrapper<>();
        medExamineInfoQueryWrapper.eq("behospital_code", behospitalcodeVO.getBehospitalCode());
        medExamineInfoQueryWrapper.eq("hospital_id", hospitalId);
//        medCheckInfoQueryWrapper.eq("check_id", userId);
//        medCheckInfoQueryWrapper.eq("check_type", CheckTypeEnum.ALL.getKey());
        MedExamineInfo medExamineInfo = medExamineInfoFacade.getOne(medExamineInfoQueryWrapper);
        SysUser user = sysUserFacade.getOne(new QueryWrapper<SysUser>()
                .eq("id", userId)
                .eq("is_deleted", IsDeleteEnum.N.getKey()));

        if (medExamineInfo == null) {
            MedExamineInfo insertCheckInfo = new MedExamineInfo();
            insertCheckInfo.setBehospitalCode(behospitalcodeVO.getBehospitalCode());
            insertCheckInfo.setCheckId(userId);
            if (user != null) {
                insertCheckInfo.setCheckName(user.getLinkman());
            }
            insertCheckInfo.setAction(CheckTypeEnum.PASSED.getKey());
            insertCheckInfo.setHospitalId(hospitalId);
            insertCheckInfo.setStatus(1);
            insertCheckInfo.setCheckTime(DateUtil.now());
            return medExamineInfoFacade.save(insertCheckInfo);
        }

        medExamineInfo.setCheckId(userId);
        if (user != null) {
            medExamineInfo.setCheckName(user.getLinkman());
        }
        medExamineInfo.setStatus(1);
        medExamineInfo.setCheckTime(DateUtil.now());
        medExamineInfoFacade.updateById(medExamineInfo);

        return true;
    }

    /**
     * 驳回接口
     */
    public Boolean rejected(RejectedVo rejectedVo) {
        //通过医院id+病历id+条目ID+未删除  获取该缺陷记录
        QcresultDetail qcresultDetail = getQcresultDetailById(rejectedVo);
        //获取该病历缺陷申诉记录(医院id+病历id+质控缺陷id+未删除)
        MedRejectedInfo medRejectedInfo = getMedRejectedInfo(rejectedVo.getHospitalId()
                , rejectedVo.getBehospitalCode()
                , rejectedVo.getCasesEntryId());
        //缺陷状态-删除或忽略
        if (IsDeleteEnum.Y.getKey().equals(qcresultDetail.getIsDeleted())) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS, "该缺陷已被删除或忽略!");
        }
        //修改病历状态-驳回
        UpdateWrapper<BehospitalInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("behospital_code", rejectedVo.getBehospitalCode())
                .eq("hospital_id", rejectedVo.getHospitalId())
                .eq("is_deleted", IsDeleteEnum.N)
                .set("status", "3");
        behospitalInfoFacade.update(updateWrapper);

        // 获取病历信息
        BehospitalInfo behospitalInfo = behospitalInfoFacade.getOne(new QueryWrapper<BehospitalInfo>()
                .eq("behospital_code", rejectedVo.getBehospitalCode())
                .eq("hospital_id", rejectedVo.getHospitalId())
                .eq("is_deleted", IsDeleteEnum.N));

        //驳回记录不存在
        if (medRejectedInfo == null) {
            //新增驳回记录
            return addmedRejectedInfo(rejectedVo, behospitalInfo.getDoctorId());
        } else {
            //删除驳回记录
            medRejectedInfoFacade.update(new UpdateWrapper<MedRejectedInfo>().set("is_deleted", IsDeleteEnum.Y.getKey())
                    .eq("id", medRejectedInfo.getId()));
            //新增驳回记录
            return addmedRejectedInfo(rejectedVo, behospitalInfo.getDoctorId());
        }

    }

    /**
     * @param rejectedVo
     * @Description通过医院id+病历id+条目ID+未删除 获取该缺陷记录
     * @Return QcresultDetail
     */
    private QcresultDetail getQcresultDetailById(RejectedVo rejectedVo) {
        if (rejectedVo.getCasesEntryId() == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "条目ID为空!");
        }
        List<QcresultDetail> qcresultDetails = qcresultDetailFacade.list(new QueryWrapper<QcresultDetail>()
                .eq("hospital_id", rejectedVo.getHospitalId())
                .eq("behospital_code", rejectedVo.getBehospitalCode())
                .eq("cases_entry_id", rejectedVo.getCasesEntryId())
                .orderByDesc("id"));
        if (ListUtil.isEmpty(qcresultDetails)) {
            throw new CommonException(CommonErrorCode.SERVER_IS_ERROR, "质控缺陷不存在!");
        }
        return qcresultDetails.get(0);
    }

    /**
     * @param hospitalId
     * @param behospitalCode
     * @param getCasesEntryId
     * @Description获取该病历缺陷申诉记录
     * @Return MedRejectedInfo
     */
    private MedRejectedInfo getMedRejectedInfo(Long hospitalId, String behospitalCode, Long getCasesEntryId) {

        if (getCasesEntryId == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "质控缺陷id为空!");
        }
        List<MedRejectedInfo> medRejectedInfos = medRejectedInfoFacade.list(new QueryWrapper<MedRejectedInfo>()
                .eq("hospital_id", hospitalId)
                .eq("behospital_code", behospitalCode)
                .eq("cases_entry_id", getCasesEntryId)
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .orderByDesc("gmt_create"));
        if (ListUtil.isNotEmpty(medRejectedInfos)) {
            return medRejectedInfos.get(0);
        }
        return null;
    }

    /**
     * @param rejectedVo
     * @Description 驳回记录插入
     * @Return Boolean
     */
    private Boolean addmedRejectedInfo(RejectedVo rejectedVo,String doctorId) {
        try {
            MedRejectedInfo medRejectedInfo = new MedRejectedInfo();
            BeanUtils.copyProperties(rejectedVo, medRejectedInfo);
            medRejectedInfo.setDoctorId(doctorId);
            medRejectedInfo.setGmtCreate(DateUtil.now());
            return medRejectedInfoFacade.save(medRejectedInfo);
        } catch (Exception e) {
            throw new CommonException(CommonErrorCode.SERVICE_STOP_ERROR, "驳回记录插入失败!");
        }
    }

    /**
     * 申诉接口
     **/
    public Boolean addAppealInfo(MedAppealInfoVO medAppealInfoVO) {

        if (medAppealInfoVO.getCasesEntryId() == null) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "质控缺陷id为空!");
        }

        //修改病历状态-申诉
        UpdateWrapper<BehospitalInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("behospital_code", medAppealInfoVO.getBehospitalCode())
                .eq("hospital_id", medAppealInfoVO.getHospitalId())
                .eq("is_deleted", IsDeleteEnum.N)
                .set("status", "5");
        behospitalInfoFacade.update(updateWrapper);

        //获取该病历缺陷申诉记录(医院id+病历id+质控缺陷id+未删除)
        List<MedAppealInfo> medAppealInfos = medAppealInfoFacade.list(new QueryWrapper<MedAppealInfo>()
                .eq("hospital_id", medAppealInfoVO.getHospitalId())
                .eq("behospital_code", medAppealInfoVO.getBehospitalCode())
                .eq("cases_entry_id", medAppealInfoVO.getCasesEntryId())
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .orderByDesc("gmt_create"));
        if (ListUtil.isEmpty(medAppealInfos)) {
            return addmedAppealInfo(medAppealInfoVO);
        } else {
            //删除申诉记录
            medAppealInfoFacade.update(new UpdateWrapper<MedAppealInfo>().set("is_deleted", IsDeleteEnum.Y.getKey())
                    .eq("id", medAppealInfos.get(0).getId()));

            //新增申诉记录
            return addmedAppealInfo(medAppealInfoVO);
        }
    }

    /**
     * @param medAppealInfoVO
     * @Description 申诉记录插入
     * @Return Boolean
     */
    private Boolean addmedAppealInfo(MedAppealInfoVO medAppealInfoVO) {
        try {
            MedAppealInfo medAppealInfo = new MedAppealInfo();
            BeanUtils.copyProperties(medAppealInfoVO, medAppealInfo);
            medAppealInfo.setGmtCreate(DateUtil.now());
            return medAppealInfoFacade.save(medAppealInfo);
        } catch (Exception e) {
            throw new CommonException(CommonErrorCode.SERVICE_STOP_ERROR, "申诉记录插入失败!");
        }
    }

    /**
     * @param behospitalcodeVO
     * @Description 获取全部驳回记录
     * @Return QcresultDetail
     */
    public List<RejectPatientDTO> getRejectPatient(BehospitalcodeVO behospitalcodeVO) {
        List<RejectPatientDTO> rejectPatientDTOList = new ArrayList<>();
        //获取该病历缺陷申诉记录(医院id+病历id+质控缺陷id+未删除)
        List<MedRejectedInfo> medRejectedInfos = medRejectedInfoFacade.list(new QueryWrapper<MedRejectedInfo>()
                .eq("hospital_id", behospitalcodeVO.getHospitalId())
                .eq("behospital_code", behospitalcodeVO.getBehospitalCode())
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .orderByDesc("gmt_create"));

        if (ListUtil.isEmpty(medRejectedInfos)) {
            return rejectPatientDTOList;
        }

        String doctorId = medRejectedInfos.get(0).getDoctorId();
        if (StringUtil.isEmpty(doctorId)) {
            throw new CommonException(CommonErrorCode.PARAM_IS_NULL, "入院登记信息中未找到主治医生!");
        }

        List<MedRejectedInfo> medReInfos = medRejectedInfoFacade.list(new QueryWrapper<MedRejectedInfo>()
                .eq("hospital_id", behospitalcodeVO.getHospitalId())
                .eq("doctor_id", doctorId)
                .eq("is_deleted", IsDeleteEnum.N.getKey())
                .orderByDesc("gmt_create"));

        List<String> beHospitalCodeList = new ArrayList<>();
        for (MedRejectedInfo medRejectedInfo : medReInfos) {
            beHospitalCodeList.add(medRejectedInfo.getBehospitalCode());
        }
        // 构建查询条件（含空值检查）
        QueryWrapper<BehospitalInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(BehospitalInfo::getHospitalId, behospitalcodeVO.getHospitalId())
                .eq(BehospitalInfo::getIsDeleted, IsDeleteEnum.N);
        if (!CollectionUtils.isEmpty(beHospitalCodeList)) {
            queryWrapper.lambda().in(BehospitalInfo::getBehospitalCode, beHospitalCodeList);
        }
        queryWrapper.lambda().select(BehospitalInfo::getName,
                BehospitalInfo::getSex,
                BehospitalInfo::getFileCode,
                BehospitalInfo::getBehospitalCode);

        rejectPatientDTOList = behospitalInfoFacade.list(queryWrapper)
                .stream()
                .map(this::convertToRejectPatientDTO)
                .collect(Collectors.toList());

        return rejectPatientDTOList;
    }

    // 对象转换方法
    private RejectPatientDTO convertToRejectPatientDTO(BehospitalInfo info) {
        return RejectPatientDTO.builder()
                .name(info.getName())
                .sex(info.getSex())
                .fileCode(info.getFileCode())
                .behospitalCode(info.getBehospitalCode())
                .build();
    }

}
