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

import com.alibaba.fastjson2.JSONObject;
import com.xinelu.common.config.XinELuConfig;
import com.xinelu.common.constant.ScreeningProjectConstants;
import com.xinelu.common.core.domain.SelectVo;
import com.xinelu.common.core.domain.TimelineVo;
import com.xinelu.common.core.domain.model.LoginUser;
import com.xinelu.common.utils.DateUtils;
import com.xinelu.common.utils.QrCodeUtils;
import com.xinelu.common.utils.SecurityUtils;
import com.xinelu.common.utils.bean.BeanUtils;
import com.xinelu.common.utils.file.FileUtils;
import com.xinelu.common.utils.uuid.IdUtils;
import com.xinelu.manage.domain.hospitalinfo.HospitalInfo;
import com.xinelu.manage.domain.hospitalpersoninfo.HospitalPersonInfo;
import com.xinelu.manage.domain.screeningproject.ScreeningProject;
import com.xinelu.manage.domain.screeningrecord.ScreeningRecord;
import com.xinelu.manage.dto.screeningrecord.ScreeningApplyDTO;
import com.xinelu.manage.dto.screeningrecord.ScreeningRecordApplyDTO;
import com.xinelu.manage.dto.screeningrecord.ScreeningRecordDTO;
import com.xinelu.manage.dto.screeningrecord.ScreeningRecordSaveDTO;
import com.xinelu.manage.mapper.hospitalinfo.HospitalInfoMapper;
import com.xinelu.manage.mapper.hospitalpersoninfo.HospitalPersonInfoMapper;
import com.xinelu.manage.mapper.screeningrecord.ScreeningRecordMapper;
import com.xinelu.manage.service.patientinfo.IPatientInfoService;
import com.xinelu.manage.service.screeningrecord.IScreeningRecordService;
import com.xinelu.manage.vo.patientinfo.PatientInfoVO;
import com.xinelu.manage.vo.screeningrecord.ScreeningRecordVo;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
* @author mengkuiliang
* @description 针对表【sd_screening_record(居民预约记录表)】的数据库操作Service实现
* @createDate 2023-01-29 13:53:13
*/
@Service
public class ScreeningRecordServiceImpl implements IScreeningRecordService {

    @Resource
    private ScreeningRecordMapper screeningRecordMapper;
    @Resource
    private IPatientInfoService patientService;
	@Resource
	private HospitalPersonInfoMapper hospitalPersonInfoMapper;
	@Resource
	private HospitalInfoMapper hospitalInfoMapper;
	@Resource
	private XinELuConfig xinELuConfig;

	@Override
	public List<ScreeningRecordVo> screeningList(ScreeningRecordDTO query) throws Exception {
		return screeningRecordMapper.screeningList(query);
	}

	/**
     * @Author mengkuiliang
     * @Description 获取预约记录
     * @Date 2023-01-29 15:55
     * @Param [query]
     * @return java.util.List<com.disease.business.domain.vo.ScreeningRecordVo>
     **/
    @Override
    public List<ScreeningRecordVo> list(ScreeningRecordDTO query) {
        return screeningRecordMapper.list(query);
    }

    /**
     * @Author mengkuiliang
     * @Description 获取筛查结果记录
     * @Date 2023-01-30 13:31
     * @Param [query]
     * @return java.util.List<com.disease.business.domain.vo.ScreeningRecordVo>
     **/
    @Override
    public List<ScreeningRecordVo> record(ScreeningRecordDTO query) {
        return screeningRecordMapper.record(query);
    }

