package cokr.xit.ens.modules.junittest.jwt;

import cokr.xit.ens.core.utils.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import java.util.*;
import java.util.Base64.Decoder;



@TestMethodOrder(value = MethodOrderer.OrderAnnotation.class)
public class JwtTestSample {
	
	private final String SECRET_KEY = "TEST";
	
	private static String ACCESS_TOKEN = null;
	

	
	@Test
	@Order(1)
	void create() {
//		System.out.println(String.format("Random Uuid => %s", UUID.randomUUID().toString()));
//		System.out.println(String.format("Str A-B-C-D-E Uuid => %s", UUID.fromString("A-B-C-D-E").toString()));
//		System.out.println(String.format("Str A-B-C-D-E Uuid => %s", UUID.fromString("A-B-C-D-E").toString()));
		System.out.println(DateUtil.absTimeSecToDate(1639231881, "yyyy-MM-dd HH:mm:ss"));
		System.out.println(DateUtil.absTimeSecToDate(1606533000, "yyyy-MM-dd HH:mm:ss"));
		
		System.out.println("\nJWT Create...");
		// Create JWT Token
		String token = JWT.create()
		    .withIssuer("발급기관")                                            
		    .withSubject("ENS-Token")                                        
		    .withAudience("이용기관")                                          
		    .withExpiresAt(new Date(System.currentTimeMillis() + 864000000)) 
//		    .withExpiresAt(new Date(System.currentTimeMillis() - 864000000)) 
		    .withNotBefore(new Date(DateUtil.dateToAbsTime(2021, 12, 28, 10, 30, 0))) 
		    .withIssuedAt(new Date(System.currentTimeMillis()))              
		    .withJWTId("JWT ID")                                             
		    .withClaim("uUuid", UUID.randomUUID().toString())                
		    .withClaim("uUrl", "www.test.co.kr")
		    .sign(Algorithm.HMAC512(SECRET_KEY.getBytes()));

		//jwt token header.payload.signature
		System.out.println(String.format("[Token(Header.Payload.Signature)] => %s", token));
		ACCESS_TOKEN = token;

	}
	
	@Test
	@Order(2)
	void decode() {
		System.out.println("\nJWT Decode...");
		
		Decoder decoder = Base64.getDecoder(); 
		final String[] splitJwt = ACCESS_TOKEN.split("\\.");
		final String header = new String(decoder.decode(splitJwt[0].getBytes()));
		final String payload = new String(decoder.decode(splitJwt[1].getBytes()));

		System.out.println(String.format("[Header] => %s", header));
		System.out.println(String.format("[Payload] => %s", payload));
		
//		Mapper
//		Long sec 
//		DateUtil.absSecTimeToDate(null, payload)

		
	}
	
	@Test
	@Order(3)
	void verify() {
		System.out.println("\nJWT Verify...");
		
		
		
		try {
			System.out.println(String.format("[Token] => %s", ACCESS_TOKEN));
			Map<String, Claim> result = JWT.require(Algorithm.HMAC512(SECRET_KEY.getBytes()))
			.build()
			.verify(ACCESS_TOKEN.replace("Bearer", ""))
//			.getClaim("UserId");
			.getClaims();
			
			//result
			Iterator<String> it = result.keySet().iterator();
			while(it.hasNext()) {
				String key = it.next();
				Claim claim = result.get(key);
				
				System.out.println(String.format("    %s = %s", key, claim.asString()));
			}
			System.out.println(String.format("    %s = %s", "사용자Uuid ", result.get("uUuid").asString()));
			System.out.println(String.format("    %s = %s", "사용자URL", result.get("uUrl").asString()));
		}catch(Exception e) {
			System.out.println(String.format("Token Verify Fail... %s", e.getMessage()));
		}
		
		
		try {
			StringBuilder modulateToken = new StringBuilder();
			modulateToken.append(ACCESS_TOKEN.split("\\.")[0])
			.append(".")
			.append("eyJzdWIiOiLtmozsm5BpZCIsImlzcyI6ImdnZ2ciLCJtZW1iZXJJZCI6ImhhaGFoYWgifQ")
			.append(".")
			.append(ACCESS_TOKEN.split("\\.")[2]);
			
			System.out.println(String.format("[Token] => %s", modulateToken));
			Claim result = JWT.require(Algorithm.HMAC512(SECRET_KEY.getBytes()))
					.build()
					.verify(modulateToken.toString().replace("Bearer", ""))
					.getClaim("uUuid");
			
			//result
			System.out.println(result.asString());
		}catch(Exception e) {
			System.out.println(String.format("Token Verify Fail... %s", e.getMessage()));
		}
	}
}
