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

import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.doctor.team.sign.DoctorPatientGroupInfo;
import com.yihu.wlyy.entity.doctor.team.sign.SignPatientLabel;
import com.yihu.wlyy.entity.doctor.team.sign.SignPatientLabelInfo;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.patient.PatientDisease;
import com.yihu.wlyy.entity.patient.SignFamily;
import com.yihu.wlyy.repository.doctor.DoctorDao;
import com.yihu.wlyy.repository.doctor.DoctorPatientGroupInfoDao;
import com.yihu.wlyy.repository.doctor.SignPatientLabelInfoDao;
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 com.yihu.wlyy.util.DateUtil;
import com.yihu.wlyy.util.IdCardUtil;
import org.apache.commons.beanutils.converters.CalendarConverter;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.type.descriptor.sql.JdbcTypeFamilyInformation;
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 org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 患者标签信息服务
 * <p>
 * Created by lyr on 2016/10/9.
 */
@Service
@Transactional
public class SignPatientLabelInfoService extends BaseService {

    @Autowired
    SignPatientLabelService labelService;
    @Autowired
    DoctorDao doctorDao;
    @Autowired
    PatientDao patientDao;
    @Autowired
    SignPatientLabelInfoDao labelInfoDao;
    @Autowired
    PatientDiseaseDao diseaseDao;
    @Autowired
    DoctorPatientGroupInfoDao groupInfoDao;
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    SignFamilyDao signFamilyDao;
    @Autowired
    StringRedisTemplate redisTemplate;

    /**
     * 查询单个居民信息
     *
     * @param patient
     * @return
     * @throws Exception
     */
    public JSONObject getPatient(String patient) throws Exception {
        JSONObject json = new JSONObject();
        Patient p = patientDao.findByCode(patient);

        if(p == null){
            throw new Exception("patient info can not find");
        }

        List<SignFamily> signs = signFamilyDao.findAllSignByPatient(patient);

        // 设置患者标识
        json.put("code", p.getCode());
        // 设置患者姓名
        json.put("name", p.getName());
        // 设置患者手机号
        json.put("mobile", p.getMobile());
        // 设置患者联系电话
        json.put("phone", p.getPhone());
        // 设置患者头像
        json.put("photo", p.getPhoto());
        // 设置患者年龄
        json.put("age", DateUtil.getAgeByBirthday(p.getBirthday()));
        // 设置患者性别
        json.put("sex", p.getSex());
        // 身份证号
        json.put("idcard", p.getIdcard());
        // 社保号
        json.put("ssc", p.getSsc());

        if(signs != null && signs.size() > 0){
            SignFamily ssSign = null;
            SignFamily familySign = null;
            for(SignFamily sign : signs){
                if(sign.getType() == 1){
                    ssSign = sign;
                } else if(sign.getType() == 2){
                    familySign = sign;
                }
            }

            if(ssSign != null) {
                // 设置患者紧急联系人
                json.put("emerMobile", StringUtils.isEmpty(ssSign.getEmerMobile()) ? "" : String.valueOf(ssSign.getEmerMobile()));
                // 设置签约日期
                json.put("qyrq", ssSign.getApplyDate() != null ? DateUtil.dateToStr((Date) ssSign.getApplyDate(), DateUtil.YYYY_MM_DD) : "");
                // 设置签约类型
                json.put("signType", 1);
                // 设置签约状态
                json.put("ssStatus", ssSign.getStatus());
            }
            if(familySign != null){
                // 设置患者紧急联系人
                json.put("emerMobile", StringUtils.isEmpty(familySign.getEmerMobile()) ? "" : String.valueOf(familySign.getEmerMobile()));
                // 设置签约日期
                json.put("qyrq", familySign.getApplyDate() != null ? DateUtil.dateToStr((Date) familySign.getApplyDate(), DateUtil.YYYY_MM_DD) : "");
                // 设置签约日期
                json.put("patientApplyDate", familySign.getPatientApplyDate() != null ? DateUtil.dateToStr((Date) familySign.getPatientApplyDate(), DateUtil.YYYY_MM_DD) : "");
                // 设置签约类型
                json.put("signType", json.has("signType") ? 3 : 2);
                // 缴费情况
                json.put("expensesStatus", StringUtils.isNotEmpty(familySign.getExpensesStatus()) ? String.valueOf(familySign.getExpensesStatus()) : "0");
                // 缴费时间
                json.put("expensesTime", familySign.getExpensesTime() != null ? DateUtil.dateToStr((Date) familySign.getExpensesTime(), DateUtil.YYYY_MM_DD_HH_MM) : "");
                // 缴费类型
                json.put("expensesType", StringUtils.isNotEmpty(familySign.getExpensesType()) ? String.valueOf(familySign.getExpensesType()) : "");
                // 设置签约状态
                json.put("familyStatus", familySign.getStatus());

                if("1".equals(familySign.getExpensesStatus())){
                    json.put("qyrq", familySign.getExpensesTime() != null ? DateUtil.dateToStr((Date) familySign.getExpensesTime(), DateUtil.YYYY_MM_DD) : "");
                }
            }

            if (json.has("expensesStatus") && (StringUtils.isEmpty(String.valueOf(json.get("expensesStatus"))) || String.valueOf(json.get("expensesStatus")).equals("0"))) {
                String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                if (StringUtils.isEmpty(epTime)) {
                    json.put("expensesRemindStatus", 0);
                } else {
                    json.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                }
            }
        }

        return json;
    }

