package com.ruoyi.web.work.hl7.service.impl;

import ca.uhn.hl7v2.HL7Exception;
import ca.uhn.hl7v2.model.v24.segment.DG1;
import ca.uhn.hl7v2.model.v24.segment.PV1;
import ca.uhn.hl7v2.model.v24.segment.PV2;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.web.work.domain.Visit;
import com.ruoyi.web.work.hl7.service.HL7DiagnosisService;
import com.ruoyi.web.work.hl7.service.HL7VisitService;
import com.ruoyi.web.work.mapper.VisitMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.util.List;

/**
 * 就诊记录
 */
@Service("HL7VisitService")
@Log4j2
@Transactional
public class HL7VisitServiceImpl extends ServiceImpl<VisitMapper, Visit> implements HL7VisitService {

    @Autowired
    private HL7DiagnosisService dg1Service;

    @Autowired
    private SysDeptMapper deptMapper;

    /**
     * 根据患者id修改当前患者的就诊记录信息
     * @param patId
     */
    @Override
    public void updateVisitInfoByPatId(List<DG1> dg1All,Long patId,PV1 pv1,PV2 pv2) throws ParseException, HL7Exception {
        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
        String department = pv1.getAssignedPatientLocation().getRoom().getValue(); //科室
        LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Visit::getPatId,patId).eq(Visit::getDeptCode,deptCode);
        Visit visitEntity = baseMapper.selectOne(wrapper);
        if (visitEntity != null){
            String hospitalStatus = pv1.getBedStatus().getValue(); // 在院状态
            String doctorCode = pv1.getAttendingDoctor(0).getIDNumber().getValue(); //医生代码
            String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue(); //主治医师
            String bed = pv1.getAssignedPatientLocation().getBed().getValue(); //床位代码
            String wardCode = pv1.getAssignedPatientLocation().getBuilding().getValue();//病区代码
            String wardName = pv1.getAssignedPatientLocation().getFloor().getValue();//病区名称
            String level = pv2.getVisitUserCode(0).getValue(); //危重级别:0-一般病人1-危重病人
            String entryTime = pv2.getExpectedAdmitDateTime().getTimeOfAnEvent().getValue(); //入区时间
            String exitTime = pv2.getExpectedDischargeDateTime().getTimeOfAnEvent().getValue(); //出区时间
            String reasonArea = pv2.getVisitDescription().getValue();//出区原因
            visitEntity.setWardName(wardName);
            visitEntity.setWardCode(wardCode);
            visitEntity.setDeptCode(deptCode);
            visitEntity.setLevel(level); //危重级别:0-一般病人1-危重病人
            visitEntity.setReasonArea(reasonArea); //出区原因
            visitEntity.setExitTime(exitTime); //出区时间
            visitEntity.setEntryTime(entryTime); //入区时间
            visitEntity.setDepartment(department);
            visitEntity.setBed(bed);
            visitEntity.setHospitalStatus(hospitalStatus); //在院状态
            visitEntity.setDoctorCode(doctorCode);
            visitEntity.setPhysician(physician);
            baseMapper.updateById(visitEntity);
            log.info("成功更新患者ID为{}的就诊信息", patId);
            Long visitId = visitEntity.getId();//就诊id
            //修改dg1诊断结果表 对医生科室信息进行补充
            dg1Service.updateDg1InfoByVisitId(visitEntity.getId(),department,physician);
            //保存诊断结果信息
            dg1Service.saveDiagnosisInfo(dg1All,visitId,pv1,patId);
        }
    }

    /**
     * 保存患者就诊记录
     * @param pv1
     * @param patId 患者id
     */
    @Override
    public void saveVisitInfo(List<DG1> dg1All,PV1 pv1,PV2 pv2, Long patId) throws Exception {
        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
        LambdaQueryWrapper<Visit> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Visit::getDeptCode,deptCode).eq(Visit::getPatId,patId);
        Visit visitEntity = baseMapper.selectOne(wrapper); //根据科室部门代码和患者id查
        if (visitEntity != null && !StringUtils.isEmpty(deptCode) && visitEntity.getDeptCode().equals(deptCode)) {
            // 如果已存在且科室代码匹配,保存诊断信息
            Long dbVisitId = visitEntity.getId(); //就诊dbVisitId
            dg1Service.saveDiagnosisInfo(dg1All,dbVisitId,pv1,patId);
            log.info("就诊已经存在，保存诊断信息! 诊断ID: {}", dbVisitId);
        } else {
            //保存患者就诊记录信息
            Long visitId = saveVisitComm(pv1,pv2,patId);
            dg1Service.saveDiagnosisInfo(dg1All,visitId,pv1,patId);
            log.info("保存患者新的就诊记录信息完成!");
        }
    }

    /**
     * 更新患者就诊记录的在院状态、出院时间、出院方式
     * @param dbPid 患者id
     * @param pv1
     */
    @Override
    public Long updateVisitHospitalStatus(Long dbPid, PV1 pv1){
        LambdaQueryWrapper<Visit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Visit::getPatId, dbPid);
        List<Visit> visitEntities = baseMapper.selectList(queryWrapper);
        if (visitEntities.isEmpty()) {
            return null;
        }
        Visit visitEntity = visitEntities.get(visitEntities.size() - 1); // 获取最后一次就诊记录
        visitEntity.setHospitalStatus(pv1.getBedStatus().getValue()); //在院状态
        visitEntity.setDischargeTime(pv1.getDischargeDateTime(0).getTimeOfAnEvent().getValue());//出院时间
        visitEntity.setDischargeMethod(pv1.getDischargeDisposition().getValue());//出院方式
        baseMapper.updateById(visitEntity);
        return visitEntity.getId();
    }

    /**
     * 根据患者id和送检科室查询是否本次就诊的报告
     * @param patId 患者id
     * @param inspectionDeptName 送检科室
     * @return
     */
    @Override
    public Visit findVisitByPatIdAndDeptName(Long patId, String inspectionDeptName) {
        LambdaQueryWrapper<Visit> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Visit::getPatId, patId).eq(Visit::getDepartment,inspectionDeptName);
        return baseMapper.selectOne(queryWrapper);
    }

    /**
     * 就诊记录基本信息
     * @param pv1
     * @param pv2
     * @param PatId 患者id
     * @return
     */
    private Long saveVisitComm(PV1 pv1,PV2 pv2,Long PatId) {
        String deptCode = pv1.getAssignedPatientLocation().getPointOfCare().getValue();//科室代码
        //根据部门dept_code查询sys_dept表获取部门信息
        LambdaQueryWrapper<SysDept> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysDept::getDeptCode,deptCode);
        SysDept sysDept = deptMapper.selectOne(wrapper);
        Long deptId = null;
        if (sysDept != null){
            deptId = sysDept.getDeptId(); //部门id
        }
        //保存患者就诊记录信息
        String patClass = pv1.getPatientClass().getValue(); //患者类别
        String department = pv1.getAssignedPatientLocation().getRoom().getValue(); //科室
        String bed = pv1.getAssignedPatientLocation().getBed().getValue(); //床位代码
        String wardCode = pv1.getAssignedPatientLocation().getBuilding().getValue();//病区代码
        String wardName = pv1.getAssignedPatientLocation().getFloor().getValue();//病区名称
        String doctorCode = pv1.getAttendingDoctor(0).getIDNumber().getValue();
        String physician = pv1.getAttendingDoctor(0).getFamilyName().getSurname().getValue(); //主治医师
        String nurseCode = pv1.getReferringDoctor(0).getIDNumber().getValue(); //主管护士代码
        String hospitalizedNumber = pv1.getReAdmissionIndicator().getValue(); //入院次数
        String cardId = pv1.getVisitNumber().getID().getValue(); //就诊卡号
        String feeCategory = pv1.getFinancialClass(0).getFinancialClass().getValue(); //收费类别
        String dischargeMethod = pv1.getDischargeDisposition().getValue(); //出院方式
        String medicalCode = pv1.getServicingFacility().getValue(); //医疗机构代码
        String hospitalStatus = pv1.getBedStatus().getValue(); // 在院状态
        String registrationStatus = pv1.getAccountStatus().getValue(); //门诊挂号状态：0-有效 1-无效
        String admissionTime = pv1.getAdmitDateTime().getTimeOfAnEvent().getValue(); //入院时间
        String dischargeTime = pv1.getDischargeDateTime(0).getTimeOfAnEvent().getValue();//出院时间
        String level = pv2.getVisitUserCode(0).getValue(); //危重级别:0-一般病人1-危重病人
        String entryTime = pv2.getExpectedAdmitDateTime().getTimeOfAnEvent().getValue(); //入区时间
        String exitTime = pv2.getExpectedDischargeDateTime().getTimeOfAnEvent().getValue(); //出区时间
        String reasonArea = pv2.getVisitDescription().getValue();//出区原因
        String babyCode = pv2.getNewbornBabyIndicator().getValue();//婴儿信息标识：Y-是 N-否
        Visit entity = new Visit();
        entity.setLevel(level);
        entity.setEntryTime(entryTime);
        entity.setExitTime(exitTime);
        entity.setReasonArea(reasonArea);
        entity.setBabyCode(babyCode);
        entity.setPatId(PatId);  //患者ID
        entity.setPatClass(patClass);
        entity.setDoctorCode(doctorCode); //医生代码
        entity.setDepartment(department); //科室
        entity.setBed(bed);
        entity.setPhysician(physician); //主治医生
        entity.setDeptCode(deptCode);
        entity.setWardCode(wardCode);
        entity.setWardName(wardName);
        entity.setNurseCode(nurseCode);
        entity.setHospitalizedNumber(hospitalizedNumber);
        entity.setFeeCategory(feeCategory);
        entity.setDischargeMethod(dischargeMethod);
        entity.setMedicalCode(medicalCode);
        entity.setHospitalStatus(hospitalStatus);
        entity.setRegistrationStatus(registrationStatus);
        entity.setAdmissionTime(admissionTime);
        entity.setDischargeTime(dischargeTime);
        entity.setCardId(Long.valueOf(cardId));
        entity.setDeptId(deptId);
        baseMapper.insert(entity);
        return entity.getId();
    }
}
