package com.jpsoft.shinestar.modules.common.utils;

import cn.hutool.core.date.DateTime;
import com.jpsoft.shinestar.modules.wechat.entity.AccessToken;
import com.jpsoft.shinestar.modules.wechat.vo.UserInfo;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.Collectors;

/**
 * 公众平台通用接口工具类
 *
 * @author lt
 * @date 2013-08-09
 */
public class WeixinUtil {
	private static Logger log = LoggerFactory.getLogger(WeixinUtil.class);

	// 获取access_token的接口地址（GET） 限200（次/天），可以在配置文件中修改
	public static String access_token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

	//获取微信的code
	public static String code = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
	public static String getCodeRequest(String appid, String url,String scope){
        String result = null;
        String url_encode = "";
        try {
			url_encode = java.net.URLEncoder.encode(url, "utf-8");
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        result  = code.replace("APPID", appid).replace("REDIRECT_URI",url_encode).replace("SCOPE", scope);
        return result;
    }

	//通过code换取网页授权access_token
	public static String accessTokenurl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
	public static AccessToken getAccessToken(String appid, String appsecret,String code) throws Exception {
        AccessToken accessToken = null;
        String formatUrl = accessTokenurl.replace("APPID", appid).replace("SECRET",appsecret).replace("CODE", code);
        JSONObject json  = HttpConnectionUtil.httpRequest(formatUrl, "GET", null);
        if (!json.isNullObject() && !json.isEmpty()) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(json.getString("access_token"));
				accessToken.setExpiresIn(json.getInt("expires_in"));
				accessToken.setOpenid(json.getString("openid"));
				accessToken.setScope(json.getString("scope"));
			} catch (Exception e) {

				// 获取token失败
				log.error("获取token失败,返回结果result={}", json);
				if (json.getString("errcode").equals("40163")){
					throw new Exception("请重新扫码");

				}

			}
		}
        return accessToken;
    }

	public static String jsAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
	public static String getJsAPI(String accessToken){
		String formatUrl = jsAccessTokenUrl.replace("ACCESS_TOKEN", accessToken);
        JSONObject json  = HttpConnectionUtil.httpRequest(formatUrl, "GET", null);

        if (!json.isNullObject() && !json.isEmpty()) {
			try {
				return json.getString("ticket");
			} catch (Exception e) {
				// 获取token失败
				log.error("获取jsAPI失败,返回结果result={}", json);
			}
		}

        return null;
	}

	/**
	 * 获取access_token
	 *
	 * @param appid 凭证
	 * @param appsecret 密钥
	 * @return
	 */
	public static AccessToken getAccessToken(String appid, String appsecret) {
		AccessToken accessToken = null;

		String requestUrl = access_token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
		JSONObject jsonObject =HttpConnectionUtil.httpRequest(requestUrl, "GET", null);
		// 如果请求成功
		if (null != jsonObject) {
			try {
				accessToken = new AccessToken();
				accessToken.setToken(jsonObject.getString("access_token"));
				accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
				//accessToken.setOpenid(jsonObject.getString("openid"));
			} catch (JSONException e) {
				accessToken = null;
				// 获取token失败
				log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
			}
		}
		return accessToken;
	}

	// 获取用户信息
	public static String user_info_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
	public static String subscribe_user_info_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN ";

	public static UserInfo getUserInfo(String openid, String accessToken) {
		// 拼装url
		String url = user_info_url.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);;

		JSONObject jsonObject = HttpConnectionUtil.httpRequest(url, "GET", null);

		UserInfo userInfo = null;
		 if (null != jsonObject) {
				try {
					userInfo = new UserInfo();
					userInfo.setOpenid(jsonObject.getString("openid").replaceAll("\"", ""));

					userInfo.setNickname(jsonObject.getString("nickname").replaceAll("\"", ""));
					userInfo.setCity(jsonObject.getString("city").replaceAll("\"", ""));
					userInfo.setProvince(jsonObject.getString("province").replaceAll("\"", ""));
					userInfo.setCountry(jsonObject.getString("country").replaceAll("\"", ""));
					userInfo.setHeadimgurl(jsonObject.getString("headimgurl").replaceAll("\"", ""));
				} catch (JSONException e) {
					// 获取token失败
					log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
				}
			}
		return userInfo;
	}

	public static boolean checkSignature(String token,String signature, String timestamp, String nonce) {
		String[] arr = new String[] { token, timestamp, nonce };

		String content = Arrays.stream(arr)
				.sorted(Comparator.naturalOrder())
				.collect(Collectors.joining());

		MessageDigest md = null;
		String tmpStr = null;

		try {
			md = MessageDigest.getInstance("SHA-1");
			// 将三个参数字符串拼接成一个字符串进行sha1加密
			byte[] digest = md.digest(content.getBytes("UTF-8"));

			StringBuffer hexstr = new StringBuffer();

			String shaHex = "";

			for (int i = 0; i < digest.length; i++) {
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexstr.append(0);
				}
				hexstr.append(shaHex);
			}

			tmpStr = hexstr.toString();
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 将sha1加密后的字符串可与signature对比，标识该请求来源于微信
		return signature.equals(tmpStr);
	}

	public static cn.hutool.json.JSONObject xmlToJson(ServletInputStream inputStream) throws Exception {
		cn.hutool.json.JSONObject jsonObject = new cn.hutool.json.JSONObject();

		// 创建sax解析工厂
		SAXParserFactory factory = SAXParserFactory.newInstance();
		// 创建sax转换工具
		SAXParser saxParser = factory.newSAXParser();

		saxParser.parse(inputStream,new DefaultHandler(){
			private String tagName;

			@Override
			public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
				tagName = qName;
			}

			@Override
			public void endElement(String uri, String localName, String qName) throws SAXException {
				tagName = null;
			}

			@Override
			public void characters(char[] ch, int start, int length) throws SAXException {
				if(tagName!=null){
					String content = new String(ch,start,length);
					jsonObject.put(tagName,content);
				}
			}
		});

		return jsonObject;
	}
	public static void replyTextMessage(HttpServletResponse response, String fromUserName, String toUserName, String content){
		StringBuilder sb = new StringBuilder();

		sb.append("<xml>");
		sb.append("<ToUserName><![CDATA[" + toUserName + "]]></ToUserName>");
		sb.append("<FromUserName><![CDATA["+ fromUserName + "]]></FromUserName>");
		sb.append("<CreateTime>" + DateTime.now().getTime() + "</CreateTime>");
		sb.append("<MsgType><![CDATA[text]]></MsgType>");
		sb.append("<Content><![CDATA[" + content + "]]></Content>");
		sb.append("</xml>");

		try {
			response.getWriter().print(sb.toString());
			response.getWriter().close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void replyArticlesMessage(HttpServletResponse response, String fromUserName, String toUserName, String title,String description,String picurl,String url){
		StringBuilder sb = new StringBuilder();
		sb.append("<xml>");
		sb.append("<ToUserName><![CDATA[" + toUserName + "]]></ToUserName>");
		sb.append("<FromUserName><![CDATA["+ fromUserName + "]]></FromUserName>");
		sb.append("<CreateTime>" + DateTime.now().getTime() + "</CreateTime>");
		sb.append("<MsgType><![CDATA[news]]></MsgType>");
		sb.append("<ArticleCount>" + 1 + "</ArticleCount>");
		sb.append("<Articles>");
		sb.append("<item>");
		sb.append("<Title><![CDATA["+title+"]]></Title> ");
		sb.append("<Description><![CDATA["+description+"]]></Description>");
		sb.append("<PicUrl><![CDATA["+picurl+"]]></PicUrl>");
		sb.append("<Url><![CDATA["+url+"]]></Url>");
		sb.append("</item>");
		sb.append("</Articles>");
		sb.append("</xml>");

		try {
			response.getWriter().print(sb.toString());
			response.getWriter().close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}


	/**
	 * 创建微信菜单
	 * @param appid
	 * @param appSecret
	 * @return
	 */
	public static String createMenu(String appid,String appSecret){
		AccessToken token = WeixinUtil.getAccessToken(appid, appSecret);

		System.out.println(token.getToken());

		JSONObject data = new JSONObject();
		JSONArray buttonArray = new JSONArray();

		JSONObject button1 = new JSONObject();
		button1.put("type", "view");
		button1.put("name", "疫情监管");
		button1.put("url", "http://wisdomhousewechat.sudaonline.net/prevention/");
		buttonArray.add(button1);

		JSONObject button2 = new JSONObject();
		button2.put("type","view");
		button2.put("name","智慧物业");
		button2.put("url","http://wisdomhousewechat.sudaonline.net/#/home/?id=1");
		buttonArray.add(button2);

		JSONObject button3 = new JSONObject();
		button3.put("type","click");
		button3.put("name","关于系统");
		button3.put("key","文章");
		buttonArray.add(button3);

		data.put("button", buttonArray);
		data.put("action_name", "QR_LIMIT_STR_SCENE");

		JSONObject actionInfo = new JSONObject();
		JSONObject scene = new JSONObject();

		scene.put("scene_str", "6");

		actionInfo.put("scene", scene);

		data.put("action_info", actionInfo);
		System.out.println(data.toString());
		//创建菜单
		String result = HttpConnectionUtil.getHttpContentByPost(" https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" + token.getToken(), "utf-8", data.toString());

		return result;
	}
}
