package com.yihu.jw.hospital.message.service;

import com.alibaba.fastjson.JSONObject;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.yihu.jw.entity.base.patient.BasePatientDO;
import com.yihu.jw.entity.hospital.consult.WlyyHospitalSysDictDO;
import com.yihu.jw.entity.hospital.message.BaseBannerDoctorDO;
import com.yihu.jw.entity.hospital.message.BaseUserMessageDO;
import com.yihu.jw.hospital.dict.WlyyHospitalSysDictDao;
import com.yihu.jw.hospital.message.dao.BaseBannerDoctorDao;
import com.yihu.jw.hospital.message.dao.BaseUserMessageDao;
import com.yihu.jw.patient.dao.BasePatientDao;
import com.yihu.jw.restmodel.web.ObjEnvelop;
import com.yihu.jw.util.date.DateUtil;
import com.yihu.jw.utils.hibernate.HibenateUtils;
import com.yihu.mysql.query.BaseJpaService;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.transaction.Transactional;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

@Service
public class BaseBannerDoctorService
        extends BaseJpaService<BaseBannerDoctorDO, BaseBannerDoctorDao>
{
    @Autowired
    private BaseBannerDoctorDao baseBannerDoctorDao;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private BaseUserMessageDao baseUserMessageDao;
    @Autowired
    private BasePatientDao patientDao;
    @Autowired
    private HibenateUtils hibenateUtils;
    @Autowired
    private WlyyHospitalSysDictDao wlyyHospitalSysDictDao;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Value("${wechat.id}")
    private String wxId;


    @Value("${wechat.flag}")
    private boolean flag;
    @Transactional
    public ObjEnvelop bannerGive(String patientId, List<String> list, String content, String doctor, String doctorName, Integer type, String key, String value)
            throws IOException
    {
        String patientName = null;
        List<BaseBannerDoctorDO> bannerList = new ArrayList();
        ObjEnvelop objEnvelop = new ObjEnvelop();
        BasePatientDO basePatientDO = this.patientDao.findById(patientId);
        boolean checkTimeOut = checkGiveTimeOut(patientId, doctor);
        boolean checkMessageTimeout = checkMessageTimeOut(patientId,doctor);
        if ((org.apache.commons.lang.StringUtils.isNotBlank(key)) && (org.apache.commons.lang.StringUtils.isNotBlank(value))) {
            if (verifyCaptcha(key, value))
            {
                checkTimeOut = true;
                checkMessageTimeout = true;
            }
            else
            {
                objEnvelop.setMessage("验证码错误");
                objEnvelop.setStatus(Integer.valueOf(78));
                return objEnvelop;
            }
        }
        boolean checkTimes = checkGiveTimes(patientId, doctor);
        if (checkTimes)
        {
            if (checkTimeOut)
            {
                String relationCode = UUID.randomUUID().toString();
                if (null != basePatientDO) {
                    patientName = basePatientDO.getName();
                }
                if (list.size() > 0)
                {
                    for (int i = 0; i < list.size(); i++)
                    {
                        BaseBannerDoctorDO baseBannerDoctorDO = new BaseBannerDoctorDO();
                        baseBannerDoctorDO.setBannerId((String)list.get(i));
                        baseBannerDoctorDO.setContent(content);
                        baseBannerDoctorDO.setDoctor(doctor);
                        baseBannerDoctorDO.setDoctorName(doctorName);
                        baseBannerDoctorDO.setPatientId(patientId);
                        baseBannerDoctorDO.setPatientName(patientName);
                        baseBannerDoctorDO.setRelationType(Integer.valueOf(1));
                        baseBannerDoctorDO.setRelationName("赠送锦旗");
                        baseBannerDoctorDO.setRelationCode(relationCode);
                        bannerList.add(baseBannerDoctorDO);
                        this.baseBannerDoctorDao.save(baseBannerDoctorDO);
                        objEnvelop.setObj(bannerList);
                        objEnvelop.setMessage("success");
                    }
                    BaseUserMessageDO baseUserMessageDO = new BaseUserMessageDO();
                    baseUserMessageDO.setReceiver(doctor);
                    baseUserMessageDO.setContent(content);
                    baseUserMessageDO.setReceiverName(doctorName);
                    baseUserMessageDO.setRelationCode(relationCode);
                    baseUserMessageDO.setSender(patientId);
                    baseUserMessageDO.setSenderName(patientName);
                    baseUserMessageDO.setRelationName("赠送锦旗");
                    baseUserMessageDO.setRelationType(Integer.valueOf(2));
                    baseUserMessageDO.setStatus(Integer.valueOf(1));
                    baseUserMessageDO.setDel(Integer.valueOf(1));
                    baseUserMessageDO.setType(type);
                    baseUserMessageDO.setIsRead(Integer.valueOf(0));
                    this.baseUserMessageDao.save(baseUserMessageDO);
                }else {
                    if(checkMessageTimes(patientId,doctor)){
                        if (checkMessageTimeout){
                            BaseUserMessageDO baseUserMessageDO = new BaseUserMessageDO();
                            baseUserMessageDO.setReceiver(doctor);
                            baseUserMessageDO.setContent(content);
                            baseUserMessageDO.setReceiverName(doctorName);
                            baseUserMessageDO.setRelationCode(relationCode);
                            baseUserMessageDO.setSender(patientId);
                            baseUserMessageDO.setSenderName(patientName);
                            baseUserMessageDO.setRelationName("赠送锦旗");
                            baseUserMessageDO.setRelationType(Integer.valueOf(2));
                            baseUserMessageDO.setStatus(Integer.valueOf(1));
                            baseUserMessageDO.setDel(Integer.valueOf(1));
                            baseUserMessageDO.setType(type);
                            baseUserMessageDO.setIsRead(Integer.valueOf(0));
                            objEnvelop.setMessage("success");
                        }else {
                            objEnvelop.setMessage("生成验证码");
                            objEnvelop.setObj(generateCaptcha());
                            return objEnvelop;
                        }
                    }else {
                        objEnvelop.setMessage("当天总送锦旗留言次数已达上限");
                        objEnvelop.setStatus(Integer.valueOf(77));
                        return objEnvelop;
                    }
                }
            }
            else
            {
                objEnvelop.setMessage("生成验证码");
                objEnvelop.setObj(generateCaptcha());
                return objEnvelop;
            }
        }
        else
        {
            objEnvelop.setMessage("当天总送锦旗次数已达上限");
            objEnvelop.setStatus(Integer.valueOf(77));
            return objEnvelop;
        }
        return objEnvelop;
    }

    public JSONObject getDoctorBanners(String doctorID)
    {
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT COUNT(1) AS \"total\",b.name AS \"name\",b.img AS \"img\" FROM base_banner_doctor a LEFT JOIN base_banner b on a.banner_id= b.id where 1=1 ");

        sql.append("and a.doctor = '" + doctorID + "' ");
        sql.append(" GROUP BY a.banner_id ,b.name,b.img");

        List<Map<String, Object>> list = this.jdbcTemplate.queryForList(sql.toString());
        int count = this.baseBannerDoctorDao.getTotalBannerCount(doctorID).intValue();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("count", Integer.valueOf(count));
        jsonObject.put("resultlist", list);
        return jsonObject;
    }

    @Transactional
    public void isRead(String messageId, String doctor)
    {
        if (org.apache.commons.lang.StringUtils.isNotEmpty(messageId))
        {
            BaseUserMessageDO baseUserMessageDO = (BaseUserMessageDO)this.baseUserMessageDao.findOne(messageId);
            if (null != baseUserMessageDO)
            {
                baseUserMessageDO.setIsRead(Integer.valueOf(1));
                this.baseUserMessageDao.save(baseUserMessageDO);
            }
        }
        else
        {
            List<BaseUserMessageDO> list = this.baseUserMessageDao.getMessageNotReadNotPage(doctor);
            if (list.size() > 0) {
                for (BaseUserMessageDO baseUserMessageDO : list)
                {
                    baseUserMessageDO.setIsRead(Integer.valueOf(1));
                    this.baseUserMessageDao.save(baseUserMessageDO);
                }
            }
        }
    }

    public JSONObject getMessageNotRead(String doctor, Integer page, Integer pageSize)
    {
        Integer count = this.baseUserMessageDao.getMessageNotReadCount(doctor);
        Map mapSql = new HashMap();
        String sqlId = "select t.id as \"id\",t.content as \"content\",t.saas_id as \"saas_id\",t.is_read as \"is_read\",t.type as \"type\",t.sender as \"sender\",t.sender_name as \"sender_name\",t.receiver as \"receiver\",t.receiver_name as \"receiver_name\",t.relation_type as \"relation_type\",t.relation_code as \"relation_code\",t.relation_name as \"relation_name\",t.status as \"status\",t.del as \"del\",t.create_user as \"create_user\",t.create_user_name as \"create_user_name\",t.create_time as \"create_time\",t.update_user as \"update_user\",t.update_user_name as \"update_user_name\",t.update_time as \"update_time\" from base_user_message t where t.is_read = 0 ";
        if (org.apache.commons.lang.StringUtils.isNotEmpty(doctor))
        {
            sqlId = sqlId + " and t.receiver = :doctor order by t.update_time desc";
            mapSql.put("doctor", doctor);
        }
        List<Map<String, Object>> listALl = this.hibenateUtils.createSQLQuery(sqlId, mapSql, page, pageSize);
        List<BaseUserMessageDO> list = new ArrayList();
        for (Map<String, Object> map : listALl)
        {
            BaseUserMessageDO baseUserMessageDO = new BaseUserMessageDO();
            baseUserMessageDO.setContent(null == map.get("content") ? "" : map.get("content").toString());
            baseUserMessageDO.setSender(map.get("sender").toString()==null?"":map.get("sender").toString());
            baseUserMessageDO.setSenderName(map.get("sender_name")==null?"":map.get("sender_name").toString());
            baseUserMessageDO.setReceiver(map.get("receiver")==null?"":map.get("receiver").toString());
            baseUserMessageDO.setReceiverName(map.get("receiver_name").toString());
            baseUserMessageDO.setRelationCode(map.get("relation_code").toString());
            baseUserMessageDO.setRelationName(map.get("relation_name").toString());
            baseUserMessageDO.setRelationType(Integer.valueOf(map.get("relation_type").toString()));
            baseUserMessageDO.setStatus(Integer.valueOf(map.get("status").toString()));
            baseUserMessageDO.setDel(Integer.valueOf(map.get("del").toString()));
            baseUserMessageDO.setType(Integer.valueOf(map.get("type").toString()));
            baseUserMessageDO.setIsRead(Integer.valueOf(map.get("is_read").toString()));
            if (null != map.get("create_time"))
            {
                String createTime = map.get("create_time").toString();
                map.put("create_time", DateUtil.dateToStrLong(DateUtil.strToDateLong(createTime)));
                baseUserMessageDO.setCreateTime(DateUtil.strToDateLong(createTime));
            }
            if (null != map.get("update_time"))
            {
                String updateTime = map.get("update_time").toString();
                baseUserMessageDO.setUpdateTime(DateUtil.strToDateLong(updateTime));
            }
            if (null != map.get("create_user")) {
                baseUserMessageDO.setCreateUser(map.get("create_user").toString());
            }
            if (null != map.get("update_user")) {
                baseUserMessageDO.setUpdateUser(map.get("update_user").toString());
            }
            list.add(baseUserMessageDO);
        }
        JSONObject jsonObject = new JSONObject();
        if (list!=null&&list.size() > 0) {
            jsonObject.put("messageNotRead", list);
        }
        jsonObject.put("totalCount", count);
        return jsonObject;
    }

    public boolean checkGiveTimeOut(String patientId, String doctor)
    {

        List<BaseBannerDoctorDO> baseBannerDoctorDOS = this.baseBannerDoctorDao.getBannersBypatients(patientId, doctor);
        WlyyHospitalSysDictDO wlyyHospitalSysDictDO = this.wlyyHospitalSysDictDao.findById("banner_give_timeout");
        if (null != baseBannerDoctorDOS&&baseBannerDoctorDOS.size()>0&&baseBannerDoctorDOS.size()>=1)
        {
            BaseBannerDoctorDO lastOne = (BaseBannerDoctorDO)baseBannerDoctorDOS.get(0);
            Date lastDate = lastOne.getCreateTime();
            long timeOut = wlyyHospitalSysDictDO.getDictValue() != null ? Long.valueOf(wlyyHospitalSysDictDO.getDictValue()).longValue() : 5L;
            Date current = new Date();
            if (current.getTime() - lastDate.getTime() > timeOut * 1000L * 60L) {
                return true;
            }
            return false;
        }
        return true;
    }

    public boolean checkGiveTimes(String patientId, String doctorId)
    {
        StringBuffer sql = new StringBuffer();
        sql.append("select t.relation_code as \"relation_code\",t.patient_id as \"patient_id\" from base_banner_doctor t");
        sql.append(" where 1=1 ");
        if (org.apache.commons.lang.StringUtils.isNotBlank(patientId)) {
            sql.append(" and t.patient_id = '" + patientId + "'");
        }
        if (org.apache.commons.lang.StringUtils.isNotBlank(doctorId)) {
            sql.append(" and t.doctor = '" + doctorId + "'");
        }
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String strDate = format.format(date);
        if("xm_ykyy_wx".equals(wxId)){
            if (flag){
                sql.append(" and t.create_time > '" + strDate + " 00:00:00' and t.create_time<'" + strDate + " 23:59:59'");
            }else {
                sql.append(" and t.create_time > to_date('" + strDate + " 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and t.create_time< to_date('" + strDate + " 23:59:59','yyyy-mm-dd hh24:mi:ss')");
            }
        }else{
            sql.append(" and t.create_time > '" + strDate + " 00:00:00' and t.create_time<'" + strDate + " 23:59:59'");
        }
        sql.append(" group by t.relation_code,t.patient_id");
        List<Map<String, Object>> list = this.hibenateUtils.createSQLQuery(sql.toString());
        WlyyHospitalSysDictDO wlyyHospitalSysDictDO = this.wlyyHospitalSysDictDao.findById("banner_gives_times");
        long countTimes = 5L;
        if (wlyyHospitalSysDictDO != null) {
            countTimes = wlyyHospitalSysDictDO.getDictValue() == null ? countTimes : Long.valueOf(wlyyHospitalSysDictDO.getDictValue()).longValue();
        }
        if (list.size() > countTimes) {
            return false;
        }
        return true;
    }

    public Map<String, String> generateCaptcha()
            throws IOException
    {
        DefaultKaptcha captchaProducer = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.put("kaptcha.textproducer.font.color", "blue");
        properties.put("kaptcha.textproducer.font.size", "45");
        properties.put("kaptcha.textproducer.char.length", "4");
        properties.put("kaptcha.textproducer.font.names", "宋体,楷体,微软雅黑");
        properties.put("kaptcha.textproducer.char.string", "0123456789");
        Config config = new Config(properties);
        captchaProducer.setConfig(config);
        String captchaText = captchaProducer.createText();
        BufferedImage image = captchaProducer.createImage(captchaText);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "png", outputStream);
        String base64Img = new BASE64Encoder().encode(outputStream.toByteArray());
        base64Img = "data:image/jpeg;base64," + base64Img.replaceAll("\n", "").replaceAll("\r", "");

        String key = "hwlyy:captcha:" + UUID.randomUUID().toString();

        Map<String, String> data = new HashMap();
        data.put("key", key);
        data.put("image", base64Img);
        data.put("format", "png");

        this.redisTemplate.opsForValue().set(key, captchaText.toLowerCase(), 5L, TimeUnit.MINUTES);
        return data;
    }

    public boolean verifyCaptcha(String key, String text)
    {
        boolean pass = false;
        String captcha = (String)this.redisTemplate.opsForValue().get(key);
        if ((org.apache.commons.lang3.StringUtils.isNotBlank(captcha)) && (captcha.equals(text.toLowerCase())))
        {
            pass = true;
            this.redisTemplate.delete(key);
        }
        return pass;
    }




    public boolean checkMessageTimeOut(String sender, String reciver)
    {
        List<BaseUserMessageDO> baseBannerDoctorDOS = this.baseUserMessageDao.getMessageByPatientAndDoctor(reciver, sender);
        WlyyHospitalSysDictDO wlyyHospitalSysDictDO = this.wlyyHospitalSysDictDao.findById("leave_message_timeout");
        if (null != baseBannerDoctorDOS&&baseBannerDoctorDOS.size()>=1)
        {
            BaseUserMessageDO lastOne = baseBannerDoctorDOS.get(0);
            Date lastDate = lastOne.getCreateTime();
            long timeOut = wlyyHospitalSysDictDO.getDictValue() != null ? Long.valueOf(wlyyHospitalSysDictDO.getDictValue()).longValue() : 5L;
            Date current = new Date();
            if (current.getTime() - lastDate.getTime() > timeOut * 1000L * 60L) {
                return true;
            }
            return false;
        }
        return true;
    }

    public boolean checkMessageTimes(String patientId, String doctorId)
    {
        StringBuffer sql = new StringBuffer();
        sql.append("select t.sender as \"sender\",t.receiver as \"receiver\" from base_user_message t");
        sql.append(" where 1=1 ");
        if (StringUtils.isNotBlank(patientId)) {
            sql.append(" and t.sender = '" + patientId + "'");
        }
        if (StringUtils.isNotBlank(doctorId)) {
            sql.append(" and t.receiver = '" + doctorId + "'");
        }
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String strDate = format.format(date);
        System.out.println(wxId+flag);
        if("xm_ykyy_wx".equals(wxId)){
            if (flag){
                sql.append(" and t.create_time > '" + strDate + " 00:00:00' and t.create_time<'" + strDate + " 23:59:59'");
            }else {
                sql.append(" and t.create_time > to_date('" + strDate + " 00:00:00', 'yyyy-mm-dd hh24:mi:ss') and t.create_time< to_date('" + strDate + " 23:59:59','yyyy-mm-dd hh24:mi:ss')");
            }
        }else{
            sql.append(" and t.create_time > '" + strDate + " 00:00:00' and t.create_time<'" + strDate + " 23:59:59'");
        }
        List<Map<String, Object>> list = this.hibenateUtils.createSQLQuery(sql.toString());
        WlyyHospitalSysDictDO wlyyHospitalSysDictDO = this.wlyyHospitalSysDictDao.findById("leave_message_times");
        long countTimes = 5L;
        if (wlyyHospitalSysDictDO != null) {
            countTimes = wlyyHospitalSysDictDO.getDictValue() == null ? countTimes : Long.valueOf(wlyyHospitalSysDictDO.getDictValue()).longValue();
        }
        if (list.size() > countTimes) {
            return false;
        }
        return true;
    }
}