package com.cf.imes.module.system.util.oauth2;

import org.junit.jupiter.api.Test;

import java.time.LocalDateTime;
import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

/**
 * {@link OAuth2Utils} 的单元测试
 */
class OAuth2UtilsTest {

    @Test
    void testBuildAuthorizationCodeRedirectUri() {
        // 测试构建授权码模式下的重定向URI
        String redirectUri = "https://example.com/callback";
        String authorizationCode = "auth-code-12345";
        String state = "state-value";

        String result = OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("code=auth-code-12345"));
        assertTrue(result.contains("state=state-value"));
    }

    @Test
    void testBuildAuthorizationCodeRedirectUriWithoutState() {
        // 测试构建授权码模式下的重定向URI（不包含state参数）
        String redirectUri = "https://example.com/callback";
        String authorizationCode = "auth-code-12345";
        String state = null;

        String result = OAuth2Utils.buildAuthorizationCodeRedirectUri(redirectUri, authorizationCode, state);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("code=auth-code-12345"));
        assertFalse(result.contains("state="));
    }

    @Test
    void testBuildImplicitRedirectUri() {
        // 测试构建简化模式下的重定向URI
        String redirectUri = "https://example.com/callback";
        String accessToken = "access-token-12345";
        String state = "state-value";
        LocalDateTime expireTime = LocalDateTime.now().plusHours(1);
        Collection<String> scopes = Arrays.asList("read", "write");
        Map<String, Object> additionalInformation = new HashMap<>();
        additionalInformation.put("user_id", "user-123");
        additionalInformation.put("client_id", "client-456");
        additionalInformation.put("extra_test_1", null);
        additionalInformation.put("extra_test_2", "2");

        String result = OAuth2Utils.buildImplicitRedirectUri(redirectUri, accessToken, state, expireTime, scopes, additionalInformation);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("access_token=access-token-12345"));
        assertTrue(result.contains("token_type=bearer"));
        assertTrue(result.contains("state=state-value"));
        assertTrue(result.contains("expires_in="));
        assertTrue(result.contains("scope=read%20write"));
        // 验证extra_前缀是否正确处理
        assertTrue(result.contains("user_id=user-123"));
        assertTrue(result.contains("client_id=client-456"));
        // 确保原始的extra_前缀key没有出现在结果中
        assertFalse(result.contains("extra_user_id="));
        assertFalse(result.contains("extra_client_id="));
        assertFalse(result.contains("extra_test_1=null"));
        assertTrue(result.contains("extra_test_2=2"));
    }

    @Test
    void testBuildImplicitRedirectUriWithMinimalParameters() {
        // 测试构建简化模式下的重定向URI（最小参数）
        String redirectUri = "https://example.com/callback";
        String accessToken = "access-token-12345";
        String state = null;
        LocalDateTime expireTime = null;
        Collection<String> scopes = null;
        Map<String, Object> additionalInformation = null;

        String result = OAuth2Utils.buildImplicitRedirectUri(redirectUri, accessToken, state, expireTime, scopes, additionalInformation);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("access_token=access-token-12345"));
        assertTrue(result.contains("token_type=bearer"));
        assertFalse(result.contains("state="));
        assertFalse(result.contains("expires_in="));
        assertFalse(result.contains("scope="));
    }

    @Test
    void testBuildUnsuccessfulRedirect() {
        // 测试构建失败重定向URI
        String redirectUri = "https://example.com/callback";
        String responseType = "code";
        String state = "state-value";
        String error = "invalid_request";
        String description = "The request is missing a required parameter";

        String result = OAuth2Utils.buildUnsuccessfulRedirect(redirectUri, responseType, state, error, description);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("error=invalid_request"));
        assertTrue(result.contains("error_description=The%20request%20is%20missing%20a%20required%20parameter"));
        assertTrue(result.contains("state=state-value"));
    }

    @Test
    void testBuildUnsuccessfulRedirectWithoutState() {
        // 测试构建失败重定向URI（不包含state参数）
        String redirectUri = "https://example.com/callback";
        String responseType = "token";
        String state = null;
        String error = "invalid_request";
        String description = "The request is missing a required parameter";

        String result = OAuth2Utils.buildUnsuccessfulRedirect(redirectUri, responseType, state, error, description);

        assertTrue(result.contains("https://example.com/callback"));
        assertTrue(result.contains("error=invalid_request"));
        assertTrue(result.contains("error_description=The%20request%20is%20missing%20a%20required%20parameter"));
        assertFalse(result.contains("state="));
    }

    @Test
    void testGetExpiresIn() {
        // 测试获取过期时间
        LocalDateTime futureTime = LocalDateTime.now().plusSeconds(3600);
        
        long expiresIn = OAuth2Utils.getExpiresIn(futureTime);
        
        // 验证过期时间在合理范围内
        assertTrue(expiresIn > 0);
        assertTrue(expiresIn <= 3600);
    }

    @Test
    void testBuildScopeStr() {
        // 测试构建scope字符串
        Collection<String> scopes = Arrays.asList("read", "write", "profile");

        String result = OAuth2Utils.buildScopeStr(scopes);

        assertEquals("read write profile", result);
    }

    @Test
    void testBuildScopeStrWithEmptyScopes() {
        // 测试构建scope字符串（空集合）
        Collection<String> scopes = new ArrayList<>();

        String result = OAuth2Utils.buildScopeStr(scopes);

        assertEquals("", result);
    }

    @Test
    void testBuildScopeStrWithNullScopes() {
        // 测试构建scope字符串（null）
        Collection<String> scopes = null;

        String result = OAuth2Utils.buildScopeStr(scopes);

        assertNull(result);
    }

    @Test
    void testBuildScopes() {
        // 测试解析scope字符串
        String scope = "read write profile";

        List<String> result = OAuth2Utils.buildScopes(scope);

        assertEquals(3, result.size());
        assertTrue(result.contains("read"));
        assertTrue(result.contains("write"));
        assertTrue(result.contains("profile"));
    }

    @Test
    void testBuildScopesWithSingleScope() {
        // 测试解析scope字符串（单个scope）
        String scope = "read";

        List<String> result = OAuth2Utils.buildScopes(scope);

        assertEquals(1, result.size());
        assertTrue(result.contains("read"));
    }

    @Test
    void testBuildScopesWithEmptyString() {
        // 测试解析scope字符串（空字符串）
        String scope = "";

        List<String> result = OAuth2Utils.buildScopes(scope);

        // 空字符串split后会返回包含一个空字符串的列表
        assertEquals(1, result.size());
        assertEquals("", result.get(0));
    }

    @Test
    void testBuildScopesWithNull() {
        // 测试解析scope字符串（null）
        String scope = null;

        List<String> result = OAuth2Utils.buildScopes(scope);

        // null值split后会返回空列表
        assertTrue(result.isEmpty());
    }
}