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

import com.xinelu.common.annotation.DataScope;
import com.xinelu.common.constant.SignRecordServiceStatusConstants;
import com.xinelu.common.enums.PatientSourceEnum;
import com.xinelu.common.exception.ServiceException;
import com.xinelu.common.utils.BaseUtil;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
import com.xinelu.manage.domain.residentinfo.ResidentInfo;
import com.xinelu.manage.domain.signpatientrecord.SignPatientRecord;
import com.xinelu.manage.dto.patientinfo.PatientBaseInfoDto;
import com.xinelu.manage.dto.patientinfo.PatientInfoDto;
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordDto;
import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
import com.xinelu.manage.mapper.residentinfo.ResidentInfoMapper;
import com.xinelu.manage.mapper.signpatientrecord.SignPatientRecordMapper;
import com.xinelu.manage.service.patientinfo.IPatientInfoService;
import com.xinelu.manage.service.patientvisitrecord.IPatientVisitRecordService;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 患者信息Service业务层处理
 *
 * @author haown
 * @date 2024-02-26
 */
@Service
public class PatientInfoServiceImpl implements IPatientInfoService {

    @Resource
    private PatientInfoMapper patientInfoMapper;
	@Resource
	private ResidentInfoMapper residentInfoMapper;
	@Resource
	private IPatientVisitRecordService patientVisitRecordService;
	@Resource
	private SignPatientRecordMapper signPatientRecordMapper;

    /**
     * 查询患者信息
     *
     * @param id 患者信息主键
     * @return 患者信息
     */
    @Override
    public PatientInfo selectPatientInfoById(Long id) {
        return patientInfoMapper.selectPatientInfoById(id);
    }

    /**
     * 查询患者信息列表
     *
     * @param patientInfo 患者信息
     * @return 患者信息
     */
    @Override
    @DataScope(agencyAlias = "p", userAlias = "p.attending_physician_id")
    public List<PatientInfo> selectPatientInfoList(PatientInfoDto patientInfo) {
        return patientInfoMapper.selectPatientInfoList(patientInfo);
    }

	/**
	 * 查询患者信息列表
	 *
	 * @param patientInfo 患者信息
	 * @return 患者信息
	 */
	@Override
	public List<PatientInfo> selectAllPatientList(PatientInfoDto patientInfo) {
		return patientInfoMapper.selectPatientInfoList(patientInfo);
	}

    /**
     * 新增患者信息
     *
     * @param patientInfo 患者信息
     * @return 结果
     */
    @Override
    @Transactional
    public PatientInfo insertPatientInfo(PatientInfo patientInfo) {
		if (StringUtils.isBlank(patientInfo.getCardNo())) {
			throw new ServiceException("请输入身份证号");
		}
		// 根据身份证号+机构id判断用户信息是否存在
	    PatientInfoDto patientQuery = new PatientInfoDto();
	    patientQuery.setCardNo(patientInfo.getCardNo());
	    patientQuery.setHospitalAgencyId(patientInfo.getHospitalAgencyId());
	    List<PatientInfo> patientList = patientInfoMapper.selectPatientInfoList(patientQuery);
		boolean exist = false;
		if(CollectionUtils.isNotEmpty(patientList)) {
			PatientInfo patientOld = patientList.get(0);
			patientInfo.setId(patientOld.getId());
			exist = true;
		} else {
			patientInfo.setCreateTime(LocalDateTime.now());
			patientInfo.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
		}
	    patientInfo.setDelFlag(0);
		// 根据身份证号计算性别出生日期
	    if (patientInfo.getBirthDate() == null) {
			patientInfo.setBirthDate(BaseUtil.getBirthday(patientInfo.getCardNo()));
	    }
		if (StringUtils.isBlank(patientInfo.getSex())) {
			patientInfo.setSex(BaseUtil.getGender(patientInfo.getCardNo()));
		}
		// 先根据身份证号查询是否有该居民
	    ResidentInfo residentQuery = new ResidentInfo();
		residentQuery.setCardNo(patientInfo.getCardNo());
	    List<ResidentInfo> residentList = residentInfoMapper.selectResidentInfoList(residentQuery);
		// 身份证号没查到居民，通过手机号查询居民
		if (CollectionUtils.isEmpty(residentList) && StringUtils.isNotBlank(patientInfo.getPatientPhone())) {
			residentQuery.setCardNo(null);
			residentQuery.setPatientPhone(patientInfo.getPatientPhone());
			residentList = residentInfoMapper.selectResidentInfoList(residentQuery);
		}
		ResidentInfo residentInfo = new ResidentInfo();
	    BeanUtils.copyBeanProp(residentInfo, patientInfo);
		if (CollectionUtils.isEmpty(residentList)) {
			// 新增居民
			residentInfoMapper.insertResidentInfo(residentInfo);
			patientInfo.setResidentId(residentInfo.getId());
		} else {
			// 修改居民信息
			residentInfo.setId(residentList.get(0).getId());
			residentInfoMapper.updateResidentInfo(residentInfo);
			patientInfo.setResidentId(residentList.get(0).getId());
		}
		// 患者来源
	    if (StringUtils.isBlank(patientInfo.getPatientSource())) {
			patientInfo.setPatientSource(PatientSourceEnum.MANAGE_END.name());
	    }
		if (exist) {
			patientInfoMapper.updatePatientInfoSelective(patientInfo);
		} else {
			patientInfoMapper.insertPatientInfo(patientInfo);
		}
		return patientInfo;
    }

