package com.artfess.application.service.impl;

import com.artfess.activemq.model.JmsMessage;
import com.artfess.application.model.MessageConfig;
import com.artfess.application.model.MsgTemplate;
import com.artfess.application.persistence.manager.MsgTemplateManager;
import com.artfess.application.service.TemplateService;
import com.artfess.base.exception.NotFoundException;
import com.artfess.base.exception.RequiredException;
import com.artfess.base.feign.UCFeignService;
import com.artfess.base.jms.JmsActor;
import com.artfess.base.jms.JmsProducer;
import com.artfess.base.jms.Notice;
import com.artfess.base.jms.NoticeMessageType;
import com.artfess.base.template.impl.FreeMarkerEngine;
import com.artfess.base.util.AppUtil;
import com.artfess.base.util.BeanUtils;
import com.artfess.base.util.JsonUtil;
import com.artfess.base.util.StringUtil;
import com.artfess.uc.api.model.IUser;
import com.artfess.uc.api.service.IUserService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * <pre>
 * @author zhaoxy
 * @company 广州宏天软件股份有限公司
 * @email zhxy@jee-soft.cn
 * @date 2018-06-06 14:20
 * </pre>
 */
@Service
public class TemplateServiceImpl implements TemplateService {
    private Log logger = LogFactory.getLog(TemplateServiceImpl.class);
    @Resource
    FreeMarkerEngine freeMarkerEngine;
    @Resource
    MsgTemplateManager msgTemplateManager;
    @Resource
    JmsProducer jmsProducer;
    @Resource
    UCFeignService ucFeignService;


    @Override
    public void sendNotice2Jms(Notice notice) {
        jmsProducer.sendToQueue(notice);
    }

