package com.jsowell.common.util;

import com.jsowell.common.constant.Constants;
import com.jsowell.common.enums.ykc.ReturnCodeEnum;
import com.jsowell.common.exception.BusinessException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;

@Component
public class JWTUtils {
	// 令牌自定义标识
	private static String header;

	@Value("${token.header}")
	public void setHeader(String header) {
		JWTUtils.header = header;
	}

	// 令牌秘钥
	private static String secret;

	@Value("${token.secret}")
	public void setSecret(String secret) {
		JWTUtils.secret = secret;
	}

	// 接口服务 令牌有效期
	private static int serviceExpireTime;

	@Value("${token.serviceExpireTime}")
	public void setServiceExpireTime(int serviceExpireTime) {
		JWTUtils.serviceExpireTime = serviceExpireTime;
	}

	protected static final long MILLIS_SECOND = 1000;

	protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;

	private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;

	/**
	 * 生成Jwt的方法
	 *
	 * @param id        用户ID
	 * @param subject   用户昵称
	 * @param ttlMillis 过期时间 毫秒
	 * @return Token String 凭证
	 */
	public static String createToken(String id, String subject, long ttlMillis) {
		// 签名方法 HS256
		SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

		// 生成Jwt的时间
		long nowMillis = System.currentTimeMillis();
		Date now = new Date(nowMillis);

		// 生成秘钥
		byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(secret);
		Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

		// 设置JWT所存储的信息
		JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now).setSubject(subject).signWith(signatureAlgorithm, signingKey);

		//builder.claim("name", "value"); //存储自定义信息

		// 设置过期时间
		if (ttlMillis >= 0) {
			long expMillis = nowMillis + ttlMillis * MILLIS_MINUTE;
			Date exp = new Date(expMillis);
			builder.setExpiration(exp);
		}

		// 构建JWT并将其序列化为紧凑的URL安全字符串
		return builder.compact();
	}

	/**
	 * 从令牌中获取数据声明
	 *
	 * @param token 令牌
	 * @return 数据声明
	 */
	private static Claims parseToken(String token) {
		return Jwts.parser()
				.setSigningKey(secret)
				.parseClaimsJws(token)
				.getBody();
	}

	/**
	 * 获取会员token
	 *
	 * @return
	 */
	public static String createMemberToken(String memberId, String nickName) {
		return createToken(memberId, nickName, serviceExpireTime);
	}

	/**
	 * 获取会员id
	 *
	 * @param memberToken
	 * @return
	 */
	public static String getMemberId(String memberToken) {
		memberToken = getToken(memberToken);
		if (StringUtils.isBlank(memberToken)) {
			throw new BusinessException(ReturnCodeEnum.CODE_TOKEN_ERROR);
		}
		Claims claims = parseToken(memberToken);
		return claims.getId();
	}

	public static boolean checkThirdPartyToken(String token) {
		token = getToken(token);
		if (StringUtils.isBlank(token)) {
			throw new BusinessException(ReturnCodeEnum.CODE_TOKEN_ERROR);
		}
		Claims claims = parseToken(token);
		return StringUtils.isNotBlank(claims.getId());
	}

	/**
	 * 替换Bearer
	 *
	 * @param memberToken 会员token
	 * @return
	 */
	private static String getToken(String memberToken) {
		if (StringUtils.isNotEmpty(memberToken) && memberToken.startsWith(Constants.TOKEN_PREFIX)) {
			memberToken = memberToken.replace(Constants.TOKEN_PREFIX, "").trim();
		}
		return memberToken;
	}

	public static void main(String[] args) {
		long ttlMillis = 60 * 60 * 24 * 1000;
		String token = createToken("I4XLPQPV", "3DSBTWHVIC6KVCKI", ttlMillis);
		System.out.println(checkThirdPartyToken(token));
	}
}
