package cn.novalon.manage.sys.security;

import cn.novalon.manage.common.config.JwtProperties;
import io.jsonwebtoken.Claims;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
class JwtTokenProviderTest {

    @Mock
    private JwtProperties jwtProperties;

    private JwtTokenProvider jwtTokenProvider;

    @BeforeEach
    void setUp() {
        jwtTokenProvider = new JwtTokenProvider(jwtProperties);
    }

    @Test
    void testGenerateToken() {
        when(jwtProperties.getSecret()).thenReturn("test-secret-key-for-testing-purposes-only-1234567890");
        when(jwtProperties.getExpiration()).thenReturn(3600000L); // 1小时
        
        String token = jwtTokenProvider.generateToken("testuser", 1L);
        
        assertThat(token).isNotNull();
        assertThat(token).isNotEmpty();
    }

    @Test
    void testGetUsernameFromToken() {
        when(jwtProperties.getSecret()).thenReturn("test-secret-key-for-testing-purposes-only-1234567890");
        when(jwtProperties.getExpiration()).thenReturn(3600000L); // 1小时
        
        String token = jwtTokenProvider.generateToken("testuser", 1L);
        
        String username = jwtTokenProvider.getUsernameFromToken(token);
        
        assertThat(username).isEqualTo("testuser");
    }

    @Test
    void testGetUserIdFromToken() {
        when(jwtProperties.getSecret()).thenReturn("test-secret-key-for-testing-purposes-only-1234567890");
        when(jwtProperties.getExpiration()).thenReturn(3600000L); // 1小时
        
        String token = jwtTokenProvider.generateToken("testuser", 1L);
        
        Long userId = jwtTokenProvider.getUserIdFromToken(token);
        
        assertThat(userId).isEqualTo(1L);
    }

    @Test
    void testGetClaimsFromToken() {
        when(jwtProperties.getSecret()).thenReturn("test-secret-key-for-testing-purposes-only-1234567890");
        when(jwtProperties.getExpiration()).thenReturn(3600000L); // 1小时
        
        String token = jwtTokenProvider.generateToken("testuser", 1L);
        
        Claims claims = jwtTokenProvider.getClaimsFromToken(token);
        
        assertThat(claims).isNotNull();
        assertThat(claims.getSubject()).isEqualTo("testuser");
        assertThat(claims.get("userId", Long.class)).isEqualTo(1L);
        assertThat(claims.get("username")).isEqualTo("testuser");
    }

    @Test
    void testValidateToken_Valid() {
        when(jwtProperties.getSecret()).thenReturn("test-secret-key-for-testing-purposes-only-1234567890");
        when(jwtProperties.getExpiration()).thenReturn(3600000L); // 1小时
        
        String token = jwtTokenProvider.generateToken("testuser", 1L);
        
        boolean isValid = jwtTokenProvider.validateToken(token);
        
        assertThat(isValid).isTrue();
    }

    @Test
    void testValidateToken_Invalid() {
        String invalidToken = "invalid.token.string";
        
        boolean isValid = jwtTokenProvider.validateToken(invalidToken);
        
        assertThat(isValid).isFalse();
    }

    @Test
    void testValidateToken_Empty() {
        boolean isValid = jwtTokenProvider.validateToken("");
        
        assertThat(isValid).isFalse();
    }

    @Test
    void testValidateToken_Null() {
        boolean isValid = jwtTokenProvider.validateToken(null);
        
        assertThat(isValid).isFalse();
    }
}