package com.cftech.base.org.api;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.cftech.base.org.model.Qyuser;
import com.cftech.base.org.service.QyuserService;
import com.cftech.core.constants.WxApiConstants;
import com.cftech.core.sql.Conds;
import com.cftech.core.util.Constants;
import com.cftech.core.util.QyTokenUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * Created by liuling on 2017/2/27.
 * 企业号消息工具
 */
@Slf4j
@Component
public class QyMsgUtil {

    private final QyTokenUtil qyTokenUtil;

    private final QyuserService qyuserService;

    @Autowired
    public QyMsgUtil(QyTokenUtil qyTokenUtil, QyuserService qyuserService) {
        this.qyTokenUtil = qyTokenUtil;
        this.qyuserService = qyuserService;
    }

    /**
     * 发送文本消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId 微信账号
     * @param sendAll    是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList 人员列表
     * @param orgUnitIds 组织列表
     * @param qytagIds   标签列表
     * @param agentId    应用的Id
     * @param content    文本内容
     * @param safe       是否保密
     * @return
     */
    public JSONObject sendText(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                               Long agentId, String content, boolean safe) {
        if (sendAll) {
            return sendTextAll(accountsId, agentId, content, safe);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }


        List<String> realArr = generateRealArr(sendList);


        retObj.put("errorNo", "0");

        //发送操作
        JSONObject contentObj = new JSONObject();
        contentObj.put("content", content);
        JSONObject postObj = generateObj(WxApiConstants.TEXT, agentId, contentObj, safe);

        JSONArray retArr = sendResult(accountsId, realArr, postObj);
        retObj.put("data", retArr);

        return retObj;
    }


    /**
     * 发送图片消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId 微信账号
     * @param sendAll    是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList 人员列表
     * @param orgUnitIds 组织列表
     * @param qytagIds   标签列表
     * @param agentId    应用的Id
     * @param mediaId    图片媒体文件id，可以调用上传临时素材或者永久素材接口获取,永久素材media_id必须由发消息的应用创建
     * @param safe       是否保密
     * @return
     */
    public JSONObject sendImage(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                                Long agentId, String mediaId, boolean safe) {
        if (sendAll) {
            return sendImageAll(accountsId, agentId, mediaId, safe);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }

        List<String> realArr = generateRealArr(sendList);

        retObj.put("errorNo", "0");

        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.IMAGE, agentId, contentObj, safe);
        JSONArray retArr = sendResult(accountsId, realArr, postObj);

        retObj.put("data", retArr);