    /**
     * 修改患者信息
     *
     * @param patientInfo 患者信息
     * @return 结果
     */
    @Override
    public PatientInfo updatePatientInfo(PatientInfo patientInfo) {
	    if (StringUtils.isBlank(patientInfo.getCardNo())) {
		    throw new ServiceException("请输入身份证号");
	    }
	    // 根据身份证号计算性别出生日期
	    patientInfo.setBirthDate(BaseUtil.getBirthday(patientInfo.getCardNo()));
	    patientInfo.setSex(BaseUtil.getGender(patientInfo.getCardNo()));
	    ResidentInfo residentInfo = new ResidentInfo();
		if (patientInfo.getResidentId() != null) {
			residentInfo = residentInfoMapper.selectResidentInfoById(patientInfo.getResidentId());
			BeanUtils.copyBeanProp(residentInfo, patientInfo);
			residentInfo.setId(patientInfo.getResidentId());
			residentInfoMapper.updateResidentInfo(residentInfo);
		} else {
			// 先根据身份证号查询是否有该居民
			ResidentInfo residentQuery = new ResidentInfo();
			residentQuery.setCardNo(patientInfo.getCardNo());
			List<ResidentInfo> residentList = residentInfoMapper.selectResidentInfoList(residentQuery);
			// 身份证号没查到居民，通过手机号查询居民
			if (CollectionUtils.isEmpty(residentList) && StringUtils.isNotBlank(patientInfo.getPatientPhone())) {
				residentQuery.setCardNo(null);
				residentQuery.setPatientPhone(patientInfo.getPatientPhone());
				residentList = residentInfoMapper.selectResidentInfoList(residentQuery);
			}
			if (CollectionUtils.isNotEmpty(residentList)) {
				Long residentId = residentList.get(0).getId();
				residentInfo = residentList.get(0);
				BeanUtils.copyBeanProp(residentInfo, patientInfo);
				residentInfo.setId(residentId);
				residentInfoMapper.updateResidentInfo(residentInfo);
			} else {
				BeanUtils.copyBeanProp(residentInfo, patientInfo);
				residentInfo.setId(null);
				residentInfoMapper.insertResidentInfo(residentInfo);
			}
			patientInfo.setResidentId(residentInfo.getId());
		}
	    patientInfo.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
	    patientInfo.setUpdateTime(LocalDateTime.now());
	    patientInfo.setDelFlag(0);
		patientInfoMapper.updatePatientInfoSelective(patientInfo);
		return patientInfo;
    }

	@Override public PatientInfo updateBaseInfo(PatientBaseInfoDto patientInfo) {
		PatientInfo patientInfo1 = patientInfoMapper.selectPatientInfoById(patientInfo.getId());
		BeanUtils.copyBeanProp(patientInfo1, patientInfo);
		return updatePatientInfo(patientInfo1);
	}

	/**
     * 批量删除患者信息
     *
     * @param ids 需要删除的患者信息主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deletePatientInfoByIds(Long[] ids) {
		int flag = 0;
	    for (Long id : ids) {
			PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(id);
			// 查询关联的就诊记录是否已签约
		    if (patientInfo.getSignPatientRecordId() != null && StringUtils.equals(SignRecordServiceStatusConstants.SERVICE_CENTER, patientInfo.getServiceStatus())) {
			    SignPatientRecord signPatientRecord = signPatientRecordMapper.selectByPrimaryKey(patientInfo.getSignPatientRecordId());
				if (ObjectUtils.isNotEmpty(signPatientRecord) && Objects.equals(patientInfo.getPatientVisitRecordId(), signPatientRecord.getPatientVisitRecordId()) && signPatientRecord.getDelFlag() == 0) {
					throw new ServiceException("该居民已签约不能删除该就诊记录！");
				}
		    }
		    patientVisitRecordService.deletePatientVisitRecordById(patientInfo.getPatientVisitRecordId());
		    // 根据患者最新一条就诊记录修改患者状态
		    PatientVisitRecordDto patientVisitRecordDto = new PatientVisitRecordDto();
		    patientVisitRecordDto.setHospitalAgencyId(patientInfo.getHospitalAgencyId());
		    patientVisitRecordDto.setPatientId(id);
		    PatientVisitRecord patientVisitRecord = patientVisitRecordService.getLastRecord(patientVisitRecordDto);
		    if (ObjectUtils.isEmpty(patientVisitRecord)) {
			    setVisitInfoNull(patientInfo);
		    } else {
			    BeanUtils.copyBeanProp(patientInfo, patientVisitRecord);
			    patientInfo.setId(id);
			    patientInfo.setPatientVisitRecordId(patientVisitRecord.getId());
			    // 设置patientType
			    patientVisitRecordService.setPatientType(patientInfo, patientVisitRecord);
		    }
		    patientInfo.setPatientType(null);
		    flag += patientInfoMapper.updatePatientInfo(patientInfo);
		}
        return flag;
    }

	/**
	 * 设置患者就诊信息为空
	 * @param patientInfo 患者信息
	 */
	private void setVisitInfoNull(PatientInfo patientInfo){
		patientInfo.setVisitDate(null);
		patientInfo.setPatientType(null);
		patientInfo.setPatientVisitRecordId(null);
		patientInfo.setVisitMethod(null);
		patientInfo.setAdmissionTime(null);
		patientInfo.setDischargeTime(null);
		patientInfo.setAttendingPhysicianId(null);
		patientInfo.setAttendingPhysicianName(null);
		patientInfo.setResponsibleNurse(null);
		patientInfo.setMainDiagnosis(null);
		patientInfo.setVisitSerialNumber(null);
		patientInfo.setInHospitalNumber(null);
	}
    /**
     * 删除患者信息
     *
     * @param id 患者信息主键
     * @return 结果
     */
    @Override
    public int deletePatientInfoById(Long id) {
        return patientInfoMapper.deletePatientInfoById(id);
    }
}
