package com.docus.server.validate;

import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.server.dto.recovery.rcvbasic.AddRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.MedicalInfoExcelModel;
import com.docus.server.entity.recovery.RcvBasic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
@Slf4j
public class MedicalImportExcelValidator {
    public void validate(List<Object> excelData) {
        if (Func.isEmpty(excelData)) {
            throw new BaseException("导如数据不能为空！");
        }
        MedicalInfoExcelModel medicalInfoExcelModel;
        // 验证重复的病案信息 住院号@住院次数@患者姓名@出院时间 （yyyy-MM-dd）  组合
        Set<String> patientInfos = new HashSet<>();
        final String patientInfoTemplate = "%s@%s@%s@%s@%s";
        for (Object obj : excelData) {
            if (Func.isNull(obj)) {
                throw new BaseException("中间行数据不能为空");
            }
            // 使用的模板下载，可以强转
            medicalInfoExcelModel = (MedicalInfoExcelModel) obj;

            if (Func.isBlank(medicalInfoExcelModel.getAdmissId())) {
                throw new BaseException("住院号不能为空");
            }

            if (Func.isEmpty(medicalInfoExcelModel.getAdmissTimes())) {
                throw new BaseException("住院次数不能为空");
            }

            if (Func.isNull(medicalInfoExcelModel.getSerialNumber())) {
                throw new BaseException("流水号不能为空");
            }

            if (Func.isBlank(medicalInfoExcelModel.getName())) {
                throw new BaseException("患者姓名不能为空");
            }

//            if (Func.isBlank(medicalInfoExcelModel.getAttendingName())) {
//                throw new BaseException("住院医师不能为空");
//            }

            String excelModelDisDate = medicalInfoExcelModel.getDisDate();
            if (Func.isBlank(excelModelDisDate)) {
                throw new BaseException("出院日期不能为空！");
            }

            if (Func.isBlank(medicalInfoExcelModel.getDisDept())) {
                throw new BaseException("出院科室编码不能为空");
            }

            if (Func.isBlank(medicalInfoExcelModel.getDisDeptName())) {
                throw new BaseException("出院科室名称不能为空");
            }

            // 有 / 分隔年月日的，转为 - 进行验证和转换
            String transDisDateStr = excelModelDisDate.replace("/", "-");
            Date disDate = parseDate(transDisDateStr);
            if (Func.isNull(disDate)) {
                throw new BaseException("出院日期格式解析错误！" + excelModelDisDate);
            }
            medicalInfoExcelModel.setDisDate(Func.formatDateTime(disDate));

            String disDateStr = Func.formatDate(disDate);

            // 住院号@住院次数@患者姓名@出院时间 （yyyy-MM-dd）  组合
            String patientInfo = String.format(patientInfoTemplate,
                medicalInfoExcelModel.getAdmissId(),
                medicalInfoExcelModel.getAdmissTimes(),
                medicalInfoExcelModel.getSerialNumber(),
                medicalInfoExcelModel.getName(),
                disDateStr);

            if (patientInfos.contains(patientInfo)) {
                throw new BaseException("本次导入有重复数据，请检查!住院号："
                    + medicalInfoExcelModel.getAdmissId()
                    + " 住院次数：" + medicalInfoExcelModel.getAdmissTimes()
                    + " 流水号：" + medicalInfoExcelModel.getSerialNumber()
                    + " 患者姓名：" + medicalInfoExcelModel.getName()
                    + " 出院日期：" + disDateStr);
            }
            patientInfos.add(patientInfo);
        }
    }

    /**
     * 解析日期时间字符串成为Date对象，日期时间字符串 ，支持 yyyy-MM-dd，yyyy-MM-dd HH，yyyy-MM-dd HH:mm，yyyy-MM-dd HH:mm:ss 四种格式
     *
     * @param dateStr 日期时间字符串
     * @return 日期对象, 转换错误返回null
     */
    public static Date parseDate(String dateStr) {
        final String dateTimeStr = dateStr.trim();
        final String example1 = "yyyy-MM-dd";
        final String example2 = "yyyy-MM-dd HH";
        final String example3 = "yyyy-MM-dd HH:mm";
        final String example4 = "yyyy-MM-dd HH:mm:ss";
        try {
            if (dateTimeStr.length() == example1.length()) {
                return Func.parseDate(dateTimeStr, example1);
            }
            if (dateTimeStr.length() == example2.length()) {
                return Func.parseDate(dateTimeStr, example2);
            }
            if (dateTimeStr.length() == example3.length()) {
                return Func.parseDate(dateTimeStr, example3);
            }
            return Func.parseDate(dateTimeStr, example4);
        } catch (Exception ex) {
            log.error(ex.getMessage(), ex);
            return null;
        }

    }

    public boolean isDataBaseExistsAndChangePatientId(AddRcvBasicDTO importExcelModelDto, Map<String, List<RcvBasic>> stringListMap) {
        if (Func.isNull(stringListMap)) {
            return false;
        }
        String serialNumber = importExcelModelDto.getSerialNumber();
        List<RcvBasic> rcvBasics = stringListMap.get(serialNumber);

        if (Func.isNotEmpty(rcvBasics)) {
            for (RcvBasic basic : rcvBasics) {
                if (Func.isNull(basic.getDisDate())) {
                    continue;
                }
                if (Func.isNull(basic.getAdmissTimes())) {
                    continue;
                }
                if (Func.isBlank(basic.getName())) {
                    continue;
                }

                String databaseDisDate = Func.formatDateTime(basic.getDisDate());
                String importDataDisDate = Func.formatDateTime(importExcelModelDto.getDisDate());
                // 住院次数、患者姓名、出院时间 （yyyy-MM-dd）  组合,如果存在，修改对象的patientId 且返回 true
                if (basic.getAdmissTimes().equals(importExcelModelDto.getAdmissTimes())
                    && databaseDisDate.equals(importDataDisDate)
                    && basic.getName().equals(importExcelModelDto.getName())) {
                    importExcelModelDto.setId(basic.getId());
                    return true;
                }
            }
        }
        return false;
    }
}