        return retObj;
    }

    /**
     * 发送声音消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId 微信账号
     * @param sendAll    是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList 人员列表
     * @param orgUnitIds 组织列表
     * @param qytagIds   标签列表
     * @param agentId    应用的Id
     * @param mediaId    语音文件id，可以调用上传临时素材或者永久素材接口获取
     * @param safe       是否保密
     * @return
     */
    public JSONObject sendVoice(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                                Long agentId, String mediaId, boolean safe) {
        if (sendAll) {
            return sendVoiceAll(accountsId, agentId, mediaId, safe);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }

        List<String> realArr = generateRealArr(sendList);

        retObj.put("errorNo", "0");

        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.VOICE, agentId, contentObj, safe);
        JSONArray retArr = sendResult(accountsId, realArr, postObj);

        retObj.put("data", retArr);

        return retObj;
    }

    /**
     * 发送文件消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId 微信账号
     * @param sendAll    是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList 人员列表
     * @param orgUnitIds 组织列表
     * @param qytagIds   标签列表
     * @param agentId    应用的Id
     * @param mediaId    语音文件id，可以调用上传临时素材或者永久素材接口获取
     * @param safe       是否保密
     * @return
     */
    public JSONObject sendFile(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                               Long agentId, String mediaId, boolean safe) {
        if (sendAll) {
            return sendFileAll(accountsId, agentId, mediaId, safe);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }

        List<String> realArr = generateRealArr(sendList);

        retObj.put("errorNo", "0");

        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.FILE, agentId, contentObj, safe);
        JSONArray retArr = sendResult(accountsId, realArr, postObj);

        retObj.put("data", retArr);

        return retObj;
    }

    /**
     * 发送图文消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId 微信账号
     * @param sendAll    是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList 人员列表
     * @param orgUnitIds 组织列表
     * @param qytagIds   标签列表
     * @param agentId    应用的Id
     * @param articles   List<QyArticle>,图文列表
     * @return
     */
    public JSONObject sendNews(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                               Long agentId, List<QyArticle> articles) {
        if (sendAll) {
            return sendNewAll(accountsId, agentId, articles);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }

        List<String> realArr = generateRealArr(sendList);

        retObj.put("errorNo", "0");
        JSONObject articleObj = new JSONObject();

        JSONArray articleArr = new JSONArray();
        for (QyArticle article : articles) {
            JSONObject tmpObj = new JSONObject();
            tmpObj.put("title", article.getTitle());
            tmpObj.put("description", article.getDescription());
            tmpObj.put("url", article.getUrl());
            tmpObj.put("picurl", article.getPicurl());
            articleArr.add(tmpObj);
        }
        articleObj.put("articles", articleArr);
        JSONObject postObj = generateNoSafeObj(WxApiConstants.NEWS, agentId, articleObj);

        JSONArray retArr = sendResult(accountsId, realArr, postObj);

        retObj.put("data", retArr);

        return retObj;
    }


    /**
     * * 发送视频消息，需要用Set去重，并记录哪些是发送失败的
     *
     * @param accountsId  微信账号
     * @param sendAll     是否发送给所有人，如果是则忽略人员列表，部门列表和标签列表
     * @param qyuserList  人员列表
     * @param orgUnitIds  组织列表
     * @param qytagIds    标签列表
     * @param agentId     应用的Id
     * @param title       视频的标题
     * @param description 视频的描述
     * @param mediaId     视频文件id，可以调用上传临时素材或者永久素材接口获取
     * @param safe        是否保密
     * @return
     */
    public JSONObject sendVideo(Long accountsId, boolean sendAll, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds,
                                Long agentId, String title, String description, String mediaId, boolean safe) {
        if (sendAll) {
            return sendVideoAll(accountsId, agentId, title, description, mediaId, safe);
        }
        //返回结果
        JSONObject retObj = new JSONObject();
        //待发送的人员列表Set
        Set<String> sendList = generateUsers(accountsId, qyuserList, orgUnitIds, qytagIds);
        if (sendList.size() == 0) {
            retObj.put("errorNo", "1");
            retObj.put("errorMsg", "not found send users");
            return retObj;
        }

        List<String> realArr = generateRealArr(sendList);

        retObj.put("errorNo", "0");

        JSONObject contentObj = new JSONObject();
        contentObj.put("title", title);
        contentObj.put("description", description);
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.VIDEO, agentId, contentObj, safe);
        JSONArray retArr = sendResult(accountsId, realArr, postObj);

        retObj.put("data", retArr);

        return retObj;
    }

    public JSONArray sendResult(Long accountsId, List<String> realArr, JSONObject postObj) {
        JSONArray retArr = new JSONArray();
        //发送操作
        int zs = 0;
        for (String userids : realArr) {

            zs++;
            if (zs % 900 == 0) {
                try {
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    // 发送信息
                    e.printStackTrace();
                }
            }


            postObj.put("touser", userids);

            JSONObject entryObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
            log.info("accountsId={}, send message result: {}", accountsId, entryObj.toJSONString());
            retArr.add(entryObj);
        }

        return retArr;
    }

    /**
     * 创建交互的postJSON
     *
     * @param msgtype
     * @param agentId
     * @param contentObj
     * @param safe
     * @return
     */
    public static JSONObject generateObj(String msgtype, Long agentId, JSONObject contentObj, boolean safe) {
        JSONObject postObj = new JSONObject();
        postObj.put("agentid", agentId);
        postObj.put("msgtype", msgtype);
        postObj.put("safe", safe ? 1 : 0);
        postObj.put(msgtype, contentObj);

        return postObj;
    }

    public static JSONObject generateNoSafeObj(String msgtype, Long agentId, JSONObject contentObj) {
        JSONObject postObj = new JSONObject();
        postObj.put("agentid", agentId);
        postObj.put("msgtype", msgtype);
        postObj.put(msgtype, contentObj);

        return postObj;
    }

    /**
     * 发送所有人文本消息
     *
     * @param accountsId
     * @param agentId
     * @param content
     * @param safe
     * @return
     */
    public JSONObject sendTextAll(Long accountsId, Long agentId, String content, boolean safe) {
        JSONObject contentObj = new JSONObject();
        contentObj.put("content", content);
        JSONObject postObj = generateObj(WxApiConstants.TEXT, agentId, contentObj, safe);
        postObj.put("touser", "@all");

        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendTextAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 发送所有人图文消息
     *
     * @param accountsId
     * @param agentId
     * @param articles
     * @return
     */
    private JSONObject sendNewAll(Long accountsId, Long agentId, List<QyArticle> articles) {
        JSONObject articleObj = new JSONObject();

        JSONArray articleArr = new JSONArray();
        for (QyArticle article : articles) {
            JSONObject tmpObj = new JSONObject();
            tmpObj.put("title", article.getTitle());
            tmpObj.put("description", article.getDescription());
            tmpObj.put("url", article.getUrl());
            tmpObj.put("picurl", article.getPicurl());
            articleArr.add(tmpObj);
        }
        articleObj.put("articles", articleArr);
        JSONObject postObj = generateNoSafeObj(WxApiConstants.NEWS, agentId, articleObj);
        postObj.put("touser", "@all");
        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendNewAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 发送所有人视频消息
     *
     * @param accountsId
     * @param agentId
     * @param title       视频主题
     * @param description 视频消息的描述
     * @param mediaId
     * @param safe
     * @return
     */
    public JSONObject sendVideoAll(Long accountsId, Long agentId, String title, String description, String mediaId, boolean safe) {
        JSONObject contentObj = new JSONObject();
        contentObj.put("title", title);
        contentObj.put("description", description);
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.VIDEO, agentId, contentObj, safe);
        postObj.put("touser", "@all");

        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendVideoAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 发送所有人文件消息
     *
     * @param accountsId
     * @param agentId
     * @param mediaId
     * @param safe
     * @return
     */
    public JSONObject sendFileAll(Long accountsId, Long agentId, String mediaId, boolean safe) {
        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.FILE, agentId, contentObj, safe);
        postObj.put("touser", "@all");

        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendFileAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 发送所有人图片消息
     *
     * @param accountsId
     * @param agentId
     * @param mediaId
     * @param safe
     * @return
     */
    public JSONObject sendImageAll(Long accountsId, Long agentId, String mediaId, boolean safe) {
        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.IMAGE, agentId, contentObj, safe);
        postObj.put("touser", "@all");

        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendImageAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 发送所有人声音消息
     *
     * @param accountsId
     * @param agentId
     * @param mediaId
     * @param safe
     * @return
     */
    public JSONObject sendVoiceAll(Long accountsId, Long agentId, String mediaId, boolean safe) {
        JSONObject contentObj = new JSONObject();
        contentObj.put("media_id", mediaId);
        JSONObject postObj = generateObj(WxApiConstants.VOICE, agentId, contentObj, safe);
        postObj.put("touser", "@all");

        JSONObject retObj = WxApiUtils.sendMessage(qyTokenUtil.getToken(accountsId), postObj);
        log.info("accountsId={}, sendVoiceAll result: {}", accountsId, retObj.toJSONString());
        return retObj;
    }

    /**
     * 获取所有的待发送人员Set
     *
     * @param accountsId
     * @param qyuserList
     * @param orgUnitIds
     * @param qytagIds
     * @return
     */
    public Set<String> generateUsers(Long accountsId, List<Qyuser> qyuserList, String[] orgUnitIds, String[] qytagIds) {
        //待发送列表
        Set<String> sendList = new HashSet<>();
        //人员列表
        if (qyuserList != null && qyuserList.size() > 0) {
            for (Qyuser qyuser : qyuserList) {
                sendList.add(qyuser.getWxuserId());
            }
        }

        //组织列表
        if (orgUnitIds != null && orgUnitIds.length > 0) {
            Conds conds = new Conds();
            conds.equal("accounts_id", accountsId);
            conds.equal("del_flag", Constants.DEL_FLAG_0);
            conds.in("org_id", orgUnitIds);
            List<Qyuser> orgUsersList = qyuserService.fetchSearchByPage(conds, null, 0, 0);
            if (orgUsersList != null && orgUsersList.size() > 0) {
                for (Qyuser qyuser : orgUsersList) {
                    sendList.add(qyuser.getWxuserId());
                }
            }
        }

        //标签列表
        if (qytagIds != null && qytagIds.length > 0) {
            StringBuffer regexp = new StringBuffer();
            for (String str : qytagIds) {
                regexp.append("(^|,)");
                regexp.append(str);
                regexp.append("($|,)");
            }

            List<Qyuser> tagUsersList = qyuserService.findUsersByTagIds(accountsId, "0", regexp.toString());
            if (tagUsersList != null && tagUsersList.size() > 0) {
                for (Qyuser qyuser : tagUsersList) {
                    sendList.add(qyuser.getWxuserId());
                }
            }
        }

        return sendList;
    }

    /**
     * 处理成900一次的人员发送列表
     *
     * @param sendList
     * @return
     */
    public static List<String> generateRealArr(Set<String> sendList) {
        List<String> realArr = Lists.newArrayList();
        //转成ArrayList
        String[] sendListArr = sendList.toArray(new String[]{});
        //每次发送900人
        int MAX_COUNT = 900;
        StringBuffer sb = new StringBuffer();
        for (int i = 0, j = sendListArr.length; i < j; i++) {
            if (i % MAX_COUNT == 0) {
                sb.append(sendListArr[i]);
                realArr.add(sb.toString());
                sb = new StringBuffer();
            } else {
                sb.append(sendListArr[i] + "|");
            }
        }
        if (sb.length() > 0) {
            realArr.add(sb.toString().substring(0, sb.toString().length() - 1));
        }

        return realArr;
    }
}