    @Override
    public void sendNotice(Notice notice) {
        if (BeanUtils.isEmpty(notice)) {
            throw new RequiredException("The args 'Notice' is required.");
        }
        NoticeMessageType[] messageTypes = notice.getMessageTypes();
        if (messageTypes.length == 0) {
            throw new RequiredException("The 'messageTypes' in 'Notice' is required.");
        }
        List<JmsActor> receiver = notice.getReceiver();
        if (BeanUtils.isEmpty(receiver) && BeanUtils.isNotEmpty(notice.getReceivers())) {
            ArrayNode users = ucFeignService.getUserByAccounts(StringUtils.join(notice.getReceivers(), ","));
            if (BeanUtils.isNotEmpty(users)) {
                receiver = new ArrayList<JmsActor>();
                for (JsonNode j : users) {
                    JmsActor actor = convertUserObject2JmsActor(j);
                    if (BeanUtils.isNotEmpty(actor)) {
                        receiver.add(actor);
                    }
                }
            }
        }
        if (receiver.size() == 0) {
            throw new RequiredException("The 'receivers' in 'Notice' is required.");
        }
        JmsProducer jmsProducer = AppUtil.getBean(JmsProducer.class);
        String templateKey = notice.getTemplateKey();
        String templateType = notice.getTemplateType();
        if (notice.isUseTemplate() && StringUtil.isEmpty(templateKey) && StringUtil.isEmpty(templateType)) {
            throw new RequiredException("Nor the 'templateKey' and the 'templateType' is empty, so we can not find out the template to send with.");
        }

        JsonNode sender = null;
        String senderAccount = notice.getSender();
        if (StringUtil.isNotEmpty(senderAccount)) {
            sender = ucFeignService.loadUserByUsername(senderAccount);
        }
//		List<JsonNode> receiveUsers = new ArrayList<>();
//		JmsActor[] receiverAccounts = ArrayUtil.unique(receivers);
//		for(String account : receiverAccounts) {
//			JsonNode receiver = ucFeignService.loadUserByUsername(account);
//			if(BeanUtils.isEmpty(receiver)){
//				CommonResult<JsonNode> userById = ucFeignService.getUserById(account);
//				if(userById.getState()) {
//					receiver = userById.getValue();
//				}
//			}
//			if(BeanUtils.isNotEmpty(receiver)) {
//				receiveUsers.add(receiver);
//			}
//		}
//		if(receiveUsers.size()==0) {
//			throw new RequiredException("The accounts of 'receivers' in 'Notice' can not find the match user, so we did not send the message.");
//		}
        String subject = notice.getSubject();
        String content = notice.getContent();
        String plainContent = "";
        String templateAlias = "";
        String templateTypeKey = "";
        String smsTemplateNo = "";//阿里大鱼短信模板code
        String voiceTemplateNo = "";//阿里大鱼语音模板code

        if (notice.isUseTemplate()) {
            MsgTemplate templateVo = null;
            if (StringUtil.isNotEmpty(templateKey)) {
                templateVo = this.getTemplate(templateKey);
                if (BeanUtils.isEmpty(templateVo)) {
                    throw new NotFoundException(String.format("The is no template key was '%s'.", templateKey));
                }
            } else {
                templateVo = this.getDefaultTemplate(templateType);
                if (BeanUtils.isEmpty(templateVo)) {
                    throw new NotFoundException(String.format("The is no default template for type: '%s'.", templateType));
                }
            }
            Map<String, Object> vars = notice.getVars();
            subject = this.parseSubject(templateVo, vars);
            content = this.parseHtmlContent(templateVo, vars);
            plainContent = this.parsePlainContent(templateVo, vars);
            templateAlias = templateVo.getKey();
            templateTypeKey = templateVo.getTypeKey();
            if (StringUtil.isNotEmpty(templateVo.getSmsTemplateNo())) {
                smsTemplateNo = templateVo.getSmsTemplateNo();
            }
            if (StringUtil.isNotEmpty(templateVo.getVoiceTemplateNo())) {
                voiceTemplateNo = templateVo.getVoiceTemplateNo();
            }
        }

//		List<JmsActor> receives = new ArrayList<>();
//		for(JsonNode user : receiveUsers) {
//			receives.add(convertUserObject2JmsActor(user));
//		}

        for (NoticeMessageType type : messageTypes) {
            JmsMessage jmsMessage = null;
            if (type.isPlain() && notice.isUseTemplate()) {
                jmsMessage = new JmsMessage(templateAlias, subject, plainContent, convertUserObject2JmsActor(sender), receiver, type.key(),templateTypeKey);
            } else {
                jmsMessage = new JmsMessage(templateAlias, subject, content, convertUserObject2JmsActor(sender), receiver, type.key(),templateTypeKey);
            }
            if (StringUtil.isNotEmpty(smsTemplateNo)) {
                jmsMessage.setSmsTemplateNo(smsTemplateNo);
            }
            if (StringUtil.isNotEmpty(voiceTemplateNo)) {
                jmsMessage.setVoiceTemplateNo(voiceTemplateNo);
            }
            jmsMessage.setExtendVars(notice.getVars());
            jmsProducer.sendToQueue(jmsMessage);
        }
    }

    @Override
    public void sendToQueueByMessageConfig(Notice notice, MessageConfig messageConfig) {
        //根据消息配置查询消息模板信息，并组装notice消息
        if (BeanUtils.isEmpty(messageConfig)) {
            throw new NotFoundException("Message config cannot be empty！");
        }
        if (BeanUtils.isEmpty(messageConfig)) {
            throw new NotFoundException("Notice cannot be empty！");
        }
        MsgTemplate template = getTemplate(messageConfig.getTplKey());
        //接收人配置方式为固定时去查询，否则就需要调用的时候传入
        if(messageConfig.getUserConfigType() == 2){
            String userIds = messageConfig.getUserId();
            String orgIds = messageConfig.getOrgId();
            if(null != template && (StringUtils.isNotBlank(userIds) || StringUtils.isNotBlank(orgIds))){
                //设置发送用户
                notice.setReceivers(getUserList(userIds, orgIds));
            }
        }
        //设置模板Key
        notice.setTemplateKey(messageConfig.getTplKey());
        //设置使用模板
        notice.setUseTemplate(true);
        //设置发送消息类型
        String notifyType = messageConfig.getNotifyType();
        String[] splitNotify = notifyType.split(",");
        NoticeMessageType[] noticeMessageTypes = new NoticeMessageType[splitNotify.length];
        for(int i=0,j=splitNotify.length;i<j;i++){
            noticeMessageTypes[i] = NoticeMessageType.valueOf(splitNotify[i].toUpperCase());
        }
        notice.setMessageTypes(noticeMessageTypes);
        //发送消息
        sendNotice(notice);

    }

