package com.xyw.console.config;

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

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.csrf.DefaultCsrfToken;
import org.springframework.security.web.csrf.InvalidCsrfTokenException;

/** File purpose (plain language): verifies that security rejections provide safe browser actions without leaking account or token details. */
class SecurityConfigTest {
  /** Plain purpose: verify a missing or invalid CSRF token receives refresh-and-retry guidance rather than an indistinguishable role error. Related files: SecurityConfig.java, auth-api-client.js. Flow: CSRF filter denial -> safe message -> browser refresh/retry. */
  @Test void csrfFailureUsesRefreshAndRetryMessage() {
    SecurityConfig config = new SecurityConfig();
    assertEquals("安全校验已失效，请刷新页面后重试", config.accessDeniedMessage(new InvalidCsrfTokenException(new DefaultCsrfToken("X-XSRF-TOKEN", "_csrf", "expected"), "actual")));
  }

  /** Plain purpose: verify a valid session without an allowed role keeps the generic denial message. Related files: SecurityConfig.java, PagePermissionService.java. Flow: controller role check -> access denial -> safe 403 response. */
  @Test void authorizationFailureKeepsGenericMessage() {
    SecurityConfig config = new SecurityConfig();
    assertEquals("没有权限", config.accessDeniedMessage(new AccessDeniedException("internal detail")));
  }

  /** 代码作用（白话）：验证单页应用把可读的 CSRF Cookie 值写进请求头后，安全配置会按原始值校验，而不会把合法退出请求误判为伪造请求。关联文件：SecurityConfig.java、auth-api-client.js。关联逻辑（调用链/数据流）：XSRF-TOKEN Cookie -> X-XSRF-TOKEN 请求头 -> Spring Security CSRF 校验 -> /api/auth/logout。 */
  @Test void csrfRequestHandlerAcceptsRawCookieTokenFromSpaHeader() {
    String tokenValue = "csrf-cookie-token";
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.addHeader("X-XSRF-TOKEN", tokenValue);
    DefaultCsrfToken csrfToken = new DefaultCsrfToken("X-XSRF-TOKEN", "_csrf", tokenValue);

    assertEquals(tokenValue, new SecurityConfig().csrfRequestHandler().resolveCsrfTokenValue(request, csrfToken));
  }
}
