package com.hotent.portal.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.hotent.base.cache.annotation.CacheEvict;
import com.hotent.base.cache.annotation.Cacheable;
import com.hotent.base.cache.annotation.FirstCache;
import com.hotent.base.constants.CacheKeyConst;
import com.hotent.base.exception.WorkFlowException;
import com.hotent.base.util.AppUtil;
import com.hotent.base.util.FluentUtil;
import com.hotent.base.util.JsonUtil;
import com.hotent.portal.params.NewsItem;
import com.hotent.portal.service.WeChatOfficialService;

@Service
public class WeChatOfficialServiceImpl implements WeChatOfficialService {
	
	 @Value("${weixin.tokenUrl:https://api.weixin.qq.com/cgi-bin/token}")
	 private String tokenUrl;
	 @Value("${weixin.materialUrl:https://api.weixin.qq.com/cgi-bin/material/batchget_material}")
	 private String materialUrl;
	 @Value("${weixin.materialcountUrl:https://api.weixin.qq.com/cgi-bin/material/get_materialcount}")
	 private String materialcountUrl;
	
	@Override
	public List<NewsItem> getMaterial(String appid,String secret,String type, int offset, int count) throws Exception {
		List<NewsItem> news = new ArrayList<NewsItem>();
		WeChatOfficialServiceImpl bean = AppUtil.getBean(getClass());
		String token = bean.getAccessToken(appid, secret);
		String curMaterialUrlUrl = materialUrl + "?access_token=" + token;
		ObjectNode params = JsonUtil.getMapper().createObjectNode();
		params.put("type", type);
		params.put("offset", offset);
		params.put("count", count>20?20:count);//接口获取素材上限为20
		//int allCount = getMaterialcount(token, "news");//获取图文总数，倒叙获取
		String result = FluentUtil.post(curMaterialUrlUrl, null, params);
		JsonNode resultNode = JsonUtil.toJsonNode(result);
		//如果token已过期，则清除缓存token，重新请求
		if(resultNode.has("errcode") && resultNode.get("errcode").asInt() == 40001) {
			this.clearAccessTokenCacheByAppId(appid);
			return getMaterial(appid, secret, type, offset, count);
		}
		if(resultNode.has("item") && resultNode.has("item_count") && resultNode.get("item_count").asInt()>0) {
			ArrayNode items = (ArrayNode) resultNode.get("item");
			for (JsonNode item : items) {
				if(item.has("content")) {
					LocalDateTime createTime = item.get("content").has("create_time")?LocalDateTime.ofEpochSecond(item.get("content").get("create_time").asLong(), 0, ZoneOffset.ofHours(8)):null;
					LocalDateTime updateTime = item.get("content").has("update_time")?LocalDateTime.ofEpochSecond(item.get("content").get("update_time").asLong(), 0, ZoneOffset.ofHours(8)):null;
					ArrayNode news_item = (ArrayNode) item.get("content").get("news_item");
					for (JsonNode node : news_item) {
						NewsItem newItem = new NewsItem();
						newItem.setTitle(node.get("title").asText(""));
						newItem.setAuthor(node.get("author").asText(""));
						newItem.setDigest(node.get("digest").asText(""));
						newItem.setContent(node.get("content").asText(""));
						newItem.setThumb_media_id(node.get("thumb_media_id").asText(""));
						newItem.setContent_source_url(node.get("content_source_url").asText(""));
						newItem.setShow_cover_pic(node.get("show_cover_pic").asInt());
						newItem.setUrl(node.get("url").asText(""));
						newItem.setNeed_open_comment(node.get("need_open_comment").asInt());
						newItem.setThumb_url(node.get("thumb_url").asText(""));
						newItem.setOnly_fans_can_comment(node.get("only_fans_can_comment").asInt());
						newItem.setCreateTime(createTime);
						newItem.setUpdateTime(updateTime);
						news.add(newItem);
					}
				}
			}
		}else {
			throw new WorkFlowException("获取微信公众号图文素材失败："+ result);
		}
		return news;
	}
	
	private int getMaterialcount(String token,String type) throws Exception {
		int count = 0;
		String curMaterialcountUrl = materialcountUrl + "?access_token=" + token;
		String result = FluentUtil.get(curMaterialcountUrl, null);
		JsonNode resultNode = JsonUtil.toJsonNode(result);
		switch (type) {
		case "news"://news_count  图文总数量
			count = resultNode.get("news_count").asInt(0);
			break;
		case "voice"://voice_count  语音总数量
			count = resultNode.get("voice_count").asInt(0);		
			break;
		case "video"://video_count  视频总数量
			count = resultNode.get("video_count").asInt(0);
			break;
		case "image"://image_count  图片总数量
			count = resultNode.get("image_count").asInt(0);
			break;
		}
		return count;
	}
	
	/**
	 * 由于微信公众号获取的access_token有效期是7200秒，这里设置缓存时间为115分钟
	 */
	@Override
    @Cacheable(value = CacheKeyConst.EIP_WEIXIN_ACCESS_TOKEN, key="#appid",
            firstCache = @FirstCache(expireTime = 115, timeUnit = TimeUnit.MINUTES))
    public String getAccessToken(String appid,String secret) throws Exception {
		String curTokenUrl = tokenUrl + "?grant_type=%s&appid=%s&secret=%s";
		curTokenUrl = String.format(curTokenUrl, "client_credential", appid, secret);
		String result = FluentUtil.get(curTokenUrl, null);
		JsonNode node = JsonUtil.toJsonNode(result);
		if(node.has("access_token")) {
			return node.get("access_token").asText();
		}else {
			throw new WorkFlowException("获取微信公众号access_token失败："+ result);
		}
    }

	@CacheEvict(value = CacheKeyConst.EIP_WEIXIN_ACCESS_TOKEN, key = "#appid")
	protected void clearAccessTokenCacheByAppId(String appid) {}

}