    public String[] getUserList(String userIds, String orgIds){
        List<IUser> userList = new ArrayList<>();
        IUserService userService = AppUtil.getBean(IUserService.class);
        List<IUser> listByUser = userService.getUserByIds(userIds);
        if(null != listByUser && listByUser.size() > 0){
            userList.addAll(listByUser);
        }
        List<IUser> listByOrg = userService.getUserListByGroups("org", orgIds);
        if(null != listByOrg && listByOrg.size() > 0){
            userList.addAll(listByOrg);
        }
        String[] accounts = new String[userList.size()];
        for(int i=0,j=userList.size();i<j;i++){
            IUser iUser = userList.get(i);
            accounts[i] = iUser.getAccount();
        }
        return accounts;
    }


    public MsgTemplate getTemplate(String templateKey) {
        MsgTemplate msgTemplate = msgTemplateManager.getByKey(templateKey);
        return msgTemplate;
    }

    public MsgTemplate getDefaultTemplate(String typeKey) {
        MsgTemplate msgTemplate = msgTemplateManager.getDefault(typeKey.toLowerCase());
        if (msgTemplate == null)
            throw new RuntimeException("There is not a default msgTemplate in table.");
        return msgTemplate;
    }

    public String parseSubject(MsgTemplate templateVo, Map<String, Object> vars) {
        String subject = "";
        try {
            subject = freeMarkerEngine.parseByTemplate(templateVo.getSubject(), vars);
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(e.getMessage());
        }
        return subject;
    }

    public String parsePlainContent(MsgTemplate templateVo, Map<String, Object> vars) {
        String content = "";
        try {
            content = freeMarkerEngine.parseByTemplate(templateVo.getPlain(), vars);
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(e.getMessage());
        }
        return content;
    }

    /**
     * 转换IUser对象为JmsActor
     *
     * @param jsonNode
     * @return
     */
    public JmsActor convertUserObject2JmsActor(JsonNode jsonNode) {
        if (BeanUtils.isEmpty(jsonNode) || !jsonNode.isObject()) return null;
        ObjectNode userNode = (ObjectNode) jsonNode;
        String userId = JsonUtil.getString(userNode, "userId");
        if (StringUtil.isEmpty(userId)) {
            userId = JsonUtil.getString(userNode, "id");
        }
        String account = JsonUtil.getString(userNode, "account");
        String fullname = JsonUtil.getString(userNode, "fullname");
        String email = JsonUtil.getString(userNode, "email");
        String mobile = JsonUtil.getString(userNode, "mobile");
        String weixin = JsonUtil.getString(userNode, "weixin");
        String clientId = JsonUtil.getString(userNode, "clientId");
        String clientToken = JsonUtil.getString(userNode, "clientToken");
        return new JmsActor(userId, account, fullname, email, mobile, weixin, clientId, clientToken);
    }

    public String parseHtmlContent(MsgTemplate templateVo, Map<String, Object> vars) {
        String content = "";
        try {
            content = freeMarkerEngine.parseByTemplate(templateVo.getHtml(), vars);
        } catch (Exception e) {
            e.printStackTrace();
            logger.debug(e.getMessage());
        }
        return content;
    }

}
