package com.ym.mec.biz.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.SysMessageDao;
import com.ym.mec.biz.dal.entity.SysMessage;
import com.ym.mec.biz.dal.entity.SysMessageConfig;
import com.ym.mec.biz.dal.entity.SysMessageConfig.MessageType;
import com.ym.mec.biz.dal.enums.MessageSendMode;
import com.ym.mec.biz.dal.enums.SendStatusEnum;
import com.ym.mec.biz.service.SysMessageConfigService;
import com.ym.mec.biz.service.SysMessageService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.redis.service.RedisCache;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext.MessageSender;
import com.ym.mec.util.string.MessageFormatter;

@Service
public class SysMessageServiceImpl extends BaseServiceImpl<Long, SysMessage> implements SysMessageService {

	private final static Logger LOGGER = LoggerFactory.getLogger(SysMessageServiceImpl.class);

	@Autowired
	private SysMessageDao sysMessageDao;

	@Autowired
	private SysMessageConfigService sysMessageConfigService;

	@Autowired
	private MessageSenderPluginContext messageSenderPluginContext;

	@Autowired
	private SysUserFeignService sysUserFeignService;
	
	@Autowired
	private RedisCache<String,Object> redisCache;

	// 验证码有效期
	public static final int CODE_EXPIRE = 60 * 5;

	// 发送验证码的间隔时间
	public static final int CODE_INTERVAL_TIME = 60;

	private final int DEFAULT_CODE = 888888;

	@Value("${message.debugMode:true}")
	private boolean debugMode = false;

	@Override
	public BaseDAO<Long, SysMessage> getDAO() {
		return sysMessageDao;
	}

	@Override
	public int addMessage(Integer userId, String subject, String content, String receivers, Date triggerTime, MessageSendMode mode, SendStatusEnum status,
			String errorMsg, Integer readStatus, String memo) {
		SysMessage message = null;
		Date date = new Date();

		List<SysMessage> messages = new ArrayList<SysMessage>();
		String[] tels = StringUtils.split(receivers, ',');
		if (tels != null && tels.length > 0) {
			for (String tel : tels) {
				message = new SysMessage();
				if (userId == null) {
					SysUser user = sysUserFeignService.getUserByMobile(tel);
					if (user != null) {
						userId = user.getId();
					}
				}
				message.setUserId(userId);
				message.setContent(content);
				message.setCreateOn(date);
				message.setModifyOn(date);
				message.setReceiver(tel);
				if (triggerTime == null) {
					triggerTime = date;
				}
				message.setSendTime(triggerTime);
				message.setTitle(subject);
				message.setStatus(status);
				message.setType(mode);
				message.setErrorMsg(errorMsg);
				message.setReadStatus(readStatus);
				message.setMemo(memo);

				messages.add(message);
			}
		}
		return sysMessageDao.batchInsert(messages);
	}

	@Override
	public int updateMessage(SysMessage message) {
		return sysMessageDao.update(message);
	}

	@Override
	@Async
	public boolean batchSendMessage(MessageSender messageSender, MessageSendMode mode, String subject, String content, String receivers, Date triggerTime,
			Integer readStatus, String memo) {

		if (StringUtils.isBlank(receivers)) {
			throw new BizException("消息接收人不能为空");
		}
		if (StringUtils.isBlank(content)) {
			throw new BizException("消息内容不能为空");
		}
		String[] tos = StringUtils.split(receivers, ',');
		if (tos != null && tos.length > 0) {
			Date date = new Date();
			SendStatusEnum status = SendStatusEnum.WAIT;

			String errorMsg = null;
			try {
				// 立即发送
				if (triggerTime == null || date.after(triggerTime)) {
					status = SendStatusEnum.SENDING;
					if (debugMode == true || messageSenderPluginContext.batchSend(messageSender, subject, content, tos, memo)) {
						status = SendStatusEnum.SUCCESSED;
					} else {
						status = SendStatusEnum.FAILED;
					}
				}
			} catch (Exception e) {
				status = SendStatusEnum.FAILED;
				errorMsg = e.getMessage();
				LOGGER.warn("消息发送失败", e);
			}
			return addMessage(null, subject, content, receivers, triggerTime, mode, status, errorMsg, readStatus, memo) > 0;
		}

		return false;
	}

