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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
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.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * @author wookvn
 *
 */
@Slf4j
@Component
@SuppressWarnings("unchecked")
public class FeishuMsgTemplate extends AppMsgTemplate {

	final static String DEFAULT_DOMAIN_HOST = "https://open.feishu.cn";

	// 获取access_token
	final static String GET_ACCESS_TOKEN_URL = "/open-apis/auth/v3/tenant_access_token/internal";
	// 通过手机号获取其所对应的userid
	final static String GET_USERID_BY_MOBILE_URL = "/open-apis/contact/v3/users/batch_get_id";
	// 发送应用消息
	final static String SEND_MESSAGE_URL = "/open-apis/im/v1/messages?receive_id_type=user_id";
	// 批量发送应用消息
	final static String BATCH_SEND_MESSAGE_URL = "/open-apis/message/v4/batch_send/";
	// 上传临时素材
	final static String UPLOAD_MEDIA_URL = "/open-apis/im/v1/files";

	@Override
	public String getAccessToken(String key, String secret) throws Exception{
		Map<String, String> tenantAccessTokenMap = new HashMap<>();
		tenantAccessTokenMap.put("app_id", key);
		tenantAccessTokenMap.put("app_secret", secret);
		String paramMap = JSON.toJSONString(tenantAccessTokenMap);
		Map<String, String> headers = new HashMap<>();
		headers.put("Content-Type", "application/json; charset=utf-8");
		String res = HttpUtil.createPost(getDomainHost() + GET_ACCESS_TOKEN_URL).body(paramMap).headerMap(headers, true).execute().body();
		log.info("飞书|获取access_token完成|res={}", res);
		Map<String, Object> tenantMaps = JSON.parseObject(res, Map.class);
		if ("0".equals(tenantMaps.get("code").toString()) && tenantMaps.containsKey("tenant_access_token")) {
			return tenantMaps.get("tenant_access_token").toString();
		}
		throw new RuntimeException("飞书|获取accessToken失败|res=" + res);
	}

	@Override
	public String uploadFile(String accessToken, String title, File file) throws Exception{
		Map<String, String> headers = new HashMap<>();
		headers.put("Authorization", "Bearer " + accessToken);
		headers.put("Content-Type", "multipart/form-data");
		String res = HttpRequest.post(getDomainHost() + UPLOAD_MEDIA_URL).headerMap(headers, true)
				.form("file", file, title).form("file_type", "pdf").form("file_name", title + ".pdf").execute().body();
		log.info("飞书|上传文件完成|res={}", res);
		Map<String, Object> resMap = JSON.parseObject(res, Map.class);
		if ("0".equals(resMap.get("code").toString())) {
			JSONObject data = JSON.parseObject(resMap.get("data").toString(), JSONObject.class);
			return data.getString("file_key");
		}
		log.warn("飞书|上传文件失败|res=" + res);
		return null;
	}

	@Override
	public List<String> getUserIds(String accessToken, Collection<String> mobiles) throws Exception  {
		Map<String, Collection<String>> map = new HashMap<>();
		map.put("mobiles", mobiles);
		String paramMap = JSON.toJSONString(map);
		Map<String, String> headers = new HashMap<>();
		headers.put("Authorization", "Bearer " + accessToken);
		headers.put("Content-Type", "application/json; charset=utf-8");
		String res = HttpUtil.createPost(getDomainHost() + GET_USERID_BY_MOBILE_URL + "?user_id_type=user_id").body(paramMap)
				.headerMap(headers, true).execute().body();
		log.info("飞书|通过手机号获取userids完成|mobiles={},res={}", JSONUtil.toJsonStr(mobiles), res);
		Map<String, Object> resMap = JSON.parseObject(res, Map.class);
		List<String> userIds = new ArrayList<>();
		if ("0".equals(resMap.get("code").toString())) {
			JSONObject data = JSON.parseObject(resMap.get("data").toString(), JSONObject.class);
			JSONArray userList = data.getJSONArray("user_list");
			if(userList != null) {
				IntStream.range(0, userList.size()).mapToObj(i -> userList.getJSONObject(i).getString("user_id")).forEach(userIds::add);
			}
		}else {
			log.info("飞书|获取userId失败|mobiles={},response={}", String.join(",", mobiles), res);
		}
		return userIds;
	}

	@Override
	public MsgResponse sendFileMessage(String appAccessToken, List<String> userIds, String mediaId, AppMsgInfo appMsgInfo) {
		if(CollectionUtil.isEmpty(userIds)) {
			return MsgResponse.failure("飞书不支持发送给所有人");
		}
		// 发送飞书消息
		int failCount = 0;
		for(String userId : userIds) {
			Map<String, String> headers = new HashMap<>();
			headers.put("Authorization", "Bearer " + appAccessToken);
			headers.put("Content-Type", "application/json; charset=utf-8");

			Map<String, Object> paraMap = new HashMap<>();
			paraMap.put("receive_id", userId);
			paraMap.put("msg_type", "file");
			JSONObject contentObject = new JSONObject();
			contentObject.put("file_key", mediaId);
			paraMap.put("content", contentObject);
			
			String paramMapStr = JSON.toJSONString(paraMap);
			String res = HttpUtil.createPost(getDomainHost() + SEND_MESSAGE_URL).body(paramMapStr).headerMap(headers, true).execute().body();
			log.info("飞书|发送文件消息完成|userId={},res={}", userId, res);
			Map<String, Object> resMap = JSON.parseObject(res, Map.class);
			if(!"ok".equals(resMap.get("msg").toString())) {
				log.warn("飞书|发送文件消息失败|userId=" + userId);
				failCount++;
			}
		}
		return MsgResponse.success(200, String.format("发送完成|成功%s个,失败%s个", userIds.size() - failCount, failCount));
	}

	@Override
	public MsgResponse sendTextMessage(String appAccessToken, List<String> userIds, String body, AppMsgInfo appMsgInfo)
			throws Exception {
		if(CollectionUtil.isEmpty(userIds)) {
			return MsgResponse.failure("飞书不支持发送给所有人");
		}
		Map<String, String> headers = new HashMap<>();
		headers.put("Authorization", "Bearer " + appAccessToken);
		headers.put("Content-Type", "application/json; charset=utf-8");

		Map<String, Object> paraMap = new HashMap<>();
		paraMap.put("user_ids", userIds);
		paraMap.put("msg_type", "text");
		JSONObject contentObject = new JSONObject();
		contentObject.put("text", body);
		paraMap.put("content", contentObject);
		String paramMapStr = JSON.toJSONString(paraMap);
		String res = HttpUtil.createPost(getDomainHost() + BATCH_SEND_MESSAGE_URL).body(paramMapStr).headerMap(headers, true).execute().body();
		log.info("飞书|发送文本消息完成|res="+res);
		Map<String, Object> resMap = JSON.parseObject(res, Map.class);
		if("ok".equals(resMap.get("msg").toString())) {
			return MsgResponse.success(200, resMap.get("msg").toString());
		}
		return MsgResponse.failure("飞书|发送文本消息失败|res=" + res);
	}

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

}
