/**
 * 
 */
package org.springblade.message.app;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springblade.message.model.AppMsgInfo;
import org.springblade.message.model.MsgResponse;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author wookvn
 *
 */
@Slf4j
@Component
public class QyWechatMsgTemplate extends AppMsgTemplate {

	/**
	 * 企业微信默认域名
	 */
	final static String DEFAULT_DOMAIN_HOST = "https://qyapi.weixin.qq.com";

	/**
	 * 获取access_token
	 */
	final static String GET_ACCESS_TOKEN_URL = "/cgi-bin/gettoken";
	/**
	 * 通过手机号获取其所对应的userid
	 */
	final static String GET_USERID_BY_MOBILE_URL = "/cgi-bin/user/getuserid?access_token=";
	/**
	 * 发送应用消息： https://developer.work.weixin.qq.com/document/path/90236
	 */
	final static String SEND_MESSAGE_URL = "/cgi-bin/message/send?access_token=";
	/**
	 * 上传临时素材
	 */
	final static String UPLOAD_MEDIA_URL = "/cgi-bin/media/upload?access_token=";
	/**
	 * oauth2.0授权接口
	 */
	final static String OAUTH2_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
	/**
	 * 发送消息给所有人时的固定特殊符号
	 */
	final static String ALL_USER_SYMBOL = "@all";

