package com.yihu.wlyy.service.app.disease;

import com.yihu.wlyy.entity.dict.Disease;
import com.yihu.wlyy.entity.patient.SignFamily;
import com.yihu.wlyy.entity.doctor.team.sign.DoctorPatientGroupInfo;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.patient.PatientDisease;
import com.yihu.wlyy.repository.dict.DiseaseDao;
import com.yihu.wlyy.repository.doctor.DoctorPatientGroupInfoDao;
import com.yihu.wlyy.repository.patient.PatientDao;
import com.yihu.wlyy.repository.patient.PatientDiseaseDao;
import com.yihu.wlyy.repository.patient.SignFamilyDao;
import com.yihu.wlyy.service.BaseService;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;

/**
 * 患者疾病服务
 * <p>
 * Created by lyr on 2016/09/09.
 */
@Service
@Transactional
public class PatientDiseaseService extends BaseService {

    @Autowired
    DiseaseDao diseaseDao;
    @Autowired
    PatientDiseaseDao patientDiseaseDao;
    @Autowired
    DoctorPatientGroupInfoDao groupInfoDao;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    SignFamilyDao signFamilyDao;
    @Autowired
    PatientDao patientDao;
    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 根据居民code查询疾病
     *
     * @param patient 居民code
     * @return
     */
    public List<PatientDisease> getPatientDisease(String patient) {
        return patientDiseaseDao.findByPatient(patient);
    }

    /**
     * 根据居民code查询三师疾病
     *
     * @param patient 居民code
     * @return
     */
    public List<PatientDisease> getPatientSsDisease(String patient) {
        return patientDiseaseDao.findByPatientSsDisease(patient);
    }

    /**
     * 根据居民code查询疾病
     *
     * @param patient 居民code
     * @return
     */
    public List<PatientDisease> getPatientDiseaseSs(String patient) {
        return patientDiseaseDao.findByPatientAndSignType(patient,"1");
    }

