package com.mosquito.project.config;

import com.mosquito.project.persistence.repository.ApiKeyRepository;
import com.mosquito.project.security.UserIntrospectionService;
import com.mosquito.project.web.ApiKeyAuthInterceptor;
import com.mosquito.project.web.ApiResponseWrapperInterceptor;
import com.mosquito.project.web.UserAuthInterceptor;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.handler.MappedInterceptor;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;

class WebMvcConfigTest {

    @Test
    @DisplayName("/api/v1/me 需要 API Key + 用户态鉴权")
    void shouldProtectMeEndpoints_withApiKeyAndUserAuth() {
        ApiKeyRepository apiKeyRepository = mock(ApiKeyRepository.class);
        MockEnvironment environment = new MockEnvironment();
        ApiResponseWrapperInterceptor responseWrapperInterceptor = new ApiResponseWrapperInterceptor();
        UserIntrospectionService introspectionService = new UserIntrospectionService(
            new RestTemplateBuilder(),
            new AppConfig(),
            Optional.empty()
        );

        WebMvcConfig config = new WebMvcConfig(
            apiKeyRepository,
            environment,
            Optional.empty(),
            responseWrapperInterceptor,
            introspectionService
        );

        TestInterceptorRegistry registry = new TestInterceptorRegistry();
        config.addInterceptors(registry);

        List<MappedInterceptor> mappedInterceptors = registry.getMappedInterceptors();
        MappedInterceptor apiKeyInterceptor = findMapped(mappedInterceptors, ApiKeyAuthInterceptor.class);
        MappedInterceptor userAuthInterceptor = findMapped(mappedInterceptors, UserAuthInterceptor.class);

        assertNotNull(apiKeyInterceptor);
        assertNotNull(userAuthInterceptor);
        assertTrue(containsPattern(apiKeyInterceptor.getPathPatterns(), "/api/**"));
        assertTrue(containsPattern(userAuthInterceptor.getPathPatterns(), "/api/v1/me/**"));
        assertTrue(containsPattern(userAuthInterceptor.getPathPatterns(), "/api/v1/activities/**"));
        assertTrue(containsPattern(userAuthInterceptor.getPathPatterns(), "/api/v1/api-keys/**"));
        assertTrue(containsPattern(userAuthInterceptor.getPathPatterns(), "/api/v1/share/**"));
    }

    private static MappedInterceptor findMapped(List<MappedInterceptor> interceptors, Class<?> type) {
        return interceptors.stream()
            .filter(interceptor -> type.isInstance(interceptor.getInterceptor()))
            .findFirst()
            .orElse(null);
    }

    private static boolean containsPattern(String[] patterns, String expected) {
        if (patterns == null) {
            return false;
        }
        return Arrays.asList(patterns).contains(expected);
    }

    private static class TestInterceptorRegistry extends InterceptorRegistry {
        List<MappedInterceptor> getMappedInterceptors() {
            return super.getInterceptors().stream()
                .filter(interceptor -> interceptor instanceof MappedInterceptor)
                .map(interceptor -> (MappedInterceptor) interceptor)
                .toList();
        }
    }
}
