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

import javax.transaction.Transactional;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yihu.wlyy.entity.dict.SystemDict;
import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.followup.Followup;
import com.yihu.wlyy.entity.followup.FollowupContent;
import com.yihu.wlyy.entity.message.Message;
import com.yihu.wlyy.entity.patient.Patient;
import com.yihu.wlyy.entity.patient.SignFamily;
import com.yihu.wlyy.repository.doctor.DoctorDao;
import com.yihu.wlyy.repository.followup.FollowupContentDao;
import com.yihu.wlyy.repository.message.MessageDao;
import com.yihu.wlyy.repository.patient.PatientDao;
import com.yihu.wlyy.repository.patient.SignFamilyDao;
import com.yihu.wlyy.service.app.team.DrHealthTeamService;
import com.yihu.wlyy.service.system.SystemDictService;
import com.yihu.wlyy.task.FollowupUploadTask;
import com.yihu.wlyy.task.PushMsgTask;
import com.yihu.wlyy.util.DateUtil;
import io.swagger.annotations.ApiParam;
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.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import com.yihu.wlyy.repository.followup.FollowUpDao;
import com.yihu.wlyy.service.BaseService;

import java.util.*;

/**
 * 随访服务
 *
 * @author hzp add 2016-12-07
 */
@Component
@Transactional(rollbackOn = Exception.class)
public class FollowUpService extends BaseService {

    @Autowired
    private DoctorDao doctorDao;

    @Autowired
    private PatientDao patientDao;

    @Autowired
    private FollowUpDao followupDao;

    @Autowired
    private FollowupContentDao followupContentDao;

    @Autowired
    private SystemDictService systemDictService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private SignFamilyDao signFamilyDao;

    @Autowired
    private DrHealthTeamService drHealthTeamService;

    @Autowired
    private MessageDao messageDao;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    SystemDictService dictService;

    /**
     * 转译随访信息
     */
    private Map<String, String> getFollowupDetail(Followup followup) throws Exception {
        Map<String, String> re = new HashMap<>();
        //患者信息
        String patientCode = followup.getPatientCode();
        Patient patient = patientDao.findByCode(patientCode);
        if (patient != null) {
            re.put("patientCode", patientCode);
            re.put("patientName", patient.getName());
            re.put("idcard", patient.getIdcard());
            String mobile = patient.getMobile();
            if (StringUtils.isEmpty(mobile)) {
                mobile = patient.getMobileRemarks();
            }
            re.put("mobile", mobile);
            re.put("sex", String.valueOf(patient.getSex()));
            re.put("birthday", DateUtil.dateToStrLong(patient.getBirthday()));
            re.put("photo", patient.getPhoto());
        } else {
            throw new Exception("not exit patient:" + patientCode);
        }

        re.put("id", String.valueOf(followup.getId()));
        re.put("followupNo", followup.getFollowupNo());
        re.put("followupDate", DateUtil.dateToStrLong(followup.getFollowupDate()));
        re.put("followupNextDate", DateUtil.dateToStrLong(followup.getFollowupNextDate()));

        //随访方式转译
        re.put("followupType", followup.getFollowupType());
        String followupTypeName = systemDictService.getDictValue("FOLLOWUP_WAY_DICT", followup.getFollowupType());
        re.put("followupTypeName", followupTypeName);

        //随访类别转译
        re.put("followupClass", followup.getFollowupClass());
        String followupClassName = systemDictService.getDictValue("FOLLOWUP_CLASS_DICT", followup.getFollowupClass());
        re.put("followupClassName", followupClassName);

        //随访管理状态转译
        re.put("followupManagerStatus", followup.getFollowupManagerStatus());
        String followupManagerStatusName = systemDictService.getDictValue("FOLLOWUP_MANAGER_STATUS", followup.getFollowupManagerStatus());
        re.put("followupManagerStatusName", followupManagerStatusName);

        re.put("doctorCode", followup.getDoctorCode());
        re.put("doctorName", followup.getDoctorName());
        re.put("orgCode", followup.getOrgCode());
        re.put("orgName", followup.getOrgName());
        re.put("dataFrom", followup.getDataFrom());
        re.put("status", followup.getStatus());
        re.put("followupContentPhone", followup.getFollowupContentPhone());
        re.put("createTime", DateUtil.dateToStrLong(followup.getCreateTime()));
        re.put("creater", followup.getCreater());

        return re;
    }

    /**
     * 获取医生随访列表
     */
    public List<Map<String, String>> getListByDoctor(String doctorCode, String startTime, String endTime, String page, String pageSize) throws Exception {
        List<Map<String, String>> re = new ArrayList<>();
        // 排序
        Sort sort = new Sort(Sort.Direction.ASC, "followupDate");
        // 分页信息
        int pageInt = Integer.valueOf(page) - 1;
        int pageSizeInt = Integer.valueOf(pageSize);
        Pageable pageRequest = new PageRequest(pageInt, pageSizeInt, sort);
        List<Followup> list = followupDao.findByDoctor(doctorCode, DateUtil.strToDate(startTime), DateUtil.strToDate(endTime), pageRequest);

        if (list != null && list.size() > 0) {
            for (Followup followup : list) {
                Map<String, String> map = getFollowupDetail(followup);
                re.add(map);
            }
        }

        return re;
    }

    /**
     * 查询居民随访列表
     *
     * @param patient
     * @param teamCode
     * @param page
     * @param pageSize
     * @return
     */
    public JSONArray getListByPatientAndTeam(String patient, Long teamCode, int page, int pageSize) {
        PageRequest pageRequest = new PageRequest(page, pageSize);
        Page<Object> result = followupDao.findByPatientAndTeam(patient, teamCode, pageRequest);
        JSONArray array = new JSONArray();

        if (result != null && result.getContent().size() > 0) {
            Map<String, String> dictMap = new HashMap<>();
            Map<String, String> statusMap = new HashMap<>();
            List<SystemDict> dicts = dictService.getDictByDictName("FOLLOWUP_WAY_DICT");

            if (dicts != null) {
                for(SystemDict dict : dicts){
                    dictMap.put(dict.getCode(),dict.getValue());
                }
            }

            statusMap.put("0","取消");
            statusMap.put("1","已完成");
            statusMap.put("2","未开始");
            statusMap.put("3","进行中");

            for (Object obj : result) {
                JSONObject followup = new JSONObject();
                Object[] objArr = (Object[]) obj;
                followup.put("doctorCode", objArr[0]);
                followup.put("doctorName", objArr[1]);
                followup.put("doctorPhoto", objArr[2]);
                followup.put("followupType", objArr[3]);
                followup.put("followupTypeName", dictMap.get(objArr[3].toString()) != null ? dictMap.get(objArr[3].toString()) : "");
                followup.put("followupClass", objArr[4]);
                followup.put("followupClassName", objArr[4].toString().equals("1") ? "高血压" : "糖尿病");
                followup.put("status", objArr[5]);
                followup.put("statusName", statusMap.get(objArr[5].toString()) != null ? statusMap.get(objArr[5].toString()) : "");
                followup.put("createTime", objArr[6]);
                followup.put("updateTime", objArr[7]);
                array.put(followup);
            }
        }

        return array;
    }

    /**
     * 获取医生随访列表(创建者)
     */
    public List<Map<String, String>> getListByCreater(String doctorCode, String startTime, String endTime, String page, String pageSize) throws Exception {
        List<Map<String, String>> re = new ArrayList<>();
        // 排序
        Sort sort = new Sort(Sort.Direction.ASC, "followupDate");
        // 分页信息
        int pageInt = Integer.valueOf(page) - 1;
        int pageSizeInt = Integer.valueOf(pageSize);
        Pageable pageRequest = new PageRequest(pageInt, pageSizeInt, sort);
        List<Followup> list = followupDao.findByCreater(doctorCode, DateUtil.strToDate(startTime), DateUtil.strToDate(endTime), pageRequest);

        if (list != null && list.size() > 0) {
            for (Followup followup : list) {
                Map<String, String> map = getFollowupDetail(followup);
                re.add(map);
            }
        }

        return re;
    }

