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

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import org.springblade.message.model.AppMsgInfo;
import org.springblade.message.model.MsgResponse;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson2.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiMediaUploadRequest;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiMediaUploadResponse;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
import com.taobao.api.FileItem;

import lombok.extern.slf4j.Slf4j;

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

	final static String DEFAULT_DOMAIN_HOST = "https://oapi.dingtalk.com";

	// 获取access_token
	final static String GET_ACCESS_TOKEN_URL = "/gettoken";
	// 通过手机号获取其所对应的userid
	final static String GET_USERID_BY_MOBILE_URL = "/topapi/v2/user/getbymobile";
	// 发送应用消息
	final static String SEND_MESSAGE_URL = "/topapi/message/corpconversation/asyncsend_v2";
	// 上传临时素材
	final static String UPLOAD_MEDIA_URL = "/media/upload";

	@Override
	public String getAccessToken(String key, String secret) throws Exception {
		DingTalkClient client = new DefaultDingTalkClient(getDomainHost() + GET_ACCESS_TOKEN_URL);
		OapiGettokenRequest request = new OapiGettokenRequest();
		request.setAppkey(key);
		request.setAppsecret(secret);
		request.setHttpMethod("GET");
		OapiGettokenResponse response = client.execute(request);
		JSONObject jsonObject = JSONObject.parseObject(response.getBody());
		log.info("钉钉|获取access_token完成|res={}", jsonObject);
		if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
			return jsonObject.getString("access_token");
		}
		throw new RuntimeException("钉钉|获取accessToken失败|res=" + response.getBody());
	}

	@Override
	public List<String> getUserIds(String accessToken, Collection<String> mobiles) throws Exception  {
		List<String> userIds = new ArrayList<>();
		for(String mobile : mobiles) {
			DingTalkClient client = new DefaultDingTalkClient(getDomainHost() + GET_USERID_BY_MOBILE_URL);
			OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
			req.setMobile(mobile);
			OapiV2UserGetbymobileResponse rsp = client.execute(req, accessToken);
			JSONObject jsonObject = JSONObject.parseObject(rsp.getBody());
			log.info("钉钉|通过手机号转userid完成|res={}", jsonObject);
			if (Objects.nonNull(jsonObject.get("errcode")) && jsonObject.getInteger("errcode") == 0) {
				userIds.add(jsonObject.getJSONObject("result").getString("userid"));
			}else {
				log.info("钉钉|获取userId失败|mobile={},response={}", mobile, rsp.getBody());
			}
		}
		return userIds;
	}

	@Override
	public String uploadFile(String accessToken, String title, File file) throws Exception {
		DingTalkClient client = new DefaultDingTalkClient(getDomainHost() + UPLOAD_MEDIA_URL);
		OapiMediaUploadRequest req = new OapiMediaUploadRequest();
		// type image：图片 voice：语音 file：普通文件例如word、excel文件
		req.setType("file");
		req.setMedia(new FileItem(file));
		OapiMediaUploadResponse response = client.execute(req, accessToken);
		log.info("钉钉|上传文件完成|res={}", response.getBody());
		if (0 != response.getErrcode()) {
			log.warn("钉钉|上传文件失败|res=" + response.getErrmsg());
			return null;
		}
		return response.getMediaId();
	}

	@Override
	public MsgResponse sendFileMessage(String appAccessToken, List<String> userIds, String mediaId,
			AppMsgInfo appMsgInfo) throws Exception {
		// 发送钉钉消息
		DingTalkClient client = new DefaultDingTalkClient(getDomainHost() + SEND_MESSAGE_URL);
		OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
		request.setAgentId(Long.valueOf(appMsgInfo.getAgentId()));
		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		msg.setMsgtype("file");
		OapiMessageCorpconversationAsyncsendV2Request.File file = new OapiMessageCorpconversationAsyncsendV2Request.File();
		file.setMediaId(mediaId);
		msg.setFile(file);
		request.setMsg(msg);
		if(CollectionUtil.isEmpty(userIds)) {
			request.setToAllUser(true);
		}else {
			request.setUseridList(String.join(",", userIds));
			request.setToAllUser(false);
		}
		OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, appAccessToken);
		log.info("钉钉|发送文件消息完成|users={},res={}", CollectionUtil.isEmpty(userIds)?"ALL":userIds.size(), response.getBody());
		if (0 != response.getErrcode()) {
			return MsgResponse.failure("钉钉|发送文件消息失败|res=" + response.getErrmsg());
		}
		return MsgResponse.success(200, "发送成功");
	}

	@Override
	public MsgResponse sendTextMessage(String appAccessToken, List<String> userIds, String body, AppMsgInfo appMsgInfo)
			throws Exception {
		// 发送钉钉消息
		DingTalkClient client = new DefaultDingTalkClient(getDomainHost() + SEND_MESSAGE_URL);
		OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
		request.setAgentId(Long.valueOf(appMsgInfo.getAgentId()));
		OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
		msg.setMsgtype("text");
		OapiMessageCorpconversationAsyncsendV2Request.Text text = new OapiMessageCorpconversationAsyncsendV2Request.Text();
		text.setContent(body);
		msg.setText(text);
		request.setMsg(msg);
		if(CollectionUtil.isEmpty(userIds)) {
			request.setToAllUser(true);
		}else {
			request.setUseridList(String.join(",", userIds));
			request.setToAllUser(false);
		}
		OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, appAccessToken);
		log.info("钉钉|发送文本消息完成|users={},res={}", CollectionUtil.isEmpty(userIds)?"ALL":userIds.size(), response.getBody());
		if (0 != response.getErrcode()) {
			return MsgResponse.failure("钉钉|发送文本消息失败|res=" + response.getErrmsg());
		}
		return MsgResponse.success(200, "发送成功");
	}

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