package com.tzy.common.utils.http.forest;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwk.Jwk;
import com.tzy.common.exception.ServiceException;
import com.tzy.common.utils.bean.JSONTools;
import com.tzy.common.utils.http.forest.param.AppleParam;
import com.tzy.common.utils.http.forest.param.AppleToken;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
public class AppleUtil {

	private static AppleForestClient appleForestClient;
	private static String keys = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgKgw5qN3memOIXocO\n" +
			"L/ZtJfGhaTePXt1b1RIOFRBfIymgCgYIKoZIzj0DAQehRANCAARHmNFKrjRRsBDQ\n" +
			"QCymT2P4+Vij+wo0BPdbQgCw6L/C1I+EkcxUWRCqUPcrKG/W+NxqtBhpaA2kcHE7\n" +
			"JtGx2c+0";
	private static final String keyID = "M3F4A458ZY";
	private static final String teamID = "NL5PMY22D8";
	private static final String appID = "com.hobbystocks";
	private static byte[] readKey = Base64.decodeBase64(keys);

	@Resource
	public void setAppleForestClient(AppleForestClient appleForestClient) {
		AppleUtil.appleForestClient = appleForestClient;
	}


	/**
	 * 获取苹果的公钥
	 *
	 * @return
	 * @throws Exception
	 */
	private static JSONArray getAuthKeys() {
		String key = appleForestClient.getKey();
		JSONObject json = JSONObject.parseObject(key);
		JSONArray arr = json.getJSONArray("keys");
		return arr;
	}

	public static Boolean verify(String jwt) throws Exception {
		JSONArray arr = getAuthKeys();
		if (arr == null) {
			return false;
		}
		return verifyExcNew(jwt, arr);
	}

	/**
	 * 根据jwt head中kid获取对应公钥参数
	 * @param keys
	 * @param kid
	 * @return
	 */
	private static JSONObject getKey(JSONArray keys, String kid) {
		for (Object object : keys) {
			JSONObject json = ((JSONObject) object);
			if (json.getString("kid").equals(kid)) {
				return json;
			}
		}
		return null;
	}

	/**
	 * 对前端传来的identityToken进行验证
	 *
	 * @param jwt     对应前端传来的 identityToken
	 * @param keys 苹果的公钥 keys
	 * @return
	 * @throws Exception
	 */
	public static Boolean verifyExcNew(String jwt, JSONArray keys) throws Exception {
		String aud = "";
		String sub = "";
		String kid = "";
		String[] jwtArr = jwt.split("\\.");
		if (jwtArr.length > 1) {
			String headClaim = new String(Base64.decodeBase64(jwtArr[0]));
			kid = JSONObject.parseObject(headClaim).get("kid").toString();
			String claim = new String(Base64.decodeBase64(jwtArr[1]));
			aud = JSONObject.parseObject(claim).get("aud").toString();
			sub = JSONObject.parseObject(claim).get("sub").toString();
		}

		JSONObject authKey = getKey(keys, kid);
		Jwk jwa = Jwk.fromValues(authKey);
		PublicKey publicKey = jwa.getPublicKey();

		JwtParser jwtParser = Jwts.parser().setSigningKey(publicKey);
		jwtParser.requireIssuer("https://appleid.apple.com");
		jwtParser.requireAudience(aud);
		jwtParser.requireSubject(sub);

		try {
			Jws<Claims> claim = jwtParser.parseClaimsJws(jwt);
			log.debug("苹果登陆token校验参数:{}", claim.getBody());
			if (claim != null && claim.getBody().containsKey("auth_time")) {
				return true;
			}
			return false;
		} catch (ExpiredJwtException e) {
			log.error("apple identityToken expired", e);
			return false;
		} catch (Exception e) {
			log.error("apple identityToken illegal,aud:{},sub:{},jwt:{}", aud, sub, jwt);
			log.error("apple identityToken illegal", e);
			return false;
		}
	}


	/**
	 * 对前端传来的JWT字符串identityToken的第二部分进行解码
	 * 主要获取其中的aud和sub，aud大概对应ios前端的包名，sub大概对应当前用户的授权的openID
	 *
	 * @param identityToken
	 * @return {"aud":"com.xkj.****","sub":"000***.8da764d3f9e34d2183e8da08a1057***.0***","c_hash":"UsKAuEoI-****","email_verified":"true","auth_time":1574673481,"iss":"https://appleid.apple.com","exp":1574674081,"iat":1574673481,"email":"****@qq.com"}
	 */
	public static JSONObject parserIdentityToken(String identityToken) {
		String[] arr = identityToken.split("\\.");
		//Base64 base64 = new Base64();
		//String decode = new String (base64.decodeBase64(arr[1]));
		String decode = new String(Base64.decodeBase64(arr[1]));
		String substring = decode.substring(0, decode.indexOf("}") + 1);
		JSONObject jsonObject = JSON.parseObject(substring);
		return jsonObject;
	}

	public static AppleParam buildAuthParam(String code) throws Exception {
		//构建client_secret关键代码：
		Map<String, Object> header = new HashMap<>(1);
		header.put("kid", keyID); // 参考后台配置
		Map<String, Object> claims = new HashMap<>(5);
		claims.put("iss", teamID); // 参考后台配置 team id
		long now = System.currentTimeMillis() / 1000;
		claims.put("iat", now);
		claims.put("exp", now + 86400 * 30); // 最长半年，单位秒
		claims.put("aud", "https://appleid.apple.com"); // 默认值
		claims.put("sub", appID);// 被授权的APP ID
		PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readKey);
		KeyFactory keyFactory = KeyFactory.getInstance("EC");
		PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
		String client_secret = Jwts.builder().setHeader(header).setClaims(claims).signWith(SignatureAlgorithm.ES256, privateKey).compact();
		AppleParam param = new AppleParam();
		param.setClient_id(appID);
		//param.setRedirect_uri(AppleConfig.getRedirectUri());
		param.setClient_secret(client_secret);
		param.setCode(code);
		return param;
	}


	public static AppleToken getAuth(String code) throws Exception {
		AppleParam appleParam = buildAuthParam(code);
		String token = appleForestClient.getToken(appleParam);
		if (StringUtils.isEmpty(token)) {
			throw new ServiceException(500, "获取苹果token失败");
		}
		return JSONTools.jsonStr2obj(token, AppleToken.class);
	}

}