    /**
     * 新增随访计划（批量）
     */
    @Transactional
    public void addFollowupPlan(String doctorCode, String patientCode, String data) throws Exception {
        //批量随访计划
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, Map.class);
        List<Map<String, String>> list = objectMapper.readValue(data, javaType);
        if (list != null && list.size() > 0) {
            //获取患者信息
            Patient patient = patientDao.findByCode(patientCode);
            if (patient == null) {
                throw new Exception("not exit patient:" + patientCode + ".\r\n");
            }
            SignFamily signFamily = signFamilyDao.findByjiatingPatient(patientCode);
            if(signFamily == null){
                throw new Exception("can not find patient's family sign info");
            }

            List<Followup> followupPlan = new ArrayList<>();
            for (Map<String, String> map : list) {
                //获取医生信息
                Doctor doctor = doctorDao.findByCode(map.get("doctor"));
                if (doctor == null) {
                    throw new Exception("not exit doctor:" + doctorCode + ".\r\n");
                }

                Followup followup = new Followup();
                followup.setFollowupType(map.get("type"));
                Date date = DateUtil.strToDate(map.get("date"));
                followup.setFollowupDate(date);
                followup.setFollowupPlanDate(date);
                followup.setDoctorCode(doctor.getCode());
                followup.setDoctorName(doctor.getName());
                followup.setOrgCode(doctor.getHospital());
                followup.setOrgName(doctor.getHospitalName());
                followup.setPatientCode(patientCode);
                followup.setPatientName(patient.getName());
                followup.setIdcard(patient.getIdcard());
                followup.setDataFrom("2");//数据来源 1基卫 2APP
                followup.setStatus("2");     //状态 0取消 1已完成 2未开始 3进行中
                followup.setCreateTime(new Date());
                followup.setCreater(doctorCode);
                followup.setAdminTeamCode(signFamily.getAdminTeamId());
                followup.setSignType(2);
                followupPlan.add(followup);
            }

            followupDao.save(followupPlan);
        }
    }


    /**
     * 编辑随访计划
     */
    public void editFollowupPlan(String doctorCode, String id, String date, String followupType) throws Exception {
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            Date followupDate = DateUtil.strToDate(date);
            followup.setFollowupDate(followupDate);
            followup.setFollowupPlanDate(followupDate);
            followup.setFollowupType(followupType);
            followup.setCreater(doctorCode);

            followupDao.save(followup);
        } else {
            throw new Exception("not exit follow:" + id + ".\r\n");
        }
    }

    /**
     * 开始随访记录
     */
    public void startFollowup(String id, String date, String followupType, String followupClass, String followupManagerStatus) throws Exception {
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            followup.setFollowupDate(DateUtil.strToDate(date));
            followup.setFollowupType(followupType);
            followup.setFollowupClass(followupClass);
            followup.setFollowupManagerStatus(followupManagerStatus);
            followup.setStatus("3");  //状态 0取消 1已完成 2未开始 3进行中

            followupDao.save(followup);
        } else {
            throw new Exception("not exit follow:" + id + ".\r\n");
        }
    }

    /**
     * 新增临时随访记录（返回ID）
     */
    public String addFollowup(String doctorCode, String patientCode, String date, String followupType, String followupClass, String followupManagerStatus) throws Exception {
        String re = "";

        //获取医生信息
        Doctor doctor = doctorDao.findByCode(doctorCode);
        if (doctor == null) {
            throw new Exception("not exit doctor:" + doctorCode + ".\r\n");
        }

        //获取患者信息
        Patient patient = patientDao.findByCode(patientCode);
        if (patient == null) {
            throw new Exception("not exit patient:" + patientCode + ".\r\n");
        }
        SignFamily signFamily = signFamilyDao.findByjiatingPatient(patientCode);
        if(signFamily == null){
            throw new Exception("can not find patient's family sign info");
        }

        Followup followup = new Followup();
        Date followDate = DateUtil.strToDate(date);
        followup.setFollowupDate(followDate);
        followup.setFollowupPlanDate(followDate);
        followup.setDoctorCode(doctorCode);
        followup.setDoctorName(doctor.getName());
        followup.setOrgCode(doctor.getHospital());
        followup.setOrgName(doctor.getHospitalName());
        followup.setPatientCode(patientCode);
        followup.setPatientName(patient.getName());
        followup.setIdcard(patient.getIdcard());
        followup.setFollowupType(followupType);
        followup.setFollowupClass(followupClass);
        followup.setFollowupManagerStatus(followupManagerStatus);
        followup.setDataFrom("2");//数据来源 1基卫 2APP
        followup.setStatus("3");     //状态 0取消 1已完成 2未开始 3进行中
        followup.setCreateTime(new Date());
        followup.setCreater(doctorCode);
        followup.setAdminTeamCode(signFamily.getAdminTeamId());
        followup.setSignType(2);
        followupDao.save(followup);
        re = String.valueOf(followup.getId());
        return re;
    }

    /**
     * 取消随访计划
     */
    public void cancelFollowupPlan(String id) throws Exception {
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            followup.setStatus("0");  //状态 0取消 1已完成 2未开始 3进行中
            followupDao.save(followup);
        } else {
            throw new Exception("not exit follow:" + id + ".\r\n");
        }
    }

    /**
     * 完成随访记录，并上传随访记录
     */
    public void finishFollowup(String id) throws Exception {
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            followup.setStatus("1");  //状态 0取消 1已完成 2未开始 3进行中
            followupDao.save(followup);

            //上传随访计划
            new Thread(new FollowupUploadTask(String.valueOf(followup.getId()))).start();
        } else {
            throw new Exception("not exit follow:" + id + ".\r\n");
        }
    }

    /*********************************** 随访详情 *******************************************************************/
    /**
     * 获取面访项目列表
     */
    public Map<String, String> getFollowup(String id) throws Exception {
        Map<String, String> re = new HashMap<>();
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            re = getFollowupDetail(followup);
        } else {
            throw new Exception("not exit follow:" + id + ".\r\n");
        }
        return re;
    }

    /**
     * 获取面访项目列表
     */
    public List<Map<String, String>> getFollowupProject(String id) throws Exception {
        List<Map<String, String>> re = new ArrayList<>();
        //获取已填写的面访项目
        List<String> project = followupContentDao.findProjectByFollowupId(Long.valueOf(id));
        //获取所有面访项目
        List<SystemDict> dictList = systemDictService.getDictByDictName("FOLLOWUP_PROJECT");
        if (dictList != null && dictList.size() > 0) {
            for (SystemDict dict : dictList) {
                Map<String, String> map = new HashMap<>();
                String code = dict.getCode();
                map.put("projectCode", code);
                map.put("projectName", dict.getValue());
                if (project != null && project.contains(code)) {
                    map.put("status", "1"); //已填写
                } else {
                    map.put("status", "0");//未填写
                }
                re.add(map);
            }
        }
        return re;
    }

    /**
     * 获取面访项目数据
     */
    public Map<String, String> getFollowupProjectData(String id, String followupProject) throws Exception {
        Map<String, String> re = new HashMap<>();
        List<FollowupContent> dataList = followupContentDao.findByFollowupIdAndFollowupProject(Long.valueOf(id), followupProject);
        for (FollowupContent item : dataList) {
            re.put(item.getFollowupKey(), item.getFollowupValue());
        }
        return re;
    }


    /**
     * 保存面访项目数据
     */
    @Transactional
    public void saveFollowupProjectData(String id, String followupProject, String followupProjectData) throws Exception {
        List<FollowupContent> dataList = followupContentDao.findByFollowupIdAndFollowupProject(Long.valueOf(id), followupProject);

        //删除原有记录
        followupContentDao.delete(dataList);

        Map<String, String> data = objectMapper.readValue(followupProjectData, Map.class);

        if (data != null && data.keySet().size() > 0) {
            List<FollowupContent> newList = new ArrayList<>();
            for (String key : data.keySet()) {
                FollowupContent item = new FollowupContent();
                item.setFollowupId(Long.valueOf(id));
                item.setFollowupProject(followupProject);
                item.setFollowupKey(key);
                item.setFollowupValue(data.get(key));
                item.setCreateTime(new Date());
                newList.add(item);
            }
            followupContentDao.save(newList);

        }
    }


    /*********************************** 电话随访 *****************************************************************/
    /**
     * 获取电话随访内容
     */
    public String getFollowupPhone(String id) throws Exception {
        String re = "";
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            re = followup.getFollowupContentPhone();
        } else {
            throw new Exception("not exit followup:" + id + ".\r\n");
        }
        return re;
    }

    /**
     * 记录电话随访内容
     */
    public void saveFollowupPhone(String id, String content) throws Exception {
        Followup followup = followupDao.findOne(Long.valueOf(id));
        if (followup != null) {
            followup.setFollowupContentPhone(content);
            followupDao.save(followup);
        } else {
            throw new Exception("not exit followup:" + id + ".\r\n");
        }
    }


    /*************************************** 上次随访 ********************************************/

    /**
     * 获取团队医生
     */
    private List<Doctor> getTeamDoctors(String doctor, String patient) throws Exception {
        List<Doctor> doctors = new ArrayList<>();
        //获取医生团队成员
        SignFamily signFamily = signFamilyDao.findByFamilyDoctorAndPatient(doctor, patient);
        // 查询家庭医生团队
        if (signFamily != null) {
            doctors = drHealthTeamService.findTeamDoctors(signFamily.getTeamCode());
        }

        // 查询三师团队医生
        if (doctors == null || doctors.size() == 0) {
            SignFamily sanshiSign = signFamilyDao.findBySanshiDoctorAndPatient(doctor, patient);
            if (sanshiSign != null) {
                doctors = drHealthTeamService.findTeamDoctors(patient, 1);
            } else {
                doctors = new ArrayList<>();
            }
        }

        return doctors;
    }

    /**
     * 获取上次随访
     */
    public Map<String, String> getLastFollowup(String doctor, String patient, String followClass) throws Exception {
        Map<String, String> re = new HashMap<>();

        //获取医生团队成员
        String[] doctors = new String[]{doctor};
        List<Doctor> doctorList = getTeamDoctors(doctor, patient);
        if (doctorList != null && doctorList.size() > 1) {
            doctors = new String[doctorList.size()];
            for (int i = 0; i < doctorList.size(); i++) {
                doctors[i] = doctorList.get(i).getCode();
            }
        }

        //获取最新的随访记录
        Followup followup = followupDao.findLastFollowup(doctors, patient, followClass);

        if (followup != null) {
            re.put("id", String.valueOf(followup.getId()));
            re.put("followupDate", DateUtil.dateToStrShort(followup.getFollowupDate()));
        } else {
            re = null;
        }

        return re;
    }

    /**
     * 获取上次随访
     */
    public void copyFollowup(Long id, Long fromId) throws Exception {
        List<FollowupContent> list = followupContentDao.findByFollowupId(fromId);

        if (list != null && list.size() > 0) {
            List<FollowupContent> copyList = new ArrayList<>();
            for (FollowupContent item : list) {
                FollowupContent copyItem = new FollowupContent();
                copyItem.setFollowupId(id);
                copyItem.setFollowupKey(item.getFollowupKey());
                copyItem.setFollowupValue(item.getFollowupValue());
                copyItem.setFollowupProject(item.getFollowupProject());
                copyItem.setCreateTime(new Date());
                copyList.add(copyItem);
            }

            followupContentDao.save(copyList);
        }
    }

    /**************************************** 随访计划消息 ******************************************/
    /**
     * 每日发送随访计划提醒消息
     */
    @Transactional
    public void sendMessage(String date) {
        try {
            String start = date + " 00:00:00";
            String end = date + " 23:59:59";

            String sql = "select doctor_code,count(1) count from wlyy_followup where status not in ('0','1') and followup_plan_date>='" + start + "' and followup_plan_date<='" + end + "' group by doctor_code";
            //获取所有未执行随访计划
            List<Map<String, Object>> followupToday = jdbcTemplate.queryForList(sql);

            if (followupToday != null) {
                List<Message> list = new ArrayList<>();
                for (Map<String, Object> map : followupToday) {
                    String doctor = String.valueOf(map.get("doctor_code"));
                    String count = String.valueOf(map.get("count"));

                    // 添加签约消息
                    String title = "随访计划提醒";
                    String content = "您今日有" + count + "个随访计划待处理";
                    Message message = new Message();
                    message.setCode(getCode());
                    message.setCzrq(new Date());
                    message.setContent(content);
                    message.setRead(1);//设置未读
                    message.setReceiver(doctor);//设置接受医生的code
                    message.setSender("system");//设置发送的用户
                    message.setTitle(title);
                    message.setType(4);//随访计划提醒
                    message.setReadonly(1);//是否只读消息
                    list.add(message);
                    // 推送消息给医生
                    PushMsgTask.getInstance().put(doctor, "4", title, content, "");
                }

                messageDao.save(list);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