    /**
     * 根据标签查询患者信息
     *
     * @param labelCode 标签code
     * @param labelType 标签类型
     * @param page      第几页
     * @param pagesize  页大小
     * @return
     */
    public JSONArray getPatientByLabel(String doctor, String labelCode, String labelType, Long teamCode, int page, int pagesize) throws Exception {
        Doctor doc = doctorDao.findByCode(doctor);

        if (doc == null) {
            throw new Exception("doctor info can not find");
        }

        Map<String, JSONObject> result = new HashMap<>();
        List<Map<String, Object>> signList = new ArrayList<>();
        int start = page * pagesize;
        String sql = "";
        Object[] args = null;

        if (labelType.equals("5")) {
            Calendar today = Calendar.getInstance();
            Calendar startDate = Calendar.getInstance();
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            sql = "select * " +
                    " from " +
                    "     wlyy_sign_family " +
                    " where " + (doc.getLevel() == 2 ? " doctor" : "doctor_health") + " = ? and status > 0 and admin_team_code = ? ";

            if (labelCode.equals("1")) {
                int week = today.get(Calendar.DAY_OF_WEEK) - 2;

                if (week == -1) {
                    week = 6;
                }
                startDate.add(Calendar.DATE, -week);
                sql += " and apply_date between '" + (df.format(startDate.getTime()) + " 00:00:00")
                        + "' and '" + (df.format(today.getTime()) + " 23:59:59'");
            } else if (labelCode.equals("2")) {
                startDate.set(Calendar.DATE, 1);
                sql += " and apply_date between '" + (df.format(startDate.getTime()) + " 00:00:00")
                        + "' and '" + (df.format(today.getTime()) + " 23:59:59'");
            } else if (labelCode.equals("3")) {
                startDate.add(Calendar.DATE, 30);
                sql += " and end between '" + (df.format(today.getTime()) + " 00:00:00")
                        + "' and '" + (df.format(startDate.getTime()) + " 23:59:59'");
            } else {
                throw new Exception("label is not exist");
            }

            args = new Object[]{doctor, teamCode};
        } else {
            if (labelCode.equals("0")) {
                sql = "SELECT " +
                        "    t1.* " +
                        " FROM " +
                        "    wlyy_sign_family t1 " +
                        " left join " +
                        "    (select patient,label,label_type from wlyy_sign_patient_label_info where patient in " +
                        "    (select patient from wlyy_sign_family where " + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + "='" + doctor + "' and status > 0) " +
                        "     and label_type = ? and status = 1) t2 " +
                        " on t1.patient = t2.patient " +
                        " WHERE " +
                        "    t2.patient is null " +
                        "    AND t1." + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                        "    AND t1.status > 0 " +
                        "    AND t1.admin_team_code = ? limit " + start + "," + pagesize;

                args = new Object[]{labelType, doctor, teamCode};
            } else {
                sql = "SELECT " +
                        "    t1.* " +
                        " FROM " +
                        "    wlyy_sign_family t1, " +
                        "    wlyy_sign_patient_label_info t2 " +
                        " WHERE " +
                        "     t2.patient in (select patient from wlyy_sign_family where " + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = '" + doctor + "' and status > 0 ) " +
                        "    AND t2.label = ? " +
                        "    AND t2.label_type = ? " +
                        "    AND t2.status = 1 " +
                        "    AND t1.patient = t2.patient " +
                        "    AND t1." + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                        "    AND t1.status > 0 " +
                        "    AND t1.admin_team_code = ? limit " + start + "," + pagesize;

                args = new Object[]{labelCode, labelType, doctor, teamCode};
            }
        }

        signList = jdbcTemplate.queryForList(sql, args);

        if (signList != null && signList.size() > 0) {
            for (Map<String, Object> sign : signList) {
                Patient p = patientDao.findByCode(sign.get("patient") == null ? "" : sign.get("patient").toString());

                if (p == null) {
                    continue;
                }

                if (result.containsKey(p.getCode())) {
                    JSONObject jsonP = result.get(p.getCode());

                    if (!String.valueOf(jsonP.get("signType")).equals(String.valueOf(sign.get("type")))) {
                        jsonP.put("signType", 3);
                    }
                    if (String.valueOf(sign.get("type")).equals("2")) {
                        jsonP.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                        // 缴费情况
                        jsonP.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")): "0");
                        // 缴费时间
                        jsonP.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                        // 缴费类型
                        jsonP.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")): "");
                        if (StringUtils.isEmpty(String.valueOf(jsonP.get("expensesStatus"))) || String.valueOf(jsonP.get("expensesStatus")).equals("0")) {
                            String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                            if (StringUtils.isEmpty(epTime)) {
                                jsonP.put("expensesRemindStatus", 0);
                            } else {
                                jsonP.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                            }
                        }
                    }

                    continue;
                }

                //List<SignPatientLabelInfo> labels = labelInfoDao.findByPatientAndStatus(sign.get("patient").toString(), 1);
                JSONObject json = new JSONObject();

                // 设置患者标识
                json.put("code", p.getCode());
                // 设置患者姓名
                json.put("name", p.getName());
                // 设置患者手机号
                json.put("mobile", p.getMobile());
                // 设置患者联系电话
                json.put("phone", p.getPhone());
                // 设置患者紧急联系人
                json.put("emerMobile", sign.get("emer_mobile") == null ? "" : String.valueOf(sign.get("emer_mobile")));
                // 设置患者头像
                json.put("photo", p.getPhoto());
                // 设置患者年龄
                json.put("age", DateUtil.getAgeByBirthday(p.getBirthday()));
                // 设置患者性别
                json.put("sex", p.getSex());
                // 设置签约日期
                json.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                // 设置签约类型
                json.put("signType", sign.get("type") == null ? "" : sign.get("type"));
                // 身份证号
                json.put("idcard", p.getIdcard());
                // 社保号
                json.put("ssc", p.getSsc());
                if(String.valueOf(sign.get("type")).equals("2")) {
                    // 缴费情况
                    json.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")) : "0");
                    // 缴费时间
                    json.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                    // 缴费类型
                    json.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")) : "");

//                if("2".equals(String.valueOf(sign.get("type"))) && "1".equals(String.valueOf(sign.get("expenses_status")))){
//                    json.put("qyrq", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD) : "");
//                }
                    if (StringUtils.isEmpty(String.valueOf(json.get("expensesStatus"))) || String.valueOf(json.get("expensesStatus")).equals("0")) {
                        String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                        if (StringUtils.isEmpty(epTime)) {
                            json.put("expensesRemindStatus", 0);
                        } else {
                            json.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                        }
                    }
                }
                // 患者标签
                //json.put("labels", labels == null ? "" : labels);

                result.put(p.getCode(), json);
            }
        }

