package cn.wise.sc.cement.business.util;

import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.Set;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.impl.DefaultClaims;

/**
 * 通过 jwt 生成token 及 验证
 *
 * @author ztw
 */
public class JwtUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(JwtUtil.class);

	private static final String SECRET_KEY = "_MeD5CiNov0_TecH";

	/**
	 * 签名算法
	 */
	private static final SignatureAlgorithm DEFAULTSIGN = SignatureAlgorithm.HS256;

	/**
	 * 根据用户信息生成 token
	 *
	 * @return
	 */
	public static String createToken(Integer id, String username, String name, String
			phone) {
		Claims claim = new DefaultClaims();
		// 设置 签发人
		long timeStamp = (new Date()).getTime();
		claim.setIssuer("cement");
		claim.put("id", id);
		claim.put("username", username);
		claim.put("name", name);
		claim.put("phone", phone);
		claim.put("timeStamp", timeStamp);
		Key signingKey = getKey(SECRET_KEY, DEFAULTSIGN.getJcaName());
		JwtBuilder builder = Jwts.builder().setClaims(claim).signWith(DEFAULTSIGN, signingKey);
		return builder.compact();
	}

	/**
	 * 根据 params 生成 token
	 *
	 * @return
	 */
	public static String createToken(JSONObject params) {
		Claims claim = new DefaultClaims();
		// 设置 签发人
		long timeStamp = (new Date()).getTime();
		claim.setIssuer("cement");
		Set<String> keys = params.keySet();
		for (String key : keys) {
			claim.put(key, params.getString(key));
		}
		claim.put("timeStamp", timeStamp);
		Key signingKey = getKey(SECRET_KEY, DEFAULTSIGN.getJcaName());
		JwtBuilder builder = Jwts.builder().setClaims(claim).signWith(DEFAULTSIGN, signingKey);
		return builder.compact();
	}

	/**
	 * 根据 userId 生成 token
	 *
	 * @param userId
	 * @return
	 */
	public static String createToken(String userId) {
		Claims claim = new DefaultClaims();
		// claim.setAudience("www.bizconf.cn");// 设置接收方
		// 设置 签发人
		long timeStamp = (new Date()).getTime();
		claim.setIssuer("goldwind");
		claim.put("userId", userId);
		claim.put("timeStamp", timeStamp);
		Key signingKey = getKey(SECRET_KEY, DEFAULTSIGN.getJcaName());
		JwtBuilder builder = Jwts.builder().setClaims(claim).signWith(DEFAULTSIGN, signingKey);
		return builder.compact();
	}

	/**
	 * 该方法使用 HS256 算法和 Secret: 生成signKey
	 *
	 * @param key
	 * @param jcaName
	 * @return
	 */
	private static Key getKey(String key, String jcaName) {
		byte[] keyb = null;
		if ("".equals(key) || key == null) {
			keyb = DatatypeConverter.parseBase64Binary(SECRET_KEY);
		} else {
			keyb = DatatypeConverter.parseBase64Binary(key);
		}
		String jcaName1 = null;
		if ("".equals(jcaName) || jcaName == null) {
			jcaName1 = DEFAULTSIGN.getJcaName();
		} else {
			jcaName1 = jcaName;
		}

		Key signKey = new SecretKeySpec(keyb, jcaName1);
		return signKey;
	}

	/**
	 * 解析 token
	 *
	 * @param token
	 * @return
	 */
	public static Map parserToken(String token) throws Exception {

		Claims claims = null;
		claims = Jwts.parser().setSigningKey(getKey(SECRET_KEY, DEFAULTSIGN.getJcaName())).parseClaimsJws(token)
				.getBody();
		//userid = (String) claims.get("userId");
		return claims;
	}

	/**
	 * 获得userId 如果解析错误返回 -1
	 *
	 * @param token
	 * @return
	 */
	public static String getUserIdByToken(String token) {

		Claims claims = null;
		String userid = "-1";
		try {
			claims = Jwts.parser().setSigningKey(getKey(SECRET_KEY, DEFAULTSIGN.getJcaName())).parseClaimsJws(token)
					.getBody();
			userid = (String) claims.get("id");
		} catch (Exception e) {
			LOGGER.info("解密userId失败：" + token);
			return userid;
		}
		return userid;
	}

	/**
	 * 获得username 如果解析错误返回 -1
	 *
	 * @param token
	 * @return
	 */
	public static String getUserNameByToken(String token) {

		Claims claims = null;
		String username = "-1";
		try {
			claims = Jwts.parser().setSigningKey(getKey(SECRET_KEY, DEFAULTSIGN.getJcaName())).parseClaimsJws(token)
					.getBody();
			username = (String) claims.get("username");
		} catch (Exception e) {
			LOGGER.info("解密userId失败：" + token);
			return username;
		}
		return username;
	}

	/**
	 * 获得userId 如果解析错误返回 -1
	 *
	 * @param token
	 * @return
	 */
	public static String getValueByToken(String token, String value) {
		Claims claims = null;
		try {
			claims = Jwts.parser().setSigningKey(getKey(SECRET_KEY, DEFAULTSIGN.getJcaName())).parseClaimsJws(token)
					.getBody();
			value = String.valueOf(claims.get(value));
			if (value == null || "".equals(value)) {
				value = "-1";
				return value;
			}
		} catch (Exception e) {
			e.printStackTrace();
			value = "-1";
			return value;
		}
		return value;
	}

	public static void main(String[] args) throws Exception {
		String token = createToken(1, "34466", "荀玉龙", "17601636518");
		System.out.println(token);
		System.out.println(parserToken(token));
		System.out.println(getValueByToken(token, "enterpriseId"));
		System.out.println(getUserIdByToken(token));

		long timeStamp = (long) parserToken(token).get("timeStamp");

		long ts = System.currentTimeMillis();
		if (ts - timeStamp > 1000 * 120) {
			System.out.println("token超时");
		} else {
			System.out.println("token有效");
		}

		//System.out.println(UUID.randomUUID().toString().replace("-", "").substring(0, 16));

	}

}
