package com.diagbot.facade.data;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.diagbot.dto.RespDTO;
import com.diagbot.dto.data.ABehospitalInfoDTO;
import com.diagbot.entity.BasDoctorInfo;
import com.diagbot.entity.BehospitalInfo;
import com.diagbot.entity.MedicalRecord;
import com.diagbot.entity.QcType;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.facade.BehospitalInfoFacade;
import com.diagbot.facade.QcAbnormalFacade;
import com.diagbot.facade.QcTypeFacade;
import com.diagbot.service.impl.BehospitalInfoServiceImpl;
import com.diagbot.util.BeanUtil;
import com.diagbot.util.DateUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.util.TZDBConn;
import com.diagbot.vo.data.ABehospitalInfoVO;
import com.diagbot.vo.data.ADeleteFlagVO;
import com.diagbot.vo.data.AMedicalRecordVO;
import com.diagbot.vo.data.APlaceFileVO;
import com.google.common.collect.Lists;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
public class ABehospitalInfoFacade extends BehospitalInfoServiceImpl {
    @Autowired
    @Qualifier("behospitalInfoServiceImpl")
    private BehospitalInfoServiceImpl behospitalInfoService;
    @Autowired
    private QcTypeFacade qcTypeFacade;
    @Autowired
    private AMedAbnormalInfoFacade aMedAbnormalInfoFacade;
    @Value("${log_switch.enable}")
    private boolean logSwitch;
    @Autowired
    private AMedicalRecordFacade aMedicalRecordFacade;
    @Autowired
    private SendDataDealFacade sendDataDealFacade;
    @Autowired
    private ABasDoctorInfoFacade aBasDoctorInfoFacade;

    private TZDBConn tzDBConn = new TZDBConn();

    /**
     * 终末质控-同步前一天的入院记录
     */
    public void executeBehospital() {
        //String sql="select * from br_inpatientinfo where cjcxrq>=dateadd(day,-2,getdate()) and cjcxrq<=getdate()";
        String sql="select * from br_inpatientinfo where cjcxrq>=(select CONVERT(varchar,GETDATE()-2,23)) and cjcxrq<(select CONVERT(varchar,GETDATE(),23)) ORDER BY cjcxrq DESC";
        List<BehospitalInfo> behospitalInfoList = tzDBConn.getBehospitalInfo(sql);
        execute(behospitalInfoList);
    }

    /**
     * 同步前一天的入院记录
     */
    public void executeBehospitalPast() {
        String sql="select * from br_inpatientinfo where cjcxrq>=dateadd(day,-2,getdate()) and cjcxrq<=getdate()";
        List<BehospitalInfo> behospitalInfoList = tzDBConn.getBehospitalInfo(sql);
        execute(behospitalInfoList);
    }