    /**
     * 更新患者疾病表
     *
     * @param patient 患者
     * @param disease 疾病
     * @return
     */
    public boolean updatePatientDisease(String patient, String disease) {
        try {
            // 删除患者家庭签约疾病
            patientDiseaseDao.updateDiseaseDel(patient);

            if (!StringUtils.isEmpty(disease) && !disease.equals("0")) {
                String[] diseases = disease.split(",");

                List<PatientDisease> patientDiseases = new ArrayList<>();

                for (String dis : diseases) {
                    if (StringUtils.isEmpty(dis)) {
                        continue;
                    } else {
                        PatientDisease patientDisease = new PatientDisease();
                        // 疾病信息
                        Disease disea = diseaseDao.findByCode(dis);

                        // 患者
                        patientDisease.setPatient(patient);
                        // 疾病
                        patientDisease.setDisease(dis);
                        patientDisease.setDel("1");
                        patientDisease.setSignType("2");

                        if (disea != null) {
                            // 疾病名字
                            patientDisease.setDiseaseName(disea.getName());
                        }
                        // 更新日期
                        patientDisease.setCzrq(new Date());
                        patientDiseases.add(patientDisease);
                    }
                }

                List<String> diseaseList = Arrays.asList(diseases);

                // 重新分组
                if (!changeGroupInfo(patient, diseaseList)) {
                    throw new Exception("set group falied");
                }

                if (patientDiseases.size() > 0) {
                    Iterable<PatientDisease> savedPatientDiseases = patientDiseaseDao.save(patientDiseases);
                    JSONArray redisValues = new JSONArray();

                    for (PatientDisease patientDisease : savedPatientDiseases) {
                        JSONObject redisValue = new JSONObject();
                        redisValue.put("disease", patientDisease.getDisease());
                        redisValue.put("diseaseName", patientDisease.getDiseaseName());
                        redisValue.put("del", patientDisease.getDel());
                        redisValue.put("signType", patientDisease.getSignType());
                        redisValues.put(redisValue);
                    }

                    List<PatientDisease> ssDisease = patientDiseaseDao.findByPatientSsDisease(patient);
                    if (ssDisease != null && ssDisease.size() > 0) {
                        for (PatientDisease pd : ssDisease) {
                            JSONObject redisValue = new JSONObject();
                            redisValue.put("disease", pd.getDisease());
                            redisValue.put("diseaseName", pd.getDiseaseName());
                            redisValue.put("del", pd.getDel());
                            redisValue.put("signType", pd.getSignType());
                            redisValues.put(redisValue);
                        }
                    }
                    // redis缓存患者疾病
                    redisTemplate.opsForValue().set("disease:" + patient, redisValues.toString());
                }
            } else {
                JSONArray redisValues = new JSONArray();
                List<PatientDisease> ssDisease = patientDiseaseDao.findByPatientSsDisease(patient);
                List<String> disList = new ArrayList<>();
                if (ssDisease != null && ssDisease.size() > 0) {
                    for (PatientDisease pd : ssDisease) {
                        JSONObject redisValue = new JSONObject();
                        redisValue.put("disease", pd.getDisease());
                        redisValue.put("diseaseName", pd.getDiseaseName());
                        redisValue.put("del", pd.getDel());
                        redisValue.put("signType", pd.getSignType());
                        redisValues.put(redisValue);
                        disList.add(pd.getDisease());
                    }
                }
                redisTemplate.opsForValue().set("disease:" + patient, redisValues.toString());
                // 重新分组
                if (!changeGroupInfo(patient, disList)) {
                    throw new Exception("set group falied");
                }
            }

            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 病人分组
     *
     * @param patient
     * @param diseases
     * @return
     * @throws Exception
     */
    public boolean changeGroupInfo(String patient, List<String> diseases) throws Exception {
        SignFamily jjSign = signFamilyDao.findSignByPatient(patient, 2);
        SignFamily ssSign = signFamilyDao.findSignByPatient(patient, 1);
        Patient p = patientDao.findByCode(patient);

        if (jjSign == null && ssSign == null) {
            throw new Exception("can not find patient's sign info");
        }
        if (patient == null) {
            throw new Exception("can not find patient's info");
        }

        if (diseases.contains("1") || diseases.contains("2")) {
            // 慢病分组
            if (jjSign != null) {
                if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctor(), patient, "2", "2") < 1) {
                    DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                    ncdGroup.setDoctor(jjSign.getDoctor());
                    ncdGroup.setPatient(patient);
                    ncdGroup.setSignType("2");
                    ncdGroup.setCzrq(new Date());
                    ncdGroup.setStatus(1);
                    ncdGroup.setPname(jjSign.getName());
                    ncdGroup.setQyrq(jjSign.getApplyDate());
                    ncdGroup.setDqrq(jjSign.getEnd());
                    ncdGroup.setGroup("2");

                    groupInfoDao.save(ncdGroup);
                }
                if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctorHealth(), patient, "2", "2") < 1) {
                    DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                    ncdJgGroup.setDoctor(jjSign.getDoctorHealth());
                    ncdJgGroup.setPatient(patient);
                    ncdJgGroup.setSignType("2");
                    ncdJgGroup.setCzrq(new Date());
                    ncdJgGroup.setStatus(1);
                    ncdJgGroup.setPname(jjSign.getName());
                    ncdJgGroup.setQyrq(jjSign.getApplyDate());
                    ncdJgGroup.setDqrq(jjSign.getEnd());
                    ncdJgGroup.setGroup("2");

                    groupInfoDao.save(ncdJgGroup);
                }
            }
            if (ssSign != null) {
                if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctor(), patient, "2", "1") < 1) {
                    DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                    ncdGroup.setDoctor(ssSign.getDoctor());
                    ncdGroup.setPatient(patient);
                    ncdGroup.setSignType("1");
                    ncdGroup.setCzrq(new Date());
                    ncdGroup.setStatus(1);
                    ncdGroup.setPname(ssSign.getName());
                    ncdGroup.setQyrq(ssSign.getApplyDate());
                    ncdGroup.setDqrq(ssSign.getEnd());
                    ncdGroup.setGroup("2");

                    groupInfoDao.save(ncdGroup);
                }
                if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctorHealth(), patient, "2", "1") < 1) {
                    DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                    ncdJgGroup.setDoctor(ssSign.getDoctorHealth());
                    ncdJgGroup.setPatient(patient);
                    ncdJgGroup.setSignType("1");
                    ncdJgGroup.setCzrq(new Date());
                    ncdJgGroup.setStatus(1);
                    ncdJgGroup.setPname(ssSign.getName());
                    ncdJgGroup.setQyrq(ssSign.getApplyDate());
                    ncdJgGroup.setDqrq(ssSign.getEnd());
                    ncdJgGroup.setGroup("2");

                    groupInfoDao.save(ncdJgGroup);
                }
            }
            groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "1", 0);
            groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "3", 0);
            groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "1", 0);
            groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "3", 0);
        } else {
            boolean isSixFive = false;
            String birth = p.getIdcard().substring(6, 14);
            int year = Integer.valueOf(birth.substring(0, 4));
            int month = Integer.valueOf(birth.substring(4, 6));
            int day = Integer.valueOf(birth.substring(6));
            Calendar cal = Calendar.getInstance();
            int age = cal.get(Calendar.YEAR) - year;
            //周岁计算
            if (cal.get(Calendar.MONTH) > (month - 1) || (cal.get(Calendar.MONTH) == (month - 1) && cal.get(Calendar.DATE) > day)) {
                age--;
            }
            if (age >= 65) {
                isSixFive = true;
            }

            if (isSixFive) {
                // 65岁以上分组
                if (jjSign != null) {
                    if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctor(), patient, "3", "2") < 1) {
                        DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                        ncdGroup.setDoctor(jjSign.getDoctor());
                        ncdGroup.setPatient(patient);
                        ncdGroup.setSignType("2");
                        ncdGroup.setCzrq(new Date());
                        ncdGroup.setStatus(1);
                        ncdGroup.setPname(jjSign.getName());
                        ncdGroup.setQyrq(jjSign.getApplyDate());
                        ncdGroup.setDqrq(jjSign.getEnd());
                        ncdGroup.setGroup("3");

                        groupInfoDao.save(ncdGroup);
                    }
                    if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctorHealth(), patient, "3", "2") < 1) {
                        DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                        ncdJgGroup.setDoctor(jjSign.getDoctorHealth());
                        ncdJgGroup.setPatient(patient);
                        ncdJgGroup.setSignType("2");
                        ncdJgGroup.setCzrq(new Date());
                        ncdJgGroup.setStatus(1);
                        ncdJgGroup.setPname(jjSign.getName());
                        ncdJgGroup.setQyrq(jjSign.getApplyDate());
                        ncdJgGroup.setDqrq(jjSign.getEnd());
                        ncdJgGroup.setGroup("3");

                        groupInfoDao.save(ncdJgGroup);
                    }
                }
                if (ssSign != null) {
                    if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctor(), patient, "3", "1") < 1) {
                        DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                        ncdGroup.setDoctor(ssSign.getDoctor());
                        ncdGroup.setPatient(patient);
                        ncdGroup.setSignType("1");
                        ncdGroup.setCzrq(new Date());
                        ncdGroup.setStatus(1);
                        ncdGroup.setPname(ssSign.getName());
                        ncdGroup.setQyrq(ssSign.getApplyDate());
                        ncdGroup.setDqrq(ssSign.getEnd());
                        ncdGroup.setGroup("3");

                        groupInfoDao.save(ncdGroup);
                    }
                    if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctorHealth(), patient, "3", "1") < 1) {
                        DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                        ncdJgGroup.setDoctor(ssSign.getDoctorHealth());
                        ncdJgGroup.setPatient(patient);
                        ncdJgGroup.setSignType("1");
                        ncdJgGroup.setCzrq(new Date());
                        ncdJgGroup.setStatus(1);
                        ncdJgGroup.setPname(ssSign.getName());
                        ncdJgGroup.setQyrq(ssSign.getApplyDate());
                        ncdJgGroup.setDqrq(ssSign.getEnd());
                        ncdJgGroup.setGroup("3");

                        groupInfoDao.save(ncdJgGroup);
                    }
                }
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "1", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "2", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "1", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "2", 0);
            } else {
                // 普通分组
                if (jjSign != null) {
                    if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctor(), patient, "1", "2") < 1) {
                        DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                        ncdGroup.setDoctor(jjSign.getDoctor());
                        ncdGroup.setPatient(patient);
                        ncdGroup.setSignType("2");
                        ncdGroup.setCzrq(new Date());
                        ncdGroup.setStatus(1);
                        ncdGroup.setPname(jjSign.getName());
                        ncdGroup.setQyrq(jjSign.getApplyDate());
                        ncdGroup.setDqrq(jjSign.getEnd());
                        ncdGroup.setGroup("1");

                        groupInfoDao.save(ncdGroup);
                    }
                    if (groupInfoDao.countDoctorPatientGroupType(jjSign.getDoctorHealth(), patient, "1", "2") < 1) {
                        DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                        ncdJgGroup.setDoctor(jjSign.getDoctorHealth());
                        ncdJgGroup.setPatient(patient);
                        ncdJgGroup.setSignType("2");
                        ncdJgGroup.setCzrq(new Date());
                        ncdJgGroup.setStatus(1);
                        ncdJgGroup.setPname(jjSign.getName());
                        ncdJgGroup.setQyrq(jjSign.getApplyDate());
                        ncdJgGroup.setDqrq(jjSign.getEnd());
                        ncdJgGroup.setGroup("1");

                        groupInfoDao.save(ncdJgGroup);
                    }
                }
                if (ssSign != null) {
                    if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctor(), patient, "1", "1") < 1) {
                        DoctorPatientGroupInfo ncdGroup = new DoctorPatientGroupInfo();

                        ncdGroup.setDoctor(ssSign.getDoctor());
                        ncdGroup.setPatient(patient);
                        ncdGroup.setSignType("1");
                        ncdGroup.setCzrq(new Date());
                        ncdGroup.setStatus(1);
                        ncdGroup.setPname(ssSign.getName());
                        ncdGroup.setQyrq(ssSign.getApplyDate());
                        ncdGroup.setDqrq(ssSign.getEnd());
                        ncdGroup.setGroup("1");

                        groupInfoDao.save(ncdGroup);
                    }
                    if (groupInfoDao.countDoctorPatientGroupType(ssSign.getDoctorHealth(), patient, "1", "1") < 1) {
                        DoctorPatientGroupInfo ncdJgGroup = new DoctorPatientGroupInfo();

                        ncdJgGroup.setDoctor(ssSign.getDoctorHealth());
                        ncdJgGroup.setPatient(patient);
                        ncdJgGroup.setSignType("1");
                        ncdJgGroup.setCzrq(new Date());
                        ncdJgGroup.setStatus(1);
                        ncdJgGroup.setPname(ssSign.getName());
                        ncdJgGroup.setQyrq(ssSign.getApplyDate());
                        ncdJgGroup.setDqrq(ssSign.getEnd());
                        ncdJgGroup.setGroup("1");

                        groupInfoDao.save(ncdJgGroup);
                    }
                }
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "2", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctor() : ssSign.getDoctor(), patient, "3", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "2", 0);
                groupInfoDao.updateDoctorPatientGroup(jjSign != null ? jjSign.getDoctorHealth() : ssSign.getDoctorHealth(), patient, "3", 0);
            }
        }

        return true;
    }

    /**
     * 更新患者疾病到redis
     */
    public void updateToRedis() {
        String sql = "select * from wlyy_patient_disease";
        List<Map<String, Object>> patientDiseases = jdbcTemplate.queryForList(sql);
        Map<String, JSONArray> diseases = new HashMap<>();

        if (patientDiseases != null) {
            for (Map<String, Object> map : patientDiseases) {
                if(!diseases.containsKey(map.get("patient").toString())){
                    diseases.put(map.get("patient").toString(), new JSONArray());
                }
                if(map.get("del").toString().equals("1")) {
                    JSONObject disease = new JSONObject();
                    disease.put("disease", map.get("disease"));
                    disease.put("diseaseName", map.get("disease_name"));
                    disease.put("del", map.get("del"));
                    disease.put("signType", map.get("sign_type"));

                    if (diseases.containsKey(map.get("patient").toString())) {
                        diseases.get(map.get("patient").toString()).put(disease);
                    } else {
                        JSONArray jsonArray = new JSONArray();
                        jsonArray.put(disease);
                        diseases.put(map.get("patient").toString(), jsonArray);
                    }
                }
            }
        }

        for (String key : diseases.keySet()) {
            redisTemplate.opsForValue().set("disease:" + key, diseases.get(key).toString());
        }
    }

    /**
     * 更新疾病到疾病表
     */
    public void updateToDisease() {
        String gxySql = "insert into wlyy_patient_disease(patient,disease,disease_name,del,sign_type,czrq) select a.code,'1','高血压','1','?1',now() from wlyy_patient a,wlyy_sign_family b where a.code = b.patient and b.type = ?2 and b.status > 0 and a.disease = 1";
        String tnbSql = "insert into wlyy_patient_disease(patient,disease,disease_name,del,sign_type,czrq) select a.code,'2','糖尿病','1','?1',now() from wlyy_patient a,wlyy_sign_family b where a.code = b.patient and b.type = ?2 and b.status > 0 and a.disease = 2";

        jdbcTemplate.update(gxySql.replace("?1", "1").replace("?2", "1"));
        jdbcTemplate.update(gxySql.replace("?1", "2").replace("?2", "2"));
        jdbcTemplate.update(tnbSql.replace("?1", "1").replace("?2", "1"));
        jdbcTemplate.update(tnbSql.replace("?1", "2").replace("?2", "2"));

        String tgSql = "select code from wlyy_patient where disease = 3 ";
        List<Map<String, Object>> codes = jdbcTemplate.queryForList(tgSql);

        for (Map<String, Object> map : codes) {
            String sql = "insert into wlyy_patient_disease(patient,disease,disease_name,del,sign_type,czrq) values('" +
                    map.get("code").toString() + "','?1','?2','1','?3',now())";
            if (signFamilyDao.countPatientSsSign(map.get("code").toString()) > 0) {
                jdbcTemplate.update(sql.replace("?1", "1").replace("?2", "高血压").replace("?3", "1"));
                jdbcTemplate.update(sql.replace("?1", "2").replace("?2", "糖尿病").replace("?3", "1"));
            }
            if (signFamilyDao.countPatientJtSign(map.get("code").toString()) > 0) {
                jdbcTemplate.update(sql.replace("?1", "1").replace("?2", "高血压").replace("?3", "2"));
                jdbcTemplate.update(sql.replace("?1", "2").replace("?2", "糖尿病").replace("?3", "2"));
            }
        }
    }
}