        return result.size() > 0 ? new JSONArray(result.values()) : new JSONArray();
    }

    /**
     * 获取团队下的患者
     *
     * @param doctor
     * @param teamCode
     * @param page
     * @param pagesize
     * @return
     * @throws Exception
     */
    public JSONArray getPatientByTeamCode(String doctor, long teamCode, String exLabelCode, String exLabelType, int page, int pagesize) throws Exception {
        Doctor doc = doctorDao.findByCode(doctor);

        if (doc == null) {
            throw new Exception("doctor info can not find");
        }

        Map<String, JSONObject> result = new HashMap<>();
        List<Map<String, Object>> signList = new ArrayList<>();
        int start = page * pagesize;
        String sql = "";
        Object[] args = null;

        sql = " select * from wlyy_sign_family where " +
                (doc.getLevel() == 2 ? " doctor" : "doctor_health") +
                " = ? and status > 0 and admin_team_code = ? " +
                " limit " + start + "," + pagesize;

        args = new Object[]{doctor, teamCode};

        signList = jdbcTemplate.queryForList(sql, args);

        if (signList != null && signList.size() > 0) {
            for (Map<String, Object> sign : signList) {
                Patient p = patientDao.findByCode(sign.get("patient") == null ? "" : sign.get("patient").toString());

                if (p == null) {
                    continue;
                }

                if (result.containsKey(p.getCode())) {
                    JSONObject jsonP = result.get(p.getCode());

                    if (!String.valueOf(jsonP.get("signType")).equals(String.valueOf(sign.get("type")))) {
                        jsonP.put("signType", 3);
                    }
                    if (String.valueOf(sign.get("type")).equals("2")) {
                        jsonP.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                        // 缴费情况
                        jsonP.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")): "0");
                        // 缴费时间
                        jsonP.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                        // 缴费类型
                        jsonP.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")): "");
                        if (StringUtils.isEmpty(String.valueOf(jsonP.get("expensesStatus"))) || String.valueOf(jsonP.get("expensesStatus")).equals("0")) {
                            String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                            if (StringUtils.isEmpty(epTime)) {
                                jsonP.put("expensesRemindStatus", 0);
                            } else {
                                jsonP.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                            }
                        }
                    }
                    continue;
                }

                if (StringUtils.isNotEmpty(exLabelCode)) {
                    SignPatientLabelInfo labelInfoEx = labelInfoDao.findByPatientAndLabelAndLabelTypeAndStatus(p.getCode(), exLabelCode, exLabelType, 1);

                    if (labelInfoEx != null) {
                        continue;
                    }
                } else if (StringUtils.isNotEmpty(exLabelType)) {
                    List<SignPatientLabelInfo> labelExs = labelInfoDao.findByPatientAndLabelTypeAndStatus(p.getCode(), exLabelType, 1);

                    if (labelExs != null && labelExs.size() > 0) {
                        continue;
                    }
                }

                List<SignPatientLabelInfo> labels = labelInfoDao.findByPatientAndStatus(sign.get("patient").toString(), 1);
                JSONObject json = new JSONObject();

                // 设置患者标识
                json.put("code", p.getCode());
                // 设置患者姓名
                json.put("name", p.getName());
                // 设置患者手机号
                json.put("mobile", p.getMobile());
                // 设置患者联系电话
                json.put("phone", p.getPhone());
                // 设置患者紧急联系人
                json.put("emerMobile", sign.get("emer_mobile") == null ? "" : String.valueOf(sign.get("emer_mobile")));
                // 设置患者头像
                json.put("photo", p.getPhoto());
                // 设置患者年龄
                json.put("age", DateUtil.getAgeByBirthday(p.getBirthday()));
                // 设置患者性别
                json.put("sex", p.getSex());
                // 设置签约日期
                json.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                // 设置签约类型
                json.put("signType", sign.get("type") == null ? "" : sign.get("type"));
                // 身份证号
                json.put("idcard", p.getIdcard());
                // 社保号
                json.put("ssc", p.getSsc());
                if(String.valueOf(sign.get("type")).equals("2")) {
                    // 缴费情况
                    json.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")) : "0");
                    // 缴费时间
                    json.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                    // 缴费类型
                    json.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")) : "");
//                if("2".equals(String.valueOf(sign.get("type"))) && "1".equals(String.valueOf(sign.get("expenses_status")))){
//                    json.put("qyrq", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD) : "");
//                }
                    if (StringUtils.isEmpty(String.valueOf(json.get("expensesStatus"))) || String.valueOf(json.get("expensesStatus")).equals("0")) {
                        String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                        if (StringUtils.isEmpty(epTime)) {
                            json.put("expensesRemindStatus", 0);
                        } else {
                            json.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                        }
                    }
                }
                // 患者标签
                json.put("labels", labels == null ? "" : labels);

                result.put(p.getCode(), json);
            }
        }

        return result.size() > 0 ? new JSONArray(result.values()) : new JSONArray();
    }

    /**
     * 查询某个标签类型的所有标签居民数统计
     *
     * @param labelType 标签类型
     * @param teamCode  标签类型为4时,不能为空
     * @return
     */
    public JSONArray getPatientAmountByLabelType(String doctor, String labelType, Long teamCode) throws Exception {
        Doctor doc = doctorDao.findByCode(doctor);

        if (doc == null) {
            throw new Exception("doctor info can not find");
        }

        List<SignPatientLabel> labels = labelService.getLabelsByTypeAndTeam(labelType, teamCode);
        JSONArray result = new JSONArray();

        SignPatientLabel labelNo = new SignPatientLabel();

        if (!labelType.equals("5")) {
            labelNo.setLabelCode("0");
            labelNo.setLabelName(labelType.equals("1") ? "未分组" : "未标注");
            labelNo.setStatus(1);
            labelNo.setIsSystem(1);
            labelNo.setLabelType(labelType);
            labelNo.setSort(999999999);

            labels.add(labelNo);
        }

        if (labels != null) {
            for (SignPatientLabel label : labels) {
                JSONObject json = new JSONObject();

                json.put("labelCode", label.getLabelCode());
                json.put("labelName", label.getLabelName());
                json.put("isSystem", label.getIsSystem());

                int amount = 0;
                String sql = "";
                Object[] args = null;

                if (labelType.equals("5")) {
                    Calendar today = Calendar.getInstance();
                    Calendar startDate = Calendar.getInstance();
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                    sql = "select count(DISTINCT patient) count" +
                            " from " +
                            "     wlyy_sign_family " +
                            " where " + (doc.getLevel() == 2 ? " doctor" : "doctor_health") + " = ? and status > 0 " +
                            (teamCode > 0 ? " and admin_team_code = ? " : "");

                    if (label.getLabelCode().equals("1")) {
                        int week = today.get(Calendar.DAY_OF_WEEK) - 2;
                        if (week == -1) {
                            week = 6;
                        }
                        startDate.add(Calendar.DATE, -week);
                        sql += " and apply_date between '" + (df.format(startDate.getTime()) + " 00:00:00")
                                + "' and '" + (df.format(today.getTime()) + " 23:59:59'");
                    } else if (label.getLabelCode().equals("2")) {
                        startDate.set(Calendar.DATE, 1);
                        sql += " and apply_date between '" + (df.format(startDate.getTime()) + " 00:00:00")
                                + "' and '" + (df.format(today.getTime()) + " 23:59:59'");
                    } else if (label.getLabelCode().equals("3")) {
                        startDate.add(Calendar.DATE, 30);
                        sql += " and end between '" + (df.format(today.getTime()) + " 00:00:00")
                                + "' and '" + (df.format(startDate.getTime()) + " 23:59:59'");
                    } else {
                        throw new Exception("label is not exist");
                    }
                    if (teamCode > 0) {
                        args = new Object[]{doctor, teamCode};
                    } else {
                        args = new Object[]{doctor};
                    }
                } else {
                    if (label.getLabelCode().equals("0")) {
                        sql = " SELECT " +
                                "     count(DISTINCT t1.patient) count " +
                                " FROM" +
                                "     wlyy_sign_family t1 " +
                                " left join " +
                                "    (SELECT patient,label,label_type from wlyy_sign_patient_label_info where patient in " +
                                "    (select patient from wlyy_sign_family where " + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = '" + doctor + "' and status > 0) " +
                                "    and label_type = ? and status = 1)  t2 " +
                                " on t1.patient = t2.patient " +
                                " WHERE" +
                                "     t2.patient is null " +
                                "     AND t1." + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                                "     AND t1.status > 0 " +
                                (teamCode > 0 ? "    AND t1.admin_team_code = ? " : "");

                        if (teamCode > 0) {
                            args = new Object[]{labelType, doctor, teamCode};
                        } else {
                            args = new Object[]{labelType, doctor};
                        }
                    } else {
                        sql = " SELECT " +
                                "     count(DISTINCT t1.patient) count " +
                                " FROM" +
                                "     wlyy_sign_family t1, " +
                                "     wlyy_sign_patient_label_info t2 " +
                                " WHERE" +
                                "     t1.patient = t2.patient " +
                                "     AND t2.patient in (select patient from wlyy_sign_family where " + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = '" + doctor + "' and status > 0) " +
                                "     AND t2.label = ? " +
                                "     AND t2.label_type = ? " +
                                "     AND t2.status = 1 " +
                                "     AND t1." + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                                "     AND t1.status > 0 " +
                                (teamCode > 0 ? "    AND t1.admin_team_code = ? " : "");

                        if (teamCode > 0) {
                            args = new Object[]{label.getLabelCode(), labelType, doctor, teamCode};
                        } else {
                            args = new Object[]{label.getLabelCode(), labelType, doctor};
                        }
                    }
                }

                List<Map<String, Object>> count = jdbcTemplate.queryForList(sql, args);

                if (count != null && count.size() > 0 && count.get(0).containsKey("count")) {
                    amount = Integer.valueOf(String.valueOf(count.get(0).get("count")));
                }

                json.put("amount", amount);

                if (label.getLabelCode().equals("0") && labelType.equals("1") && amount < 1) {
                    continue;
                }
                result.put(json);
            }
        }

        return result;
    }

    /**
     * 设置患者标签
     *
     * @param patient     患者名称
     * @param idcard      身份证号
     * @param patientName 患者姓名
     * @param health      健康情况标签
     * @param disease     疾病类型标签
     * @param custom      自定义标签
     * @return
     */
    public int setPatientLabels(String patient, String idcard, String patientName, String health, String disease, String custom) {
        Patient p = patientDao.findByCode(patient);

        if (p == null && (StringUtils.isEmpty(idcard) || StringUtils.isEmpty(patientName))) {
            return 0;
        } else {
            idcard = p.getIdcard();
            patientName = p.getName();

            List<PatientDisease> diseaseSs = diseaseDao.findByPatientSsDisease(p.getCode());

            if (diseaseSs != null && diseaseSs.size() > 0) {
                String[] diseaseArr = disease.split(",");

                if (diseaseArr == null || diseaseArr.length < 1) {
                    return -3;
                }

                for (PatientDisease dis : diseaseSs) {
                    if (!Arrays.asList(diseaseArr).contains(dis.getDisease())) {
                        return -3;
                    }
                }
            }
        }

        String[] diseaseArr = disease.split(",");
        String[] customArr = custom.split(",");

        // 健康情况标签
        int healthAmount = labelInfoDao.deleteByPatientAndLabelTypeAndStatus(patient, "2", 1);

        if (StringUtils.isNotEmpty(health)) {
            SignPatientLabelInfo healthLabel = new SignPatientLabelInfo();
            SignPatientLabel label = labelService.getLabelByCodeAndType(health, "2");

            if (label == null) {
                return -1;
            }

            healthLabel.setPatient(patient);
            healthLabel.setPname(patientName);
            healthLabel.setLabelType("2");
            healthLabel.setLabel(health);
            healthLabel.setLabelName(label.getLabelName());
            healthLabel.setStatus(1);
            healthLabel.setCzrq(new Date());

            labelInfoDao.save(healthLabel);
        } else {
            return -2;
        }

        // 疾病类型标签
        int disAmount = labelInfoDao.deleteByPatientAndLabelTypeAndStatus(patient, "3", 1);

        if (diseaseArr != null && diseaseArr.length > 0) {
            for (String diseaseLabel : diseaseArr) {
                if (StringUtils.isEmpty(diseaseLabel)) {
                    continue;
                }
                SignPatientLabelInfo disLabel = new SignPatientLabelInfo();
                SignPatientLabel label = labelService.getLabelByCodeAndType(diseaseLabel, "3");

                if (label == null) {
                    return -1;
                }

                disLabel.setPatient(patient);
                disLabel.setPname(patientName);
                disLabel.setLabelType("3");
                disLabel.setLabel(diseaseLabel);
                disLabel.setLabelName(label.getLabelName());
                disLabel.setStatus(1);
                disLabel.setCzrq(new Date());

                labelInfoDao.save(disLabel);
            }
        }

        // 自定义标签
        int cusAmount = labelInfoDao.deleteByPatientAndLabelTypeAndStatus(patient, "4", 1);

        if (customArr != null && customArr.length > 0) {
            for (String customLabel : customArr) {
                if (StringUtils.isEmpty(customLabel)) {
                    continue;
                }
                SignPatientLabelInfo cusLabel = new SignPatientLabelInfo();
                SignPatientLabel label = labelService.getLabelByCodeAndType(customLabel, "4");

                if (label == null) {
                    return -1;
                }

                cusLabel.setPatient(patient);
                cusLabel.setPname(patientName);
                cusLabel.setLabelType("4");
                cusLabel.setLabel(customLabel);
                cusLabel.setLabelName(label.getLabelName());
                cusLabel.setStatus(1);
                cusLabel.setCzrq(new Date());

                labelInfoDao.save(cusLabel);
            }
        }

        // 卫计委三大分组
        int wjwAmount = labelInfoDao.deleteByPatientAndLabelTypeAndStatus(patient, "1", 1);

        if (diseaseArr != null && diseaseArr.length > 0 && (Arrays.asList(diseaseArr).contains("1")
                || Arrays.asList(diseaseArr).contains("2"))) {
            SignPatientLabelInfo disLabel = new SignPatientLabelInfo();

            disLabel.setPatient(patient);
            disLabel.setPname(patientName);
            disLabel.setLabelType("1");
            disLabel.setLabel("2");
            disLabel.setLabelName("慢病人群");
            disLabel.setStatus(1);
            disLabel.setCzrq(new Date());

            labelInfoDao.save(disLabel);
        } else {
            int age = IdCardUtil.getAgeForIdcard(idcard);
            SignPatientLabelInfo disLabel = new SignPatientLabelInfo();

            disLabel.setPatient(patient);
            disLabel.setPname(patientName);
            disLabel.setLabelType("1");
            disLabel.setStatus(1);
            disLabel.setCzrq(new Date());

            if (age >= 65) {
                disLabel.setLabel("3");
                disLabel.setLabelName("65岁以上人群");
            } else {
                disLabel.setLabel("1");
                disLabel.setLabelName("普通人群");
            }

            labelInfoDao.save(disLabel);
        }

        return 1;
    }

    /**
     * 查询某个患者的某个类型的标签
     *
     * @param patient   患者code
     * @param labelType 标签类型
     * @return
     */
    public List<SignPatientLabelInfo> getPatientLabelByLabelType(String patient, String labelType) {
        List<SignPatientLabelInfo> labels = new ArrayList<>();

        if (StringUtils.isEmpty(labelType)) {
            labels = labelInfoDao.findByPatientAndStatus(patient, 1);
        } else {
            labels = labelInfoDao.findByPatientAndLabelTypeAndStatus(patient, labelType, 1);
        }

        return labels;
    }

    /**
     * 根据患者姓名或标签名称查询
     *
     * @param doctor
     * @param filter
     * @return
     * @throws Exception
     */
    public JSONArray searchPatientByNameOrLabel(String doctor, String filter,
                                                String labelCode, String labelType, long teamCode,
                                                String exLabelCode,
                                                String exLabelType,
                                                int page, int pagesize) throws Exception {
        Doctor doc = doctorDao.findByCode(doctor);

        if (doc == null) {
            throw new Exception("doctor info can not find");
        }

        Map<String, JSONObject> result = new HashMap<>();
        List<Map<String, Object>> signList = new ArrayList<>();
        page = page * pagesize;
        Object[] args = null;
        String sql = "SELECT " +
                "    t1.* " +
                " FROM " +
                "    wlyy_sign_family t1 " +
                (StringUtils.isNotEmpty(labelCode) || StringUtils.isNotEmpty(labelType) ?
                        " join " : " left join ") +
                "    (select patient,label,label_name,label_type from wlyy_sign_patient_label_info  where patient in" +
                "    (select patient from wlyy_sign_family where " + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = '" + doctor + "' and status > 0) " +
                "     and status = 1 " +
                (StringUtils.isNotEmpty(labelCode) ? " AND label = ? " : "") +
                (StringUtils.isNotEmpty(labelType) ? " AND label_type = ? " : "") + ") t2" +
                " ON t1.patient = t2.patient " +
                " WHERE " +
                "    t1." + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                "    AND t1.status > 0 " +
                (teamCode > 0 ? (" AND admin_team_code = " + teamCode) : "") +
                "    AND (t1.name like ? OR t2.label_name like ?) " +
                " limit " + page + "," + pagesize;

        if (StringUtils.isNotEmpty(labelCode)) {
            args = new Object[]{labelCode, labelType, doctor, "%" + filter + "%", "%" + filter + "%"};
        } else if (StringUtils.isEmpty(labelCode) && StringUtils.isNotEmpty(labelType)) {
            args = new Object[]{labelType, doctor, "%" + filter + "%", "%" + filter + "%"};
        } else {
            args = new Object[]{doctor, "%" + filter + "%", "%" + filter + "%"};
        }

        signList = jdbcTemplate.queryForList(sql, args);

        if (signList != null && signList.size() > 0) {
            for (Map<String, Object> sign : signList) {
                Patient p = patientDao.findByCode(sign.get("patient") == null ? "" : sign.get("patient").toString());

                if (p == null) {
                    continue;
                }

                if (result.containsKey(p.getCode())) {
                    JSONObject jsonP = result.get(p.getCode());

                    if (!String.valueOf(jsonP.get("signType")).equals(String.valueOf(sign.get("type")))) {
                        jsonP.put("signType", 3);
                    }
                    if (String.valueOf(sign.get("type")).equals("2")) {
                        jsonP.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                        // 缴费情况
                        jsonP.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")): "0");
                        // 缴费时间
                        jsonP.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                        // 缴费类型
                        jsonP.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")): "");
                        if (StringUtils.isEmpty(String.valueOf(jsonP.get("expensesStatus"))) || String.valueOf(jsonP.get("expensesStatus")).equals("0")) {
                            String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                            if (StringUtils.isEmpty(epTime)) {
                                jsonP.put("expensesRemindStatus", 0);
                            } else {
                                jsonP.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                            }
                        }
                    }

                    continue;
                }

                if (StringUtils.isNotEmpty(exLabelCode)) {
                    SignPatientLabelInfo labelInfoEx = labelInfoDao.findByPatientAndLabelAndLabelTypeAndStatus(p.getCode(), exLabelCode, exLabelType, 1);

                    if (labelInfoEx != null) {
                        continue;
                    }
                } else if (StringUtils.isNotEmpty(exLabelType)) {
                    List<SignPatientLabelInfo> labelExs = labelInfoDao.findByPatientAndLabelTypeAndStatus(p.getCode(), exLabelType, 1);

                    if (labelExs != null && labelExs.size() > 0) {
                        continue;
                    }
                }


                List<SignPatientLabelInfo> labels = labelInfoDao.findByPatientAndStatus(sign.get("patient").toString(), 1);

                if (StringUtils.isEmpty(exLabelCode) || StringUtils.isEmpty(exLabelType)) {

                }

                JSONObject json = new JSONObject();

                // 设置患者标识
                json.put("code", p.getCode());
                // 设置患者姓名
                json.put("name", p.getName());
                // 设置患者手机号
                json.put("mobile", p.getMobile());
                // 设置患者联系电话
                json.put("phone", p.getPhone());
                // 设置患者紧急联系人
                json.put("emerMobile", sign.get("emer_mobile") == null ? "" : String.valueOf(sign.get("emer_mobile")));
                // 设置患者头像
                json.put("photo", p.getPhoto());
                // 设置患者年龄
                json.put("age", DateUtil.getAgeByBirthday(p.getBirthday()));
                // 设置患者性别
                json.put("sex", p.getSex());
                // 设置签约日期
                json.put("qyrq", sign.get("apply_date") != null ? DateUtil.dateToStr((Date) sign.get("apply_date"), DateUtil.YYYY_MM_DD) : "");
                // 设置签约类型
                json.put("signType", sign.get("type") == null ? "" : sign.get("type"));
                // 身份证号
                json.put("idcard", p.getIdcard());
                // 社保号
                json.put("ssc", p.getSsc());
                if (String.valueOf(sign.get("type")).equals("2")) {
                    // 缴费情况
                    json.put("expensesStatus", sign.get("expenses_status") != null ? String.valueOf(sign.get("expenses_status")) : "0");
                    // 缴费时间
                    json.put("expensesTime", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD_HH_MM) : "");
                    // 缴费类型
                    json.put("expensesType", sign.get("expenses_type") != null ? String.valueOf(sign.get("expenses_type")) : "");
//                if("2".equals(String.valueOf(sign.get("type"))) && "1".equals(String.valueOf(sign.get("expenses_status")))){
//                    json.put("qyrq", sign.get("expenses_time") != null ? DateUtil.dateToStr((Date) sign.get("expenses_time"), DateUtil.YYYY_MM_DD) : "");
//                }
                    if (StringUtils.isEmpty(String.valueOf(json.get("expensesStatus"))) || String.valueOf(json.get("expensesStatus")).equals("0")) {
                        String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());

                        if (StringUtils.isEmpty(epTime)) {
                            json.put("expensesRemindStatus", 0);
                        } else {
                            json.put("expensesRemindStatus", new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime) ? 1 : 0);
                        }
                    }
                }
                // 患者标签
                json.put("labels", labels == null ? "" : labels);

                result.put(p.getCode(), json);
            }
        }

        return result.size() > 0 ? new JSONArray(result.values()) : new JSONArray();
    }

    /**
     * 添加居民到某个标签
     *
     * @param patient   患者
     * @param labelCode 标签code
     * @param labelType 标签类型
     * @return
     */
    public int addPatientLabel(String patient, String labelCode, String labelType) {
        Patient p = patientDao.findByCode(patient);

        if (p == null) {
            return -1;
        }

        SignPatientLabelInfo labelInfo = labelInfoDao.findByPatientAndLabelAndLabelTypeAndStatus(patient, labelCode, labelType, 1);

        if (labelInfo != null) {
            return -2;
        }

        SignPatientLabel label = labelService.getLabelByCodeAndType(labelCode, labelType);

        if (label == null) {
            return -3;
        }

        labelInfo = new SignPatientLabelInfo();

        labelInfo.setPatient(patient);
        labelInfo.setPname(p.getName());
        labelInfo.setLabel(labelCode);
        labelInfo.setLabelType(labelType);
        labelInfo.setLabelName(label.getLabelName());
        labelInfo.setStatus(1);
        labelInfo.setCzrq(new Date());

        labelInfoDao.save(labelInfo);

        return 1;
    }

    /**
     * 添加多个患者到一个标签
     *
     * @param patients
     * @param labelCode
     * @param labelType
     * @return
     */
    public int addPatientsLabel(String patients, String labelCode, String labelType) {
        if (StringUtils.isNotEmpty(patients)) {
            String[] patientArr = patients.split(",");

            for (String p : patientArr) {
                int result = addPatientLabel(p, labelCode, labelType);

                if (result != 1) {
                    return result;
                }
            }
        }

        return 1;
    }

    /**
     * 删除居民的某个标签
     *
     * @param patient   患者
     * @param labelCode 标签code
     * @param labelType 标签类型
     * @return
     */
    public int deletePatientLabel(String patient, String labelCode, String labelType) {
        SignPatientLabelInfo labelInfo = labelInfoDao.findByPatientAndLabelAndLabelTypeAndStatus(patient, labelCode, labelType, 1);

        if (labelInfo == null) {
            return -1;
        }

        labelInfoDao.delete(labelInfo);

        return 1;
    }

    /**
     * 删除一个标签下的多个患者
     *
     * @param patients
     * @param labelCode
     * @param labelType
     * @return
     */
    public int deltePatientsLabel(String patients, String labelCode, String labelType) {
        if (StringUtils.isNotEmpty(patients)) {
            String[] patientArr = patients.split(",");

            for (String p : patientArr) {
                int result = deletePatientLabel(p, labelCode, labelType);

                if (result != 1) {
                    return result;
                }
            }
        }

        return 1;
    }


    /**
     * 新增标签并添加患者
     *
     * @param labelName
     * @param creator
     * @param teamCode
     * @param patients
     * @return
     */
    public int addLabelAndPatient(String labelName, String creator, Long teamCode, String patients) {

        if (labelService.isLabelNameExist(labelName, teamCode) != null) {
            return -4;
        }

        SignPatientLabel label = labelService.addLabel(labelName, creator, teamCode);

        if (StringUtils.isNotEmpty(patients)) {
            String[] patientArr = patients.split(",");

            for (String p : patientArr) {
                int result = addPatientLabel(p, label.getLabelCode(), "4");

                if (result != 1) {
                    return result;
                }
            }
        }

        return 1;
    }

    /**
     * 疾病转标签
     *
     * @return
     */
    public boolean diseaseToLabel() {
        List<PatientDisease> diseases = diseaseDao.findByDel("1");
        Iterator<Patient> patients = patientDao.findAll().iterator();
        Map<String, String> patientNames = new HashMap<>();

        while (patients.hasNext()) {
            Patient p = patients.next();
            patientNames.put(p.getCode(), p.getName());
        }

        for (PatientDisease disease : diseases) {
            SignPatientLabelInfo labelInfo = new SignPatientLabelInfo();

            labelInfo.setPatient(disease.getPatient());
            labelInfo.setPname(patientNames.get(disease.getPatient()));
            labelInfo.setLabel(disease.getDisease());
            labelInfo.setLabelName(disease.getDiseaseName());
            labelInfo.setLabelType("3");
            labelInfo.setStatus(1);
            labelInfo.setCzrq(new Date());

            labelInfoDao.save(labelInfo);
        }

        return true;
    }

    /**
     * 分组转标签
     *
     * @return
     */
    public boolean groupToLabel() throws Exception {
        Iterator<Patient> patients = patientDao.findAll().iterator();
        Map<String, Patient> patientNames = new HashMap<>();
        Map<String, SignPatientLabelInfo> normalLabel = new HashMap<>();
        Map<String, SignPatientLabelInfo> manbingLabel = new HashMap<>();
        Map<String, SignPatientLabelInfo> sixFiveLabel = new HashMap<>();

        while (patients.hasNext()) {
            Patient p = patients.next();
            patientNames.put(p.getCode(), p);
        }

        List<DoctorPatientGroupInfo> groupInfos = groupInfoDao.findByGroupAndStatus("1", 1);

        for (DoctorPatientGroupInfo groupInfo : groupInfos) {
            Patient p = patientNames.get(groupInfo.getPatient());

            if (p == null) {
                continue;
            }

            SignPatientLabelInfo labelInfo = new SignPatientLabelInfo();

            labelInfo.setPatient(p.getCode());
            labelInfo.setPname(p.getName());
            labelInfo.setLabel("1");
            labelInfo.setLabelName("普通人群");
            labelInfo.setLabelType("1");
            labelInfo.setStatus(1);
            labelInfo.setCzrq(new Date());

            normalLabel.put(p.getCode(), labelInfo);
        }

        List<DoctorPatientGroupInfo> groupInfos1 = groupInfoDao.findByGroupAndStatus("2", 1);

        for (DoctorPatientGroupInfo groupInfo : groupInfos1) {
            Patient p = patientNames.get(groupInfo.getPatient());

            if (p == null) {
                continue;
            }

            SignPatientLabelInfo labelInfo = new SignPatientLabelInfo();

            labelInfo.setPatient(p.getCode());
            labelInfo.setPname(p.getName());
            labelInfo.setLabel("2");
            labelInfo.setLabelName("慢病人群");
            labelInfo.setLabelType("1");
            labelInfo.setStatus(1);
            labelInfo.setCzrq(new Date());

            manbingLabel.put(p.getCode(), labelInfo);
        }

        List<DoctorPatientGroupInfo> groupInfos2 = groupInfoDao.findByGroupAndStatus("3", 1);

        for (DoctorPatientGroupInfo groupInfo : groupInfos2) {
            Patient p = patientNames.get(groupInfo.getPatient());

            if (p == null) {
                continue;
            }

            SignPatientLabelInfo labelInfo = new SignPatientLabelInfo();

            labelInfo.setPatient(p.getCode());
            labelInfo.setPname(p.getName());
            labelInfo.setLabel("3");
            labelInfo.setLabelName("65岁以上人群");
            labelInfo.setLabelType("1");
            labelInfo.setStatus(1);
            labelInfo.setCzrq(new Date());

            sixFiveLabel.put(p.getCode(), labelInfo);
        }

        if (normalLabel.size() > 0) {
            for (SignPatientLabelInfo labelInfo : normalLabel.values()) {
                labelInfoDao.save(labelInfo);
            }
        }
        if (manbingLabel.size() > 0) {
            for (SignPatientLabelInfo labelInfo : manbingLabel.values()) {
                labelInfoDao.save(labelInfo);
            }
        }
        if (sixFiveLabel.size() > 0) {
            for (SignPatientLabelInfo labelInfo : sixFiveLabel.values()) {
                labelInfoDao.save(labelInfo);
            }
        }

        return true;
    }
}