    /**
     * 通过接口更新病人住院记录信息
     * @param list
     * @return
     */
    public RespDTO<List<ABehospitalInfoDTO>> executeBehospital(List<ABehospitalInfoVO> list) {
        try {
            if(list!=null && list.size()>0) {
                //循环验证数据有效性
                for (ABehospitalInfoVO behospitalInfo:list) {
                    if("".equals(behospitalInfo.getBehospitalCode())) {
                        return RespDTO.onError("请输入病人住院编码!");
                    }else if(behospitalInfo.getHospitalId()==null){
                        return RespDTO.onError("请输入医院编码!");
                    }else if("".equals(behospitalInfo.getBehDeptId())){
                        return RespDTO.onError("请输入住院科室编码!");
                    }else if("".equals(behospitalInfo.getBehDeptName())){
                        return RespDTO.onError("请输入住院科室名称!");
                    }
                }

                List<BehospitalInfo> behospitalInfoList = Lists.newArrayList();
                list.stream().forEach(s->{
                    BehospitalInfo behospitalInfo=new BehospitalInfo();
                    BeanUtil.copyProperties(s,behospitalInfo);
                    if(StringUtil.isNotBlank(s.getBirthday())) {
                        behospitalInfo.setBirthday(DateUtil.parseDate(s.getBirthday()));
                    }
                    if(StringUtil.isNotBlank(s.getLeaveHospitalDate())) {
                        behospitalInfo.setLeaveHospitalDate(DateUtil.parseDateTime(s.getLeaveHospitalDate()));
                    }
                    if(StringUtil.isNotBlank(s.getBehospitalDate())){
                        behospitalInfo.setBehospitalDate(DateUtil.parseDateTime(s.getBehospitalDate()));
                    }
                    if(StringUtil.isNotBlank(s.getPlacefileDate())){
                        behospitalInfo.setPlacefileDate(DateUtil.parseDateTime(s.getPlacefileDate()));
                    }
                    behospitalInfoList.add(behospitalInfo);

                });

                execute(behospitalInfoList);
                if(true){
                    behospitalInfoList.forEach(s->{
                        aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-正常","", JSON.toJSONString(list),"","");
                    });
                }
                return RespDTO.onSuc("操作正常！");
            }else{
                return RespDTO.onError("未接收到数据!");
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
            aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-异常","", JSON.toJSONString(list),"",e.getMessage());
            return RespDTO.onError("数据处理异常，详情查看日志表");
        }
    }

    public void execute(List<BehospitalInfo> behospitalInfoList){
        List<BehospitalInfo> addE = Lists.newLinkedList();
        List<BehospitalInfo> updateE = Lists.newLinkedList();
        behospitalInfoList.stream().forEach(s -> {
            BehospitalInfo behospitalInfo = this.getOne(new QueryWrapper<BehospitalInfo>()
                    .eq("behospital_code", s.getBehospitalCode())
                    .eq("hospital_id", s.getHospitalId()));
            //判断doctorId是否为数字，不为数字的情况下采用之前的doctorId
            Pattern pattern = Pattern.compile("-?[0-9]+\\.?[0-9]*");
            Matcher isNum = pattern.matcher(StringUtils.isNotEmpty(s.getDoctorId())?s.getDoctorId():"-");
            if (behospitalInfo != null) {
                if (!isNum.matches()){
                    s.setDoctorId(StringUtils.isNotEmpty(behospitalInfo.getDoctorId())?behospitalInfo.getDoctorId():"-");
                }
                s.setIsDeleted("N");
                s.setGmtModified(new Date());
                s.setQcTypeId(initQcTypeId(s));
                updateE.add(s);
            } else {
                s.setGmtCreate(new Date());
                s.setQcTypeId(initQcTypeId(s));
                this.save(s);
            }
        });
        if(addE.size()>0){
            behospitalInfoService.saveBatch(addE);
        }
        if(updateE.size()>0){
            behospitalInfoService.updateBatchByKey(updateE);
        }
    }

    /**
     * 初始化QcTypeId
     * @param s
     * @return
     */
    private Long initQcTypeId(BehospitalInfo s) {
        Long qcTypeId = Long.valueOf("0");
        //判断一下是否是日间病例
        if (null != s.getLeaveHospitalDate()&& null !=s.getBehospitalDate()){
                if (this.differentDays(s.getBehospitalDate(),s.getLeaveHospitalDate())<=1) {
                    return qcTypeId;
                }
        }
        if("麻痹性痴呆".equals(s.getDiagnose())){
            qcTypeId = Long.valueOf(200);
            return qcTypeId;
        }
        //判断文书表中是否有入院记录文书
        List<MedicalRecord> medicalRecordList= aMedicalRecordFacade.list(new QueryWrapper<MedicalRecord>()
        .eq("mode_id",1)
        .eq("behospital_code",s.getBehospitalCode())
        .eq("hospital_id",s.getHospitalId())
        .eq("is_deleted",IsDeleteEnum.N));
        //根据疾病来判断是否有对映的质控类型
        List<QcType> qcTypes =qcTypeFacade.list(new QueryWrapper<QcType>()
                .eq("name", StringUtils.isNotEmpty(s.getDiagnose())?s.getDiagnose():"")
                .eq("hospital_id",s.getHospitalId())
                .eq("is_deleted",IsDeleteEnum.N));
        if (qcTypes.size()>0){
            qcTypeId=qcTypes.get(0).getId();
        }else if (medicalRecordList.size()>=1){
            //根据科室来判断是否有对映的质控类型
            List<QcType> qcTypeList =qcTypeFacade.list(new QueryWrapper<QcType>()
                    .eq("beh_dept_id",s.getBehDeptId())
                    .eq("hospital_id",s.getHospitalId())
                    .eq("is_deleted",IsDeleteEnum.N));
            if (qcTypeList.size()==0){
                //没有对映的科室就根据病人的性别来判断
                QcType qcType = qcTypeFacade.getOne(new QueryWrapper<QcType>()
                        .eq("default_module",1)
                        .eq("hospital_id",s.getHospitalId())
                        .eq("sex",s.getSex())
                        .eq("is_deleted",IsDeleteEnum.N));
                qcTypeId =qcType.getId();
            }else if (qcTypeList.size()==1){
                qcTypeId =qcTypeList.get(0).getId();
            }else {
                //有多个科室信息就根据病人的男女来判断有对映的质控类型
                QcType qcType =new QcType();
                qcTypeList.forEach(qc->{
                    if (qc.getSex().equals(s.getSex()))
                        qcType.setId(qc.getId());
                });
                qcTypeId =qcType.getId();
            }
        }
        return qcTypeId;
    }

    public RespDTO deleteFlag(ADeleteFlagVO aDeleteFlagVO){
        try {
            //验证数据是否存在
            if(StringUtil.isEmpty(aDeleteFlagVO.getBehospitalCode())){
                return RespDTO.onError("请输入病人住院编码!");
            }else if(aDeleteFlagVO.getHospitalId()==null){
                return RespDTO.onError("请输入医院编码!");
            }else {
                UpdateWrapper<BehospitalInfo> updateWrapper=new UpdateWrapper<>();
                updateWrapper.eq("behospital_code", aDeleteFlagVO.getBehospitalCode())
                        .eq("hospital_id", aDeleteFlagVO.getHospitalId())
                        .eq("is_deleted",IsDeleteEnum.N)
                        .set("is_deleted",IsDeleteEnum.Y)
                        .set("gmt_modified", DateUtil.now());

                Boolean flag=update(new BehospitalInfo(),updateWrapper);
                //aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-删除",JSON.toJSONString(aDeleteFlagVO),"","删除成功!");
                return RespDTO.onSuc(flag);
            }
        }catch (Exception e){
            aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-删除","",JSON.toJSONString(aDeleteFlagVO),"",e.getMessage());
            return RespDTO.onError(e.getMessage());
        }
    }

    public RespDTO placeFileFlag(APlaceFileVO aPlaceFileVO){
        try {
            //从新拉取最新的入院登记
            sendDataDealFacade.sendInfo(aPlaceFileVO.getBehospitalCode());
            //时间转换
            String date="";
            if (StringUtils.isNotBlank(aPlaceFileVO.getPlaceFileDate())){
            date=aPlaceFileVO.getPlaceFileDate().replace("/", "-");
            }
            //验证数据是否存在
            if(StringUtil.isBlank(aPlaceFileVO.getBehospitalCode())){
                return RespDTO.onError("请输入病人住院编码!");
            }else if(aPlaceFileVO.getHospitalId()==null){
                return RespDTO.onError("请输入医院编码!");
            }else{
                UpdateWrapper<BehospitalInfo> updateWrapper=new UpdateWrapper<>();
                updateWrapper.eq("behospital_code", aPlaceFileVO.getBehospitalCode())
                        .eq("hospital_id", aPlaceFileVO.getHospitalId())
                        .eq("is_deleted",IsDeleteEnum.N)
                        .set("is_placefile","1")
                        .set("placefile_date",StringUtils.isNotEmpty(date)?DateUtil.parseDateTime(date):DateUtil.now())
                        .set("gmt_modified", DateUtil.now());

                Boolean flag=update(new BehospitalInfo(),updateWrapper);
                aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-归档 ","",JSON.toJSONString(aPlaceFileVO),flag.toString(),DateUtil.now()+"");
                return RespDTO.onSuc(flag);
            }
        }catch (Exception e){
            aMedAbnormalInfoFacade.saveAbnormalInfo("病人住院登记-归档cuowu ","",JSON.toJSONString(aPlaceFileVO),"",e.getMessage());
            return RespDTO.onError(e.getMessage());
        }
    }

    public  int differentDays(Date date1,Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);

        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2)   //不同一年
        {
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0)    //闰年
                {
                    timeDistance += 366;
                }
                else    //不是闰年
                {
                    timeDistance += 365;
                }
            }

            return timeDistance + (day2-day1) ;
        }
        else    //同一年
        {
            System.out.println("判断day2 - day1 : " + (day2-day1));
            return day2-day1;
        }
    }
}
