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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springblade.message.MsgTemplate;
import org.springblade.message.enums.AppMsgTypeEnum;
import org.springblade.message.enums.MsgType;
import org.springblade.message.model.AppMsgInfo;
import org.springblade.message.model.AppMsgRequest;
import org.springblade.message.model.MsgResponse;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

/**
 * @author wookvn
 *
 */
@Setter
@Getter
@Slf4j
public abstract class AppMsgTemplate implements MsgTemplate {

	protected String domainHost;

	final static Cache<String, String> TOKEN_MAP = Caffeine.newBuilder().maximumSize(10).expireAfterWrite(1, TimeUnit.HOURS).build();
	
	@Override
	public MsgResponse sendAppMessage(AppMsgRequest appMsgRequest) {
		//用户ID不传递，并且也不是发送给所有人
		if(CollectionUtil.isEmpty(appMsgRequest.getPhones()) && CollectionUtil.isEmpty(appMsgRequest.getUserIds())
				&& !Optional.ofNullable(appMsgRequest.getAllUserStatus()).orElse(false)){
			return MsgResponse.failure("消息推送的用户不能为空");
		}
		AppMsgInfo appMsgInfo = appMsgRequest.getAppMsgInfo();
		if (StrUtil.isEmpty(appMsgInfo.getAppId())
				|| StrUtil.isEmpty(appMsgInfo.getAppSecret())
				|| appMsgRequest.getMsgType() == null) {
			return MsgResponse.failure("核心参数为空");
		}
		if (appMsgRequest.getFile() == null && StrUtil.isEmpty(appMsgRequest.getBody())) {
			return MsgResponse.failure("必填参数不能为空");
		}
		//设置domainHost
		this.setDomainHost(appMsgInfo.getDomainHost());
		try {
			//先从缓存取token
			String accessTokenKey = appMsgRequest.getMsgType().name() + ":" + "accessToken";
			String accessToken = TOKEN_MAP.get(accessTokenKey, key -> {
				try {
					return getAccessToken(appMsgInfo.getAppId(), appMsgInfo.getAppSecret());
				} catch (Exception e) {
					log.error(e.getMessage(), e);
					return null;
				}finally {
					log.info("[{}]|从接口中获取accessToken", appMsgRequest.getMsgType());
				}
			});
			if(StrUtil.isEmpty(accessToken)) {
				return MsgResponse.failure("AccessToken获取失败");
			}
			List<String> userIdList = new ArrayList<>();
			//根据手机号获取userids
			if(CollectionUtil.isNotEmpty(appMsgRequest.getPhones())) {
				List<String> getUserIdList = getUserIds(accessToken, appMsgRequest.getPhones());
				if(CollectionUtil.isEmpty(getUserIdList)) {
					return MsgResponse.failure("手机号未注册["+appMsgRequest.getMsgType().getMessage()+"]");
				}else {
					userIdList.addAll(getUserIdList);
				}
			}
			//userids直接使用
			if(CollectionUtil.isNotEmpty(appMsgRequest.getUserIds())){
				userIdList.addAll(appMsgRequest.getUserIds());
			}
			// 上传文件获取mediaId
			String mediaId = null; 
			if(appMsgRequest.getAppMsgType() == AppMsgTypeEnum.file) {
				mediaId = uploadFile(accessToken, appMsgRequest.getTitle(), appMsgRequest.getFile());
			}
			// 发送文件消息
			if (StrUtil.isNotEmpty(mediaId)) {
				return sendFileMessage(accessToken, userIdList, mediaId, appMsgInfo);
			}
			// 发送文本卡片消息
			if(appMsgRequest.getAppMsgType() == AppMsgTypeEnum.textcard) {
				return sendTextCardMessage(accessToken, userIdList, appMsgRequest.getTitle(), appMsgRequest.getBody(), appMsgRequest.getUrl(), appMsgRequest.getAuthRedirectUrl(), appMsgInfo);
			}else if (StrUtil.isNotEmpty(appMsgRequest.getBody())) {
				// 发送文本消息
				return sendTextMessage(accessToken, userIdList, appMsgRequest.getBody(), appMsgInfo);
			}else {
				return MsgResponse.success(500, "无效的参数");
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return MsgResponse.failure(e.getMessage());
		}
	}

	/**
	 * 获取普通AccessToken
	 * 
	 * @param key
	 * @param secret
	 * @return
	 */
	public abstract String getAccessToken(String key, String secret) throws Exception;

	/**
	 * 上传文件获取mediaId
	 * 
	 * @param accessToken
	 * @param file
	 * @return
	 */
	public abstract String uploadFile(String accessToken, String title, File file) throws Exception;

	/**
	 * 根据手机号获取userId
	 * 
	 * @param accessToken
	 * @param mobiles
	 * @return
	 */
	public abstract List<String> getUserIds(String accessToken, Collection<String> mobiles) throws Exception;

	/**
	 * 默认domainHost
	 * @return
	 */
	protected abstract String defaultDomainHost();

	/**
	 * 发送文件消息
	 * 
	 * @param appAccessToken
	 * @param userIds
	 * @param mediaId
	 * @param appMsgInfo
	 * @return
	 */
	public abstract MsgResponse sendFileMessage(String appAccessToken, List<String> userIds, String mediaId,
			AppMsgInfo appMsgInfo) throws Exception;

	/**
	 * 发送文本消息
	 * 
	 * @param appAccessToken
	 * @param userIds
	 * @param body
	 * @param appMsgInfo
	 * @return
	 */
	public MsgResponse sendTextMessage(String appAccessToken, List<String> userIds, String body, AppMsgInfo appMsgInfo)
			throws Exception {
		return null;
	}

	/**
	 * 发送文本卡片消息
	 * @param appAccessToken
	 * @param userIds
	 * @param title
	 * @param description
	 * @param url
	 * @param appMsgInfo
	 * @return
	 * @throws Exception
	 */
	public MsgResponse sendTextCardMessage(String appAccessToken, List<String> userIds,  String title, String description, String url, String authRedirectUrl, AppMsgInfo appMsgInfo) throws Exception {
		return null;
	}

	/**
	 * <p>获取domainHost地址</p>
	 * @author wookvn
	 * @datetime 2024-12-25 15:12:29
	 * @return java.lang.String
	 **/
	protected String getDomainHost() {
		String tmpDomainHost = StrUtil.removeSuffix(domainHost, "/");
		return (StrUtil.isBlank(tmpDomainHost) ? defaultDomainHost() : tmpDomainHost);
	}

	public static void main(String[] args) {
		AppMsgTemplate appMsgTemplate = new QyWechatMsgTemplate();

		AppMsgRequest appMsgRequest = new AppMsgRequest();
		appMsgRequest.setMsgType(MsgType.appQywechat);
		appMsgRequest.setAppMsgType(AppMsgTypeEnum.text);
		appMsgRequest.setAllUserStatus(true);
//		appMsgRequest.setPhones(Arrays.asList("13011223122"));
		appMsgRequest.setBody("测试给全体员工发消息");
		AppMsgInfo appMsgInfo = AppMsgInfo.builder()
				.appSecret("Bq-egV65KvoQJaHqhNHboem2c29MRZMOvjZwQkCC89g")
				.appId("ww70971991bf0840bc").agentId("1000012").build();
		appMsgRequest.setAppMsgInfo(appMsgInfo);
		MsgResponse msgResponse = appMsgTemplate.sendAppMessage(appMsgRequest);
		System.out.println(JSONUtil.toJsonPrettyStr(msgResponse));
	}
}
