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

import com.xinelu.common.constant.Constants;
import com.xinelu.common.constant.NodeTypeConstants;
import com.xinelu.common.constant.PatientTypeConstants;
import com.xinelu.common.constant.VisitMethodConstants;
import com.xinelu.common.core.domain.AjaxResult;
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.common.utils.regex.RegexUtil;
import com.xinelu.manage.domain.agency.Agency;
import com.xinelu.manage.domain.department.Department;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
import com.xinelu.manage.dto.patientinfo.PatientInfoDto;
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordDto;
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordImportDto;
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordInfoSaveDto;
import com.xinelu.manage.dto.patientvisitrecord.PatientVisitRecordSaveDto;
import com.xinelu.manage.mapper.agency.AgencyMapper;
import com.xinelu.manage.mapper.department.DepartmentMapper;
import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper;
import com.xinelu.manage.service.patientinfo.IPatientInfoService;
import com.xinelu.manage.service.patientvisitrecord.IPatientVisitRecordService;
import com.xinelu.manage.vo.patientinfo.PatientBaseInfoVo;
import com.xinelu.manage.vo.patientvisitrecord.PatientVisitRecordVo;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
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 PatientVisitRecordServiceImpl implements IPatientVisitRecordService {
    @Resource
    private PatientVisitRecordMapper patientVisitRecordMapper;
	@Resource
	private RegexUtil regexUtil;
	@Resource
	private PatientInfoMapper patientMapper;
	@Resource
	private AgencyMapper agencyMapper;
	@Resource
	private DepartmentMapper departmentMapper;
	@Resource
	private IPatientInfoService patientInfoService;

	/**
     * 查询患者就诊记录基本信息
     *
     * @param id 患者就诊记录基本信息主键
     * @return 患者就诊记录基本信息
     */
    @Override
    public PatientVisitRecord selectPatientVisitRecordById(Long id) {
        return patientVisitRecordMapper.selectPatientVisitRecordById(id);
    }

	@Override public PatientVisitRecordVo getByPatientId(Long patientId) {
		return patientVisitRecordMapper.getByPatientId(patientId);
	}

	/**
     * 查询患者就诊记录基本信息列表
     *
     * @param patientVisitRecord 患者就诊记录基本信息
     * @return 患者就诊记录基本信息
     */
    @Override
    public List<PatientVisitRecord> selectPatientVisitRecordList(PatientVisitRecordDto patientVisitRecord) {
        return patientVisitRecordMapper.selectPatientVisitRecordList(patientVisitRecord);
    }

    /**
     * 新增患者就诊记录基本信息
     *
     * @param saveDto 患者就诊记录基本信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertPatientVisitRecord(PatientVisitRecordSaveDto saveDto) {
	    if (StringUtils.isBlank(saveDto.getCardNo())) {
		    throw new ServiceException("请填写正确的身份证号!");
	    }
	    if (saveDto.getBirthDate() == null) {
		    saveDto.setBirthDate(BaseUtil.getBirthday(saveDto.getCardNo()));
	    }
	    if (StringUtils.isBlank(saveDto.getSex())) {
		    saveDto.setSex(BaseUtil.getGender(saveDto.getCardNo()));
	    }
		// 根据机构id、患者身份证号判断门诊/住院号是否重复
	    PatientVisitRecordDto patientVisitRecordDto = new PatientVisitRecordDto();
	    patientVisitRecordDto.setHospitalAgencyId(saveDto.getHospitalAgencyId());
	    patientVisitRecordDto.setCardNo(saveDto.getCardNo());
	    patientVisitRecordDto.setInHospitalNumber(saveDto.getInHospitalNumber());
	    PatientVisitRecord patientVisitRecord = patientVisitRecordMapper.getLastRecord(patientVisitRecordDto);
		if (ObjectUtils.isNotEmpty(patientVisitRecord)) {
			throw new ServiceException("门诊/住院号重复，请确认后重新输入!");
		}
	    PatientVisitRecord saveBody = new PatientVisitRecord();
	    BeanUtils.copyBeanProp(saveBody, saveDto);
		setVisitDate(saveBody);
		// 1、保存患者信息-查询是否有患者档案
	    PatientInfoDto patientInfoDto = new PatientInfoDto();
		patientInfoDto.setHospitalAgencyId(saveBody.getHospitalAgencyId());
		patientInfoDto.setCardNo(saveBody.getCardNo());
	    List<PatientInfo> patientInfoList = patientInfoService.selectAllPatientList(patientInfoDto);
		// 患者档案信息新增/修改
	    PatientInfo patientInfo = new PatientInfo();
	    if(CollectionUtils.isEmpty(patientInfoList)) {
		    BeanUtils.copyBeanProp(patientInfo, saveDto);
			patientInfo.setPatientSource(PatientSourceEnum.MANAGE_END.name());
		    patientInfo.setDelFlag(0);
		    patientInfo.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
		    patientInfo.setCreateTime(LocalDateTime.now());
		    PatientInfo patientSave = patientInfoService.insertPatientInfo(patientInfo);
		    saveBody.setPatientId(patientSave.getId());
		    saveBody.setResidentId(patientSave.getResidentId());
	    } else {
		    patientInfo = patientInfoList.get(0);
			Long patientId = patientInfo.getId();
		    // 修改档案
		    BeanUtils.copyBeanProp(patientInfo, saveDto);
		    patientInfo.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
		    patientInfo.setUpdateTime(LocalDateTime.now());
		    patientInfo.setId(patientId);
		    patientInfoService.updatePatientInfo(patientInfo);
		    saveBody.setPatientId(patientId);
		    saveBody.setResidentId(patientInfo.getResidentId());
	    }
		// 保存/修改就诊记录
	    Long recordId = saveOrUpate(saveBody);
		// 修改患者最近一次就诊记录id
		patientInfo.setPatientVisitRecordId(recordId);
	    patientInfo.setVisitDate(saveBody.getVisitDate());
	    patientInfoService.updatePatientInfo(patientInfo);
    }

	private Long saveOrUpate(PatientVisitRecord patientVisitRecord) {
		PatientVisitRecordDto query = new PatientVisitRecordDto();
		query.setHospitalAgencyId(patientVisitRecord.getHospitalAgencyId());
		query.setInHospitalNumber(patientVisitRecord.getInHospitalNumber());
		List<PatientVisitRecord> patientVisitRecordList = patientVisitRecordMapper.selectPatientVisitRecordList(query);
		if (CollectionUtils.isEmpty(patientVisitRecordList)) {
			patientVisitRecord.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
			patientVisitRecord.setCreateTime(LocalDateTime.now());
			patientVisitRecord.setDelFlag(0);
			patientVisitRecordMapper.insertPatientVisitRecord(patientVisitRecord);
		} else {
			patientVisitRecord.setId(patientVisitRecordList.get(0).getId());
			patientVisitRecord.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
			patientVisitRecord.setUpdateTime(LocalDateTime.now());
			patientVisitRecordMapper.updatePatientVisitRecord(patientVisitRecord);
		}
		return patientVisitRecord.getId();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int updatePatientVisitRecord(PatientVisitRecord patientVisitRecord) {
		if (StringUtils.isBlank(patientVisitRecord.getCardNo())) {
			throw new ServiceException("请填写正确的身份证号!");
		}
		if (patientVisitRecord.getPatientId() == null) {
			throw new ServiceException("患者信息有误");
		}
		patientVisitRecord.setBirthDate(BaseUtil.getBirthday(patientVisitRecord.getCardNo()));
		patientVisitRecord.setSex(BaseUtil.getGender(patientVisitRecord.getCardNo()));

		// 根据机构id、患者身份证号判断门诊/住院号是否重复
		PatientVisitRecordDto patientVisitRecordDto = new PatientVisitRecordDto();
		patientVisitRecordDto.setHospitalAgencyId(patientVisitRecord.getHospitalAgencyId());
		patientVisitRecordDto.setCardNo(patientVisitRecord.getCardNo());
		patientVisitRecordDto.setInHospitalNumber(patientVisitRecord.getInHospitalNumber());
		PatientVisitRecord object = patientVisitRecordMapper.getLastRecord(patientVisitRecordDto);
		if (ObjectUtils.isNotEmpty(object)) {
			throw new ServiceException("门诊/住院号重复，请确认后重新输入!");
		}
		// 修改患者基本信息
		PatientInfo patientInfo = patientMapper.selectPatientInfoById(patientVisitRecord.getPatientId());
		Long residentId = patientInfo.getResidentId();
		setVisitDate(patientVisitRecord);
		BeanUtils.copyBeanProp(patientInfo, patientVisitRecord);
		patientInfo.setId(patientVisitRecord.getPatientId());
		patientInfo.setResidentId(residentId);
		PatientInfo afterUpd = patientInfoService.updatePatientInfo(patientInfo);
		// 修改就诊记录信息
		patientVisitRecord.setResidentId(afterUpd.getResidentId());
		return patientVisitRecordMapper.updatePatientVisitRecord(patientVisitRecord);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
    public int saveRecord(PatientVisitRecordInfoSaveDto saveDto) {
		if (saveDto.getPatientId() == null) {
			throw new ServiceException("患者信息传输错误！");
		}
        PatientVisitRecord patientVisitRecord = new PatientVisitRecord();
        // 查询患者基本信息
        PatientBaseInfoVo patientBaseInfo = patientMapper.getPatientBaseInfo(saveDto.getPatientId());
        BeanUtils.copyBeanProp(patientVisitRecord, patientBaseInfo);
		// 根据机构id、患者身份证号判断门诊/住院号是否重复
		PatientVisitRecordDto patientVisitRecordDto = new PatientVisitRecordDto();
		patientVisitRecordDto.setHospitalAgencyId(saveDto.getHospitalAgencyId());
		patientVisitRecordDto.setCardNo(patientVisitRecord.getCardNo());
		patientVisitRecordDto.setInHospitalNumber(saveDto.getInHospitalNumber());
		PatientVisitRecord object = patientVisitRecordMapper.getLastRecord(patientVisitRecordDto);
		if (ObjectUtils.isNotEmpty(object)) {
			throw new ServiceException("门诊/住院号重复，请确认后重新输入!");
		}
        BeanUtils.copyBeanProp(patientVisitRecord, saveDto);
		patientVisitRecord.setDelFlag(0);
        patientVisitRecord.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        patientVisitRecord.setCreateTime(LocalDateTime.now());
        setVisitDate(patientVisitRecord);
		int flag = patientVisitRecordMapper.insertPatientVisitRecord(patientVisitRecord);
		if (flag > 0) {
			// 修改患者信息
			PatientInfo patientInfo = patientMapper.selectPatientInfoById(saveDto.getPatientId());
			BeanUtils.copyBeanProp(patientInfo, patientVisitRecord);
			patientInfo.setId(saveDto.getPatientId());
			//patientInfo.setPatientPreHospitalizationId(null);
			// 设置患者类型
			setPatientType(patientInfo, patientVisitRecord);
			patientInfo.setPatientVisitRecordId(patientVisitRecord.getId());
			patientInfoService.updatePatientInfo(patientInfo);
		}
	    return flag;
    }

    /**
     * 修改患者就诊记录基本信息
     *
     * @param updDto 患者就诊记录基本信息
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateRecord(PatientVisitRecordInfoSaveDto updDto) {
		if (updDto.getId() == null) {
			throw new ServiceException("数据传输错误");
		}
	    if (updDto.getPatientId() == null) {
		    throw new ServiceException("患者信息传输错误！");
	    }
        PatientVisitRecord patientVisitRecord = new PatientVisitRecord();
        BeanUtils.copyBeanProp(patientVisitRecord, updDto);
        patientVisitRecord.setUpdateBy(SecurityUtils.getLoginUser().getUser().getNickName());
        patientVisitRecord.setUpdateTime(LocalDateTime.now());
        // 住院时间，出院时间-入院时间
        setVisitDate(patientVisitRecord);
		int flag = patientVisitRecordMapper.updatePatientVisitRecord(patientVisitRecord);
	    if (flag > 0) {
		    // 查询患者信息
		    PatientInfo patientInfo = patientMapper.selectPatientInfoById(updDto.getPatientId());
		    // 修改患者信息
		    patientInfo.setVisitMethod(updDto.getVisitMethod());
			patientInfo.setDepartmentId(updDto.getDepartmentId());
			patientInfo.setDepartmentName(updDto.getDepartmentName());
			patientInfo.setAdmissionTime(updDto.getAdmissionTime());
			patientInfo.setDischargeTime(updDto.getDischargeTime());
		    setPatientType(patientInfo, patientVisitRecord);
		    patientInfoService.updatePatientInfo(patientInfo);
	    }
        return flag;
    }


    /**
     * 批量删除患者就诊记录基本信息
     *
     * @param ids 需要删除的患者就诊记录基本信息主键
     * @return 结果
     */
    @Override
    public int deletePatientVisitRecordByIds(Long[] ids) {
        return patientVisitRecordMapper.deletePatientVisitRecordByIds(ids);
    }

    /**
     * 删除患者就诊记录基本信息信息
     *
     * @param id 患者就诊记录基本信息主键
     * @return 结果
     */
    @Override
    public int deletePatientVisitRecordById(Long id) {
        return patientVisitRecordMapper.deletePatientVisitRecordById(id);
    }

	@Override
	public AjaxResult importPatientList(List<PatientVisitRecordImportDto> patientList, String patientType) {
		//判断添加的数据是否为空
		if (CollectionUtils.isEmpty(patientList)) {
			return AjaxResult.error("请添加就诊信息导入信息！");
		}
		// 根据患者身份证号做去除处理
		List<PatientVisitRecordImportDto> importDataList = patientList.stream().filter(item -> StringUtils.isNotBlank(item.getCardNo())).distinct().collect(Collectors.toList());
		// 校验联系电话格式是否正确
		PatientVisitRecordImportDto patient = importDataList.stream().filter(item -> StringUtils.isNotBlank(item.getPatientPhone())).filter(item -> BooleanUtils.isFalse(regexUtil.regexPhone(item.getPatientPhone()))).findFirst().orElse(new PatientVisitRecordImportDto());
		if (StringUtils.isNotBlank(patient.getPatientPhone())) {
			return AjaxResult.error("当前患者联系电话：" + patient.getPatientPhone() + " 格式不正确，请重新录入！");
		}

		List<PatientVisitRecord> saveList = new ArrayList<>();
		for (PatientVisitRecordImportDto item : importDataList) {
			PatientVisitRecord patientVisitRecord = new PatientVisitRecord();
			BeanUtils.copyProperties(item, patientVisitRecord);
			patientVisitRecord.setCreateTime(LocalDateTime.now());
			patientVisitRecord.setCreateBy(SecurityUtils.getLoginUser().getUser().getNickName());
			switch (patientType) {
				// 在院患者
				case Constants.IN_HOSPITAL:
				case Constants.DISCHARGED:
					patientVisitRecord.setVisitMethod(VisitMethodConstants.BE_IN_HOSPITAL);
					break;
				// 门诊患者
				case Constants.OUTPATIENT:
					patientVisitRecord.setVisitMethod(VisitMethodConstants.OUTPATIENT_SERVICE);
					patientVisitRecord.setInHospitalNumber(item.getOutpatientNumber());// 门诊、住院号共用一个字段
					break;
			}
			// 根据医院名称查询医院id
			Agency agency = new Agency();
			if (StringUtils.isNotBlank(item.getHospitalAgencyName())) {
				agency.setAgencyName(item.getHospitalAgencyName());
				agency.setNodeType(NodeTypeConstants.HOSPITAL);
				List<Agency> agencyList = agencyMapper.selectAgencyList(agency);
				if (CollectionUtils.isNotEmpty(agencyList)) {
					patientVisitRecord.setHospitalAgencyId(agencyList.get(0).getId());
				}
			} else {
				patientVisitRecord.setHospitalAgencyId(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
				Agency agencyData = agencyMapper.selectAgencyById(SecurityUtils.getLoginUser().getUser().getHospitalAgencyId());
				if (ObjectUtils.isNotEmpty(agencyData)) {
					patientVisitRecord.setHospitalAgencyName(agencyData.getAgencyName());
				}
			}
			// 查询院区id
			if (StringUtils.isNotBlank(item.getCampusAgencyName())) {
				agency.setParentId(patientVisitRecord.getHospitalAgencyId());
				agency.setAgencyName(item.getCampusAgencyName());
				agency.setNodeType(NodeTypeConstants.CAMPUS);
				List<Agency> campusList = agencyMapper.selectAgencyList(agency);
				if (CollectionUtils.isNotEmpty(campusList)) {
					patientVisitRecord.setCampusAgencyId(campusList.get(0).getId());
				}
			}

			// 查询科室id
			Department department = new Department();
			if (StringUtils.isNotBlank(item.getDepartmentName())) {
				department.setHospitalAgencyName(item.getHospitalAgencyName());
				department.setDepartmentName(item.getDepartmentName());
				department.setNodeType(NodeTypeConstants.DEPARTMENT);
				List<Department> deptList = departmentMapper.selectDepartmentList(department);
				if (CollectionUtils.isNotEmpty(deptList)) {
					patientVisitRecord.setDepartmentId(deptList.get(0).getId());
				}
			} else {
				patientVisitRecord.setDepartmentId(SecurityUtils.getLoginUser().getUser().getDepartmentId());
				Department department1 = departmentMapper.selectDepartmentById(SecurityUtils.getLoginUser().getUser().getDepartmentId());
				if (ObjectUtils.isNotEmpty(department1)) {
					patientVisitRecord.setDepartmentName(department1.getDepartmentName());
				}
			}
			// 查询病区
			if (StringUtils.isNotBlank(item.getWardName())) {
				department.setHospitalAgencyName(item.getHospitalAgencyName());
				department.setDepartmentName(item.getWardName());
				department.setNodeType(NodeTypeConstants.WARD);
				List<Department> deptList = departmentMapper.selectDepartmentList(department);
				if (CollectionUtils.isNotEmpty(deptList)) {
					patientVisitRecord.setWardId(deptList.get(0).getId());
				}
			}
			// 根据身份证号查询患者信息
			PatientInfoDto patientQuery = new PatientInfoDto();
			patientQuery.setCardNo(item.getCardNo());
			patientQuery.setHospitalAgencyId(patientVisitRecord.getHospitalAgencyId());
			List<PatientInfo> patientInfoList = patientMapper.selectPatientInfoList(patientQuery);
			if (CollectionUtils.isNotEmpty(patientInfoList)) {
				// 修改居民信息
				PatientInfo updInfo = patientInfoList.get(0);
				BeanUtils.copyBeanProp(updInfo, item);
				patientMapper.updatePatientInfoSelective(updInfo);
				patientVisitRecord.setPatientId(patientInfoList.get(0).getId());
			} else {
				PatientInfo saveInfo = new PatientInfo();
				// 添加居民
				BeanUtils.copyBeanProp(saveInfo, item);
				patientMapper.insertPatientInfo(saveInfo);
				patientVisitRecord.setPatientId(saveInfo.getId());
			}
			patientVisitRecord.setDelFlag(0);
			// 根据门诊/住院编号查询是否有记录
			PatientVisitRecordDto recordQuery = new PatientVisitRecordDto();
			recordQuery.setVisitMethod(patientType);
			recordQuery.setInHospitalNumber(patientVisitRecord.getInHospitalInfo());
			List<PatientVisitRecord> patientVisitRecordList = patientVisitRecordMapper.selectPatientVisitRecordList(recordQuery);
			if (CollectionUtils.isEmpty(patientVisitRecordList)) {
				// 新增
				saveList.add(patientVisitRecord);
			} else {
				// 修改
				patientVisitRecord.setId(patientVisitRecordList.get(0).getId());
				int flag = patientVisitRecordMapper.updatePatientVisitRecord(patientVisitRecord);
				if (flag < 0) {
					throw new ServiceException("导入患者就诊信息失败，请联系管理员！");
				}
			}
		}
		int insertCount = patientVisitRecordMapper.insertBatch(saveList);
		if (insertCount <= 0) {
			throw new ServiceException("导入患者就诊信息失败，请联系管理员！");
		}
		return AjaxResult.success();
	}

	@Override
	public void setPatientType(PatientInfo patientInfo, PatientVisitRecord patientVisitRecord) {
		if (StringUtils.equals(VisitMethodConstants.BE_IN_HOSPITAL, patientVisitRecord.getVisitMethod())) {
			// 住院患者：有出院时间，设置患者类型为出院，没有出院时间，设置患者类型为在院
			if (patientVisitRecord.getDischargeTime() == null) {
				patientInfo.setPatientType(PatientTypeConstants.IN_HOSPITAL_PATIENT);
			} else {
				patientInfo.setPatientType(PatientTypeConstants.DISCHARGED_PATIENT);
			}
		} else if (StringUtils.equals(VisitMethodConstants.OUTPATIENT_SERVICE, patientVisitRecord.getVisitMethod())) {
			patientInfo.setPatientType(PatientTypeConstants.OUTPATIENT);
		}
	}

	@Override public PatientVisitRecord getLastRecord(PatientVisitRecordDto patientVisitRecordDto) {
		return patientVisitRecordMapper.getLastRecord(patientVisitRecordDto);
	}

	private void setVisitDate(PatientVisitRecord patientVisitRecord) {
		if (StringUtils.equals(VisitMethodConstants.OUTPATIENT_SERVICE, patientVisitRecord.getVisitMethod())) {
			patientVisitRecord.setVisitDate(patientVisitRecord.getDischargeTime());
		} else if (StringUtils.equals(VisitMethodConstants.BE_IN_HOSPITAL, patientVisitRecord.getVisitMethod())) {
			// 住院时间，出院时间-入院时间
			if (patientVisitRecord.getAdmissionTime() != null && patientVisitRecord.getDischargeTime() != null) {
				long daysBetween = ChronoUnit.DAYS.between(patientVisitRecord.getAdmissionTime(), patientVisitRecord.getDischargeTime());
				patientVisitRecord.setHospitalizationDays((int) daysBetween + 1);
			}
			patientVisitRecord.setVisitDate(patientVisitRecord.getAdmissionTime());
		}
	}
}
