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

import com.yihu.wlyy.entity.doctor.profile.Doctor;
import com.yihu.wlyy.entity.organization.Hospital;
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.organization.HospitalDao;
import com.yihu.wlyy.repository.patient.PatientDao;
import com.yihu.wlyy.repository.patient.SignFamilyDao;
import com.yihu.wlyy.service.BaseService;
import com.yihu.wlyy.service.common.SMSService;
import com.yihu.wlyy.task.PushMsgTask;
import com.yihu.wlyy.util.DateUtil;
import com.yihu.wlyy.util.SendP2PUtil;
import com.yihu.wlyy.wechat.util.WeiXinAccessTokenUtils;
import org.apache.commons.lang3.StringUtils;
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.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 缴费提醒服务
 * <p>
 * Created by lyr on 2016/10/24.
 */
@Service
public class ExpensesRemindService extends BaseService {

    @Autowired
    SignFamilyDao signFamilyDao;
    @Autowired
    DoctorDao doctorDao;
    @Autowired
    PatientDao patientDao;
    @Autowired
    HospitalDao hospitalDao;
    @Autowired
    SMSService smsService;
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    WeiXinAccessTokenUtils tokenUtils;
    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * 缴费提醒
     *
     * @param doctor 医生
     * @throws Exception
     */
    @Async
    public void remindPatientExpensesAll(String doctor) throws Exception {
        try {
            Doctor doc = doctorDao.findByCode(doctor);
            if (doc == null) {
                throw new Exception("doctor info can not find");
            }

            Hospital hos = hospitalDao.findByCode(doc.getHospital());
            if (hos == null) {
                throw new Exception("hospital info can not find");
            }

            RemindAll(doc, hos);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 所有未缴费提醒
     *
     * @param doc
     * @param hos
     */
    public void RemindAll(Doctor doc, Hospital hos) {
        try {
            String sql = "select distinct a.patient from " +
                    " (select patient,expenses_status,LENGTH(trim(ifnull(expenses_status,''))) len " +
                    "     from " +
                    "        wlyy_sign_family " +
                    "     where "
                    + (doc.getLevel() == 2 ? "doctor" : "doctor_health") + " = ? " +
                    "        and status > 0 " +
                    "        and type = 2 " +
                    "        order by begin desc ) a" +
                    " where a.expenses_status = '0' or a.len < 1";

            List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, new Object[]{doc.getCode()});

            if (result != null && result.size() > 0) {
                for (Map<String, Object> map : result) {
                    Patient p = patientDao.findByCode(String.valueOf(map.get("patient")));

                    if (p != null) {
                        String epTime = redisTemplate.opsForValue().get("expenses:remind:" + p.getCode());
                        if(StringUtils.isNotEmpty(epTime) &&
                                new SimpleDateFormat("yyyy-MM-dd").format(new Date()).equals(epTime)) {
                            continue;
                        }
                        remindPatientExpenses(p, doc, hos, true);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 提醒患者缴费
     *
     * @param patient 患者
     * @param doctor  医生
     * @return
     */
    public JSONObject remindPatientExpenses(String patient, String doctor) {
        try {
            Doctor doc = doctorDao.findByCode(doctor);
            if (doc == null) {
                throw new Exception("doctor info can not find");
            }

            Hospital hos = hospitalDao.findByCode(doc.getHospital());
            if (hos == null) {
                throw new Exception("hospital info can not find");
            }

            Patient p = patientDao.findByCode(patient);

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

            return remindPatientExpenses(p, doc, hos, false);
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject reObj = new JSONObject();
            reObj.put("status",-1);
            reObj.put("msg",e.getMessage());
            return reObj;
        }
    }

    /**
     * 提醒患者缴费
     *
     * @param p   患者
     * @param doc 医生
     * @param hos 医院
     * @return
     */
    public JSONObject remindPatientExpenses(Patient p, Doctor doc, Hospital hos, boolean ignore) throws Exception {
        try {
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            JSONObject reObj = new JSONObject();
            String mDesc = "";
            boolean mFlag = false;
            boolean wFlag = false;
            boolean isMobileExist = false;
            boolean isOpenIdExist = false;

            if (StringUtils.isNotEmpty(p.getMobile())) {
                isMobileExist = true;
                JSONObject result = smsService.sendMsg(p.getMobile(), doc.getName() + "医生提醒您：为完成家庭医生签约，" +
                        "尽早为您提供家庭医生服务，请尽快到" + hos.getName() + "（地址：" + hos.getAddress() + "）缴费");
                if (result != null && result.getInt("result") == 0) {
                    mFlag = true;
                }
                if (result != null) {
                    mDesc = result.getString("description");
                }
            }
            if (StringUtils.isNotEmpty(p.getOpenid())) {
                isOpenIdExist = true;
                // 微信提醒
                JSONObject json = new JSONObject();
                json.put("first", "缴费提醒");
                json.put("toUser", p.getCode());
                json.put("name", p.getName());
                json.put("doctor", doc.getCode());
                json.put("doctorName", doc.getName());
                json.put("date", DateUtil.dateToStrShort(new Date()));
                json.put("content", p.getName() + "，您好！为完成家庭医生签约，尽早为您提供家庭医生服务，请尽快到" + hos.getName() + "（地址：" + hos.getAddress() + "）缴费");
                json.put("remark", "");
                // 添加到发送队列
                PushMsgTask.getInstance().putWxMsg(tokenUtils.getAccessToken(), 8, p.getOpenid(), p.getName(), json);
                wFlag = true;
            }
            //发送IM
            SendP2PUtil.sendP2Pmsg(doc.getCode(),p.getCode(),"1",doc.getName() + "医生提醒您：为完成家庭医生签约，" +
                    "尽早为您提供家庭医生服务，请尽快到" + hos.getName() + "（地址：" + hos.getAddress() + "）缴费");
            if (ignore) {
                redisTemplate.opsForValue().set("expenses:remind:" + p.getCode(), df.format(new Date()));
                redisTemplate.expire("expenses:remind:" + p.getCode(), 1, TimeUnit.DAYS);
            }

            if (wFlag || mFlag) {
                reObj.put("status", 200);
                redisTemplate.opsForValue().set("expenses:remind:" + p.getCode(), df.format(new Date()));
                redisTemplate.expire("expenses:remind:" + p.getCode(), 1, TimeUnit.DAYS);
                if (wFlag && mFlag) {
                    reObj.put("msg", "提醒成功");
                } else if (mFlag && !wFlag) {
                    reObj.put("msg", "已短信提醒，居民未绑定微信，无法微信提醒");
                } else {
                    if (!isMobileExist) {
                        reObj.put("msg", "已微信提醒，居民未绑定手机，无法短信提醒");
                    } else {
                        reObj.put("msg", "已微信提醒，短信提醒失败，失败原因：" + mDesc);
                    }
                }
            } else {
                reObj.put("status", -1);

                if (!isMobileExist && !isOpenIdExist) {
                    reObj.put("msg", "居民未绑定手机及微信，无法提醒");
                } else if (isMobileExist && !isOpenIdExist) {
                    reObj.put("msg", "居民未绑定微信，且短信提醒失败，无法提醒居民。短信失败原因：" + mDesc);
                } else {
                    reObj.put("msg", "提醒失败");
                }
            }

            return reObj;
        } catch (Exception e) {
            e.printStackTrace();
            JSONObject reObj = new JSONObject();
            reObj.put("status",-1);
            reObj.put("msg",e.getMessage());
            return reObj;
        }
    }
}
