package study.testing.slicetest;

import java.nio.charset.StandardCharsets;
import java.util.Base64;

import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.ApplicationContext;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

/**
 * 对照组：类路径加上 spring-boot-security-test 后，Boot4 的 @WebMvcTest 切片
 * 重新导入安全自动配置——安全链在场、匿名 401、mock 身份源可完成认证。
 */
@WebMvcTest(ApiController.class)
class WebMvcSliceSecurityTest {

    @Autowired
    MockMvc mvc;

    @Autowired
    ApplicationContext context;

    @MockitoBean
    UserDetailsService users;

    @Test
    void securityTestModuleRestoresSecurityInSlice() throws Exception {
        int chains = context.getBeansOfType(SecurityFilterChain.class).size();
        org.junit.jupiter.api.Assertions.assertEquals(1, chains, "spring-boot-security-test 让切片装配默认安全链");
        int anonymous = mvc.perform(MockMvcRequestBuilders.get("/api/hello")).andReturn().getResponse().getStatus();
        org.junit.jupiter.api.Assertions.assertEquals(401, anonymous, "匿名请求被默认安全链拒绝");
        System.out.println("U25OBSERVE webmvc-slice-security securityFilterChains=" + chains + " anonymous=" + anonymous);
    }

    @Test
    void mockedIdentitySourceCompletesAuthenticationInSlice() throws Exception {
        Mockito.when(users.loadUserByUsername("sliceuser"))
                .thenReturn(User.withUsername("sliceuser").password("{noop}slice-pass").roles("USER").build());
        String token = Base64.getEncoder().encodeToString("sliceuser:slice-pass".getBytes(StandardCharsets.UTF_8));
        MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/api/hello")
                .header("Authorization", "Basic " + token);
        int status = mvc.perform(request).andReturn().getResponse().getStatus();
        org.junit.jupiter.api.Assertions.assertEquals(200, status, "真实 Provider 对 mock 凭据完成认证");
        System.out.println("U25OBSERVE webmvc-slice-security mockedUser=" + status);
    }
}