	@Override
	public String getAccessToken(String key, String secret) throws Exception {
		Map<String, Object> formMap = new HashMap<>();
		formMap.put("corpid", key);
		formMap.put("corpsecret", secret);
		String res = HttpUtil.createGet(getDomainHost() + GET_ACCESS_TOKEN_URL).form(formMap).execute().body();
		log.info("企业微信|获取access_token完成|res={}", res);
		JSONObject jsonObject = JSONObject.parseObject(res);
		if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
			return jsonObject.getString("access_token");
		}
		throw new RuntimeException("企业微信|获取accessToken失败|res=" + res);
	}

	@Override
	public String uploadFile(String accessToken, String title, File file) throws Exception {
		HashMap<String, Object> pMap = new HashMap<>();
		// 文件上传只需将参数中的键指定（默认file），值设为文件对象即可，对于使用者来说，文件上传与普通表单提交并无区别
		pMap.put("file", file);
		pMap.put("type", "file");
		String res = HttpUtil.post(getDomainHost() + UPLOAD_MEDIA_URL + accessToken, pMap);
		log.info("企业微信|上传文件完成|res={}", res);
		JSONObject uploadJson = JSONObject.parseObject(res);
		if (Objects.nonNull(uploadJson.get("errcode")) && uploadJson.getInteger("errcode") == 0) {
			return uploadJson.getString("media_id");
		}
		log.warn("企业微信|上传文件失败|res=" + res);
		return null;
	}

	/**
	 * 请确保手机号的正确性，若出错的次数超出企业规模人数的20%，会导致1天不可调用。
	 * https://developer.work.weixin.qq.com/document/path/95402
	 */
	@Override
	public List<String> getUserIds(String accessToken, Collection<String> mobiles) throws Exception {
		List<String> userIds = new ArrayList<>();
		for(String mobile : mobiles) {
			Map<String, Object> map = new HashMap<>();
			map.put("mobile", mobile);
			String paramMap = JSON.toJSONString(map);
			String res = HttpUtil.createPost(getDomainHost() + GET_USERID_BY_MOBILE_URL + accessToken).body(paramMap)
					.execute().body();
			log.info("企业微信|通过手机号获取userid完成|mobile={},res={}", mobile, res);
			JSONObject jsonObject = JSONObject.parseObject(res);
			if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
				userIds.add(jsonObject.getString("userid"));
			}else {
				log.info("企业微信|获取userId失败|mobile={},response={}", mobile, res);
			}
		}
		return userIds;
	}

	@Override
	public MsgResponse sendFileMessage(String appAccessToken, List<String> userIds, String mediaId, AppMsgInfo appMsgInfo)
			throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("touser", CollectionUtil.isEmpty(userIds) ? ALL_USER_SYMBOL : String.join("|", userIds));
		map.put("msgtype", "file");
		map.put("agentid", Long.parseLong(appMsgInfo.getAgentId()));
		JSONObject mediaObj = new JSONObject();
		mediaObj.put("media_id", mediaId);
		map.put("file", mediaObj);
		String paramMap = JSON.toJSONString(map);
		String res = HttpUtil.createPost(getDomainHost() + SEND_MESSAGE_URL + appAccessToken).body(paramMap).execute().body();
		log.info("企业微信|发送文件消息完成|users={},res={}", CollectionUtil.isEmpty(userIds)?"ALL":userIds.size(), res);
		JSONObject jsonObject = JSONObject.parseObject(res);
		if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
			return MsgResponse.success(200, jsonObject.getString("errmsg"));
		}
		return MsgResponse.failure("企业微信|发送文件消息失败|res=" + res);
	}
	
	@Override
	public MsgResponse sendTextMessage(String appAccessToken, List<String> userIds, String body, AppMsgInfo appMsgInfo)
			throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("touser", CollectionUtil.isEmpty(userIds) ? ALL_USER_SYMBOL : String.join("|", userIds));
		map.put("msgtype", "text");
		map.put("agentid", Long.parseLong(appMsgInfo.getAgentId()));
		JSONObject contentObj = new JSONObject();
		contentObj.put("content", body);
		map.put("text", contentObj);
		String paramMap = JSON.toJSONString(map);
		String res = HttpUtil.createPost(getDomainHost() + SEND_MESSAGE_URL + appAccessToken).body(paramMap).execute().body();
		log.info("企业微信|发送文本消息完成|users={},res={}", CollectionUtil.isEmpty(userIds)?"ALL":userIds.size(), res);
		JSONObject jsonObject = JSONObject.parseObject(res);
		if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
			return MsgResponse.success(200, jsonObject.getString("errmsg"));
		}
		return MsgResponse.failure("企业微信|发送文本消息失败|res=" + res);
	}

	@Override
	public MsgResponse sendTextCardMessage(String appAccessToken, List<String> userIds, String title, String description, String url, String authRedirectUrl, AppMsgInfo appMsgInfo) throws Exception {
		Map<String, Object> map = new HashMap<>();
		map.put("touser", CollectionUtil.isEmpty(userIds) ? ALL_USER_SYMBOL : String.join("|", userIds));
		map.put("msgtype", "textcard");
		//1表示发送给应用可见范围内的所有人（包括互联企业的成员），默认为0
		map.put("toall", "0");
		//企业应用的id，整型。可在应用的设置页面查看
		map.put("agentid", Long.parseLong(appMsgInfo.getAgentId()));
		JSONObject contentObj = new JSONObject();
		//标题，不超过128个字节，超过会自动截断
		contentObj.put("title", title);
		//描述，不超过512个字节，超过会自动截断
		contentObj.put("description", description);
		if(StrUtil.isNotBlank(authRedirectUrl)) {
			//String authRedirectUrl = "http://windata.platomix.net/api/wecom/getCode";
			String encodeAuthRedirectUrl = URLEncoder.encode(authRedirectUrl,"UTF-8");
			String encodeUrl = URLEncoder.encode(url,"UTF-8");
			String responseType = "code";
			//snsapi_privateinfo、snsapi_base-静默授权
			String scope = "snsapi_base";
			url = String.format(OAUTH2_URL + "?appid=%s&redirect_uri=%s&response_type=%s&scope=%s&state=%s&agentid=%s#wechat_redirect", appMsgInfo.getAppId(), encodeAuthRedirectUrl, responseType, scope, encodeUrl, appMsgInfo.getAgentId());
		}
		//点击后跳转的链接
		contentObj.put("url", url);
		map.put("textcard", contentObj);
		//按钮文字。 默认为“详情”， 不超过4个文字，超过自动截断。
		//map.put("btntxt", Long.parseLong(appMsgInfo.getAgentId()));
		String paramMap = JSON.toJSONString(map);
		String res = HttpUtil.createPost(getDomainHost() + SEND_MESSAGE_URL + appAccessToken).body(paramMap).execute().body();
		log.info("企业微信|发送卡片消息完成|users={},res={}", CollectionUtil.isEmpty(userIds)?"ALL":userIds.size(), res);
		JSONObject jsonObject = JSONObject.parseObject(res);
		if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
			return MsgResponse.success(200, jsonObject.getString("errmsg"));
		}
		return MsgResponse.failure("企业微信|发送卡片消息失败|res=" + res);
	}

	@Override
	protected String defaultDomainHost() {
		return DEFAULT_DOMAIN_HOST;
	}
}