    /**
     * @Author mengkuiliang
     * @Description 预约保存
     * @Date 2023-01-29 14:10
     * @Param [body]
     * @return void
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject save(ScreeningApplyDTO body) throws Exception {
        // 校验是否已经注册
        PatientInfoVO registerVo = patientService.selectPatientInfoByCardNo(body.getIdentity());
        if(registerVo == null) {
           throw new Exception("用户未注册");
        }
        if(StringUtils.isBlank(body.getPatientId())) {
        	body.setPatientId(String.valueOf(registerVo.getId()));
		}
	    // 查询 同一机构的同一筛查项目在同一天是否有预约
	    ScreeningRecordDTO query = new ScreeningRecordDTO();
	    query.setPatientId(body.getPatientId());
	    query.setHospitalId(body.getHospitalId());
	    query.setProjectId(body.getProjectId());
	    query.setApplyStartDate(body.getApplyStartTime());
	    query.setApplyEndDate(body.getApplyEndTime());
	    List<ScreeningRecordVo> recordList = list(query);
	    if (!CollectionUtils.isEmpty(recordList)) {
		    throw new Exception("已在" + DateUtils.formatDate(body.getApplyStartTime(), "yyyy年MM月dd日")  + "预约了" + body.getProjectName() + "项目不能重复预约");
	    }

        body.setScreeningId(IdUtils.fastSimpleUUID());
        ScreeningRecordApplyDTO recordBody = new ScreeningRecordApplyDTO();
        BeanUtils.copyProperties(body, recordBody);
        recordBody.setScreeningStatus("1");
	    recordBody.setApplyCode(generateCode());
	    recordBody.setScreeningType("1");
		try {
			// 预约条码
			recordBody.setApplyBarcode(generateBarcode(xinELuConfig.getApplyBarcodePitureUrl(), recordBody.getScreeningId(), recordBody.getApplyCode()));
		} catch (Exception e) {
			e.printStackTrace();
		}
		JSONObject result = new JSONObject();
		result.put("patientId", body.getPatientId());
        int flag = screeningRecordMapper.insert(recordBody);
		if(flag > 0) {
			// 组装发送消息通知参数
			result.put("openid", registerVo.getBindOpenid());
			result.put("receiveName", registerVo.getPatientName());
			result.put("text1", body.getHospitalName());
			result.put("text2", (body.getProjectName().length() >= 17? (body.getProjectName().substring(0, 17) + "..."): body.getProjectName()));
			result.put("text3", body.getProjectName());
			result.put("sendTitle", "筛查预约");
			result.put("sendTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", recordBody.getApplyStartTime()));
			result.put("busType", "10");
			result.put("sendContent", registerVo.getPatientName() + "预约筛查成功");
			result.put("messageType", "5");
			result.put("messageCategory", "4");
			result.put("cardNo", registerVo.getCardNo());
		}
        return result;
    }

	@Override
	public JSONObject update(ScreeningRecord body) {
		HospitalPersonInfo hospitalPersonInfo = hospitalPersonInfoMapper.selectHospitalPersonInfoById(SecurityUtils.getLoginUser().getUser().getHospitalPersonId());
		if (hospitalPersonInfo != null) {
			body.setDoctorId(hospitalPersonInfo.getId());
			body.setDoctorName(hospitalPersonInfo.getPersonName());
			HospitalInfo hospitalInfo = hospitalInfoMapper.selectHospitalInfoById(hospitalPersonInfo.getHospitalId());
			if (hospitalInfo != null) {
				body.setHospitalId(hospitalInfo.getId());
				body.setHospitalName(hospitalInfo.getHospitalName());
			}
		}

		body.setScreeningStatus("4");
		body.setScreeningDate(new Date());
		int flag = screeningRecordMapper.update(body);
		// 校验是否已经注册
		PatientInfoVO registerVo = patientService.selectPatientInfoById(Long.valueOf(body.getPatientId()));
		JSONObject result = new JSONObject();
		result.put("patientId", body.getPatientId());
		if (flag > 0) {
			// 组装发送消息通知参数
			result.put("openid", registerVo.getOpenid());
			result.put("receiveName", registerVo.getPatientName());
			result.put("sendTitle", "筛查预约");
			result.put("sendTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss", new Date()));
			result.put("senderName", SecurityUtils.getLoginUser().getUser().getNickName());
			result.put("busType", "");
			result.put("sendContent", "您的筛查项目已检测完成，点击查看详情。");
			result.put("messageType", "1");
			result.put("messageCategory", "4");
			result.put("cardNo", registerVo.getCardNo());
			result.put("contentId", body.getScreeningId());
			result.put("sourceType", "1");
		}
		return result;
	}

	/**
     * @Author mengkuiliang
     * @Description 取消预约
     * @Date 2023-01-29 14:10
     * @Param [screeningId]
     * @return void
     **/
    @Override
    public void cancel(String screeningId) {
        screeningRecordMapper.updateStatus(screeningId, "2", null);
    }

    /**
     * @Author mengkuiliang
     * @Description 登记
     * @Date 2023-01-29 14:31
     * @Param [body]
     * @return void
     **/
    @Override
    public String receive(String screeningId) throws Exception {
        LoginUser loginUser = SecurityUtils.getLoginUser();
	    ScreeningRecord screeningRecord = screeningRecordMapper.selectByScreeningId(screeningId);
	    // 判断预约是否过期，是否已登记
	    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
	    if (sdf.parse(DateUtils.formatDate(screeningRecord.getApplyEndTime(), "yyyy-MM-dd")).before(sdf.parse(DateUtils.formatDate(new Date(), "yyyy-MM-dd")))){
		    throw new Exception("患者预约已过期，不可进行登记。");
	    }
	    if (StringUtils.equals("3", screeningRecord.getScreeningStatus()) || StringUtils.equals("4", screeningRecord.getScreeningStatus())) {
		    throw new Exception("该预约已登记，请勿重复登记。");
	    }
		screeningRecord.setDoctorId(loginUser.getUser().getHospitalPersonId());
	    screeningRecord.setDoctorName(loginUser.getUser().getNickName());
	    screeningRecord.setRegistrationDate(new Date());
	    screeningRecord.setScreeningStatus("3");
	    // 生成登记条码
	    screeningRecord.setRegistrationCode(generateCode());
	    screeningRecord.setRegistrationBarcode(generateBarcode(xinELuConfig.getRegisterBarcodePitureUrl(), screeningRecord.getScreeningId(), screeningRecord.getRegistrationCode()));
	    int flag = screeningRecordMapper.update(screeningRecord);
	    return screeningRecord.getRegistrationCode();

    }

    /**
     * @Author mengkuiliang
     * @Description 取消登记
     * @Date 2023-01-29 14:31
     * @Param [screeningId]
     * @return void
     **/
    @Override
    public void cancelReceive(String screeningId) {
        screeningRecordMapper.updateStatus(screeningId, "1", null);
    }

    /**
     * @Author mengkuiliang
     * @Description 获取预约详情
     * @Date 2023-01-29 14:10
     * @Param [screeningId]
     * @return com.disease.business.domain.vo.ScreeningRecordVo
     **/
    @Override
    public ScreeningRecordVo detail(String screeningId) {
        ScreeningRecordVo recordVo =  screeningRecordMapper.detail(screeningId);
        if(recordVo == null) {
            return null;
        }
        return recordVo;
    }

    /**
     * @Author mengkuiliang
     * @Description 获取当前居民预约信息
     * @Date 2023-01-29 14:10
     * @Param [screeningId]
     * @return com.disease.business.domain.vo.ScreeningRecordVo
     **/
    @Override
    public ScreeningRecordVo getScreeningByPatientId(String patientId) {
        ScreeningRecordVo recordVo = screeningRecordMapper.getScreeningByPatientId(patientId);
        if(recordVo == null) {
            return null;
        }
        getRecordDetail(recordVo);
        return recordVo;
    }

    /**
     * @Author mengkuiliang
     * @Description 获取最新一次筛查结果
     * @Date 2023-01-30 11:46
     * @Param [patientId]
     * @return com.disease.business.domain.vo.ProjectRecordVo
     **/
    @Override
    public ScreeningRecordVo last(String patientId,String projectId) {
        ScreeningRecordVo recordVo = screeningRecordMapper.getScreeningOfLast(patientId, null, "1",projectId);
        if(recordVo == null) {
            return null;
        }
		if(StringUtils.isNotBlank(recordVo.getAttachment())) {
			String fileDir = XinELuConfig.getProfile() + recordVo.getAttachment().replaceAll("/profile", "");
			File file = new File(fileDir);
			if (file.exists() && file.isFile()) {
				String fileName = file.getName();
				recordVo.setFileType(fileName.substring(fileName.lastIndexOf(".") + 1));
			}
		}
	    if (!StringUtils.contains(recordVo.getProjectName(), ScreeningProjectConstants.ALZHEIMER)) {
		    getRecordDetail(recordVo);
	    }
        return recordVo;
    }

	@Override public List<SelectVo> getTimelineList(String patientId) {
		List<TimelineVo> timelineVos = screeningRecordMapper.selectTimeLineList(patientId);
		// 按照年份进行分组
		Map<String, List<TimelineVo>> groupByTime = timelineVos.stream().collect(Collectors.groupingBy(item-> DateUtils.formatDate(item.getCreateTime(), "yyyy")));
		List<SelectVo> timeList = new ArrayList<>();

		for (String time : groupByTime.keySet()) {
			List<TimelineVo> timelineVoList = groupByTime.get(time);
			List<SelectVo> children = timelineVoList.stream().map(child -> {
				SelectVo result = new SelectVo();
				result.setLabel(DateUtils.formatDate(child.getCreateTime(), "yyyy-MM-dd"));
				result.setValue(child.getId());
				return result;
			}).collect(Collectors.toList());

			timeList.add(SelectVo.builder()
				.label(time)
				.value(time)
				.children(children).build());
		}
		return timeList;
	}

	@Override public Integer pushScreening(ScreeningRecordSaveDTO body) throws Exception {
		List<ScreeningProject> projectList = body.getProjectList();
		int flag = 0;

		String assessRecordId = "";
		// 查询居民最新一次评估记录
		//List<RiskAssessRecord> riskAssessRecords = riskAssessRecordMapper.selectByPatientId(body.getPatientId());
		//if (riskAssessRecords != null && riskAssessRecords.size() > 0) {
		//	RiskAssessRecord riskAssessRecord = riskAssessRecords.get(riskAssessRecords.size() - 1);
		//	if (riskAssessRecord != null) {
		//		assessRecordId = riskAssessRecord.getAssessRecordId();
		//	}
		//} else {
		//	throw new Exception("还未评估，请评估后推送");
		//}
		for (ScreeningProject project : projectList) {
			ScreeningRecordApplyDTO screeningRecord = new ScreeningRecordApplyDTO();
			screeningRecord.setAssessRecordId(assessRecordId);
			screeningRecord.setScreeningId(IdUtils.fastSimpleUUID());
			screeningRecord.setProjectId(project.getProjectId());
			screeningRecord.setProjectName(project.getProjectName());
			screeningRecord.setPatientId(body.getPatientId());
			screeningRecord.setDoctorId(SecurityUtils.getLoginUser().getUser().getHospitalPersonId());
			screeningRecord.setDoctorName(SecurityUtils.getLoginUser().getUser().getNickName());
			HospitalPersonInfo hospitalPersonInfo = hospitalPersonInfoMapper.selectHospitalPersonInfoById(SecurityUtils.getLoginUser().getUser().getHospitalPersonId());
			if (hospitalPersonInfo == null) {
				throw new Exception("当前用户未绑定医生账号");
			} else {
				HospitalInfo hospitalInfo = hospitalInfoMapper.selectHospitalInfoById(hospitalPersonInfo.getHospitalId());
				if (hospitalInfo != null) {
					screeningRecord.setHospitalId(hospitalInfo.getId());
					screeningRecord.setHospitalName(hospitalInfo.getHospitalName());
				}
			}
			screeningRecord.setScreeningStatus("1");
			screeningRecord.setScreeningType("2");
			screeningRecord.setApplyStartTime(new Date());
			flag += screeningRecordMapper.insert(screeningRecord);
		}
		if (flag > 0) {
			// TODO 推送消息通知
			//JSONObject jsonObject = new JSONObject();
			//RegisterVo register = registerService.getByPatientId(body.getPatientId());
			//jsonObject.fluentPut("senderNo", SecurityUtils.getUserId())
			//	.fluentPut("senderName", SecurityUtils.getLoginUser().getUser().getNickName())
			//	.fluentPut("doctorName", SecurityUtils.getLoginUser().getUser().getNickName())
			//	.fluentPut("recipientName", register.getPatientName())
			//	.fluentPut("recipientIdentity", register.getIdentity())
			//	.fluentPut("sendTime", DateUtils.formatDate(new Date(), "yyyy-MM-dd HH:mm:ss"))
			//	.fluentPut("messageType", "4")
			//	.fluentPut("messageCategory", "1")
			//	.fluentPut("templateType", MessageTypeEnum.JTYSXXTZ.getType())
			//	.fluentPut("content", "根据评估结果您需筛查，详情请点击查看。")
			//	.fluentPut("contentId", assessRecordId);
			//FdmpPushMegUtil.sendPost(jsonObject);
		}
		return flag;
	}