	@Override
	@Async
	public void sendMessage(MessageSender messageSender, Integer userId, MessageSendMode mode, MessageType type, String receiver, Date triggerTime,
			Integer readStatus, String url, Object... args) {

		if (StringUtils.isBlank(receiver)) {
			throw new BizException("接收地址不能为空");
		}
		SysMessageConfig messageConfig = sysMessageConfigService.queryByType(type);
		if (messageConfig == null) {
			throw new BizException("消息类型错误");
		}
		Date date = new Date();
		SendStatusEnum status = SendStatusEnum.WAIT;
		String errorMsg = null;
		// 立即发送
		if (triggerTime == null || date.after(triggerTime)) {
			status = SendStatusEnum.SENDING;
			try {
				if (debugMode == true
						|| messageSenderPluginContext.send(messageSender, receiver, messageConfig.getDescription(),
								MessageFormatter.arrayFormat(messageConfig.getContent(), args), url)) {
					status = SendStatusEnum.SUCCESSED;
				} else {
					status = SendStatusEnum.FAILED;
				}
			} catch (Exception e) {
				status = SendStatusEnum.FAILED;
				errorMsg = e.getMessage();
				LOGGER.warn("消息发送失败", e);
			}
		}
		addMessage(userId, type.getCode(), MessageFormatter.arrayFormat(messageConfig.getContent(), args), receiver, triggerTime, mode, status, errorMsg,
				readStatus, url);
	}

	@Override
	@Async
	public void sendMessage(MessageSender messageSender, Integer userId, MessageSendMode mode, String title, String content, String receiver, Date triggerTime,
			Integer readStatus, String url) {
		if (StringUtils.isBlank(receiver)) {
			throw new BizException("接收地址不能为空");
		}
		Date date = new Date();
		SendStatusEnum status = SendStatusEnum.WAIT;
		String errorMsg = null;
		// 立即发送
		if (triggerTime == null || date.after(triggerTime)) {
			status = SendStatusEnum.SENDING;
			try {
				if (debugMode == true || messageSenderPluginContext.send(messageSender, receiver, title, content, url)) {
					status = SendStatusEnum.SUCCESSED;
				} else {
					status = SendStatusEnum.FAILED;
				}
			} catch (Exception e) {
				status = SendStatusEnum.FAILED;
				errorMsg = e.getMessage();
				LOGGER.warn("消息发送失败", e);
			}
		}
		addMessage(userId, title, content, receiver, triggerTime, mode, status, errorMsg, readStatus, url);
	}

	@Override
	public boolean sendSecurityCode(MessageSender messageSender, Integer userId, MessageSendMode mode, MessageType messageType, String receiver) {
		String key1 = getVerificationCode1CacheKey(messageType, receiver);
		if (redisCache.get(key1) != null) {
			throw new BizException("请勿频繁操作，获取验证码间隔时间为60秒");
		}

		String key = getVerificationCodeCacheKey(messageType, receiver);
		int code = DEFAULT_CODE;
		if (debugMode == false) {
			code = getRandomCode(messageType, receiver);
		}
		sendMessage(messageSender, userId, mode, messageType, receiver, null, 1, "", code);
		redisCache.put(key, code, CODE_EXPIRE);
		redisCache.put(key1, code, CODE_INTERVAL_TIME);
		return true;
	}

	@Override
	public String getSendedVerificationCode(MessageType type, String mobileNOOrEmailAddr) {
		if (debugMode == true) {
			return DEFAULT_CODE + "";
		}
		String key = getVerificationCodeCacheKey(type, mobileNOOrEmailAddr);
		Object object = redisCache.get(key);
		return object == null ? null : object.toString();
	}

	@Override
	public void delSendedVerificationCode(MessageType type, String mobileNOOrEmailAddr) {
		String key = getVerificationCodeCacheKey(type, mobileNOOrEmailAddr);
		if (StringUtils.isNotBlank(key)) {
			redisCache.delete(key);
		}
	}

	@Override
	public int queryCountOfUnread(Integer userId) {
		return sysMessageDao.queryCountOfUnread(userId);
	}

	public void setDebugMode(boolean debugMode) {
		this.debugMode = debugMode;
	}

	private int getRandomCode(MessageType type, String mobileNo) {
		int min = 100000;
		int max = 999999;
		Random random = new Random();

		return random.nextInt(max) % (max - min + 1) + min;
	}

	private static String getVerificationCodeCacheKey(MessageType type, String mobileNOOrEmailAddr) {
		return "verificationCode" + type.name() + mobileNOOrEmailAddr;
	}

	private static String getVerificationCode1CacheKey(MessageType type, String mobileNOOrEmailAddr) {
		return "verificationCode" + mobileNOOrEmailAddr;
	}

	/**
	 *
	 * @param userId 用户id数组
	 * @param status 状态/1 已读,0未读
	 * @return 修改的条数
	 */
	@Override
	public int updateStatus(Integer userId, int status) {
		return sysMessageDao.updateStatus(userId, status);
	}

	@Override
	public int updateOneStatus(Long id, int status) {
		return sysMessageDao.updateOneStatus(id, status);
	}
}