package org.cmh.backend.Utils;

import io.jsonwebtoken.Claims;
import lombok.Getter;
import lombok.Setter;
import org.junit.Assert;
import org.junit.Test;

import java.util.Date;

public class JwtUtilTest {

    @Test
    public void testGenerateToken() throws InterruptedException {
        String username = "testUser";
        String token = JwtUtil.generateToken(username);
        Thread.sleep(100);

        // Validate token is not empty
        Assert.assertNotNull("Token should not be null", token);
        Assert.assertFalse("Token should not be empty", token.isEmpty());

        // Parse the token to check claims
        Claims claims = JwtUtil.extractClaims(token);
//        System.out.println(claims.getIssuedAt().toString());


        // Validate claims
        Assert.assertTrue("Token should be valid", JwtUtil.isTokenValid(token, username));
        Assert.assertEquals("Username in claims should match", username, claims.getSubject());
        Assert.assertTrue("Token should be issued in the past", new Date().after(claims.getIssuedAt()));
        Assert.assertTrue("Token expiration should be in the future", new Date().before(claims.getExpiration()));
    }

    @Test
    public void testTokenExpiration() {
        String username = "testUser";
        String token = JwtUtil.generateToken(username);

        Claims claims = JwtUtil.extractClaims(token);

        long expirationTime = claims.getExpiration().getTime();
        long currentTime = new Date().getTime();

        // Validate token expires within 10 hours
        Assert.assertTrue("Token should expire within 10 hours", expirationTime - currentTime <= 1000 * 60 * 60 * 10);
    }

    @Test
    public void testInvalidToken() {
        String invalidToken = "invalidToken";
        String validToken = JwtUtil.generateToken("validUser");
        Assert.assertFalse("Invalid token should not be valid", JwtUtil.isTokenValid(invalidToken));
        Assert.assertTrue("Valid token should be able to extract", JwtUtil.isTokenValid(validToken));
        Assert.assertFalse("Invalid token should not be valid", JwtUtil.isTokenValid(invalidToken, "validUser"));
        Assert.assertTrue("Valid token should be valid", JwtUtil.isTokenValid(validToken, "validUser"));
    }

    @Getter
    @Setter
    private class SomeJwtRequest extends JwtRequest {
        String msg;

        public SomeJwtRequest(String token, String msg) {
            super.setToken(token);
            this.msg = msg;
        }
    }

    private class SomeController {
        private final SomeJwtRequest request;

        SomeController(String token) {
            this.request = new SomeJwtRequest(token, "test");
        }

        public boolean run() {
            try {
                return verify(request);
            } catch (JwtValidationException e) {
                return false;
            }
        }

        @JwtVerify
        public boolean verify(SomeJwtRequest request) {
            return false;
        }
    }


    @Test
    public void testVerify() {
        //TODO:这里似乎不能这样测试，待修改或忽略
        String username = "testUser";
        String token = JwtUtil.generateToken(username);
        SomeController validTokenController = new SomeController(token);
        SomeController invalidTokenController = new SomeController("invalidToken");
        Assert.assertFalse("Valid token should pass verification", validTokenController.run());
        Assert.assertFalse("Invalid token should fail verification", invalidTokenController.run());
    }
}