	@Override public JSONObject getInfo(String assessRecordId) {
		// 根据评估记录业务主键查询医生推荐筛查项目
		JSONObject retObject = new JSONObject();
		ScreeningRecordDTO query = new ScreeningRecordDTO();
		query.setAssessRecordId(assessRecordId);
		List<ScreeningRecordVo> screeningRecordVoList = list(query);
		if (screeningRecordVoList != null && screeningRecordVoList.size() > 0) {
			List<String> projectName = screeningRecordVoList.stream().map(ScreeningRecordVo::getProjectName).collect(Collectors.toList());
			retObject.fluentPut("projectName", String.join("," , projectName))
				.fluentPut("doctorName", screeningRecordVoList.get(0).getDoctorName());
			PatientInfoVO patientInfoVO = patientService.selectPatientInfoById(screeningRecordVoList.get(0).getPatientId());
			retObject.fluentPut("name", patientInfoVO.getPatientName());
		}

		// 根据评估记录业务主键查询评估记录
		//RiskAssessRecord riskAssessRecord = riskAssessRecordMapper.selectById(assessRecordId);
		//if (riskAssessRecord != null) {
		//	String assessResult = "高血压等级：" + getRiskLevel(riskAssessRecord.getRiskLevelHbp()) +";糖尿病风险等级：" +getRiskLevel(riskAssessRecord.getRiskLevelDm());
		//	retObject.fluentPut("assessResult", assessResult);
		//} else {
		//	retObject.fluentPut("assessResult", "未评估");
		//}
		return retObject;
	}

	private String getRiskLevel(String riskLevel) {
		String value = "正常";
		switch (riskLevel) {
			case "0" :
				value = "正常";
			break;
			case "1" :
				value = "低危";
			break;
			case "2" :
				value = "中危";
			break;
			case "3" :
				value = "高危";
			break;
		}
		return value;
	}
	/** 获取检测项目记录 */
	@Override
    public void getRecordDetail(ScreeningRecordVo vo) {
        // 拼接预约时间区间
        vo.setApplyTime(DateUtils.formatDate(vo.getApplyStartTime(), "yyyy年MM月dd日") + " " + DateUtils.formatDate(vo.getApplyStartTime(), "HH:mm") + "~" + DateUtils.formatDate(vo.getApplyEndTime(), "HH:mm"));
	    setAttachment(vo);
    }

    /** 获取图片附件转base64 */
    private void setAttachment(ScreeningRecordVo record) {
        if(StringUtils.isNotBlank(record.getAttachment())) {
	        String fileDir = XinELuConfig.getProfile() + record.getAttachment().replaceAll("/profile", "");
	        File file = new File(fileDir);
			if(file.exists() && file.isFile()) {
				record.setAttachment(FileUtils.PicToBase64(fileDir));
			}
        }
        if(StringUtils.isNotBlank(record.getAttachmentTwo())) {
	        String fileDir = XinELuConfig.getProfile() + record.getAttachmentTwo().replaceAll("/profile", "");
	        File file = new File(fileDir);
			if (file.exists() && file.isFile()) {
				record.setAttachmentTwo(FileUtils.PicToBase64(fileDir));
			}
        }
    }

	/**
	 * 生成预约码
	 * @return
	 */
	private String generateCode() {
		return System.currentTimeMillis() + "";
	}

	/**
	 * 生成条码
	 * @param url
	 * @param screeningId
	 * @param content
	 */
	private String generateBarcode(String url, String screeningId, String content) {
		String uploadPathUrl = XinELuConfig.getProfile() + url + "/";
		String fileName = screeningId + ".jpg";
		QrCodeUtils.createTxm(content, uploadPathUrl, fileName);
		return uploadPathUrl + fileName;
	}
}




