// Path: spat-services/src/main/java/com/pcalouche/spat/config/SpatProperties.java
// @Getter
// @Setter
// @Component
// @ConfigurationProperties(prefix = "spat")
// @Validated
// public class SpatProperties {
//     /**
//      * The current version. This is set use Spring Boot's automatic
//      * property expansion.
//      */
//     private String version;
//     /**
//      * What origins to allow access from
//      */
//     private String[] corsAllowedOrigins;
//     /**
//      * The signing key used for JWTs.
//      */
//     @NotEmpty
//     private String jwtSigningKey;
//     /**
//      * How long JWT tokens are good for
//      */
//     @NonNull
//     private Duration jwtTokenDuration;
//     /**
//      * How long JWT refresh tokens are good for
//      */
//     @NotNull
//     private Duration refreshTokenDuration;
//     /**
//      * The hostname of the environment
//      */
//     @NotEmpty
//     private String hostname;
// 
//     public boolean isHttpsEnvironment() {
//         return !"localhost".equals(hostname);
//     }
// }
// 
// Path: spat-services/src/main/java/com/pcalouche/spat/entity/User.java
// @Entity
// @Table(name = "users")
// @Getter
// @Setter
// @Builder
// @NoArgsConstructor
// @AllArgsConstructor
// public class User implements UserDetails {
//     @Id
//     @GeneratedValue(strategy = GenerationType.IDENTITY)
//     private Integer id;
//     @NotBlank
//     @Column(unique = true, nullable = false)
//     private String username;
//     @NotBlank
//     @Column(nullable = false)
//     private String password;
//     @Builder.Default
//     private boolean accountNonExpired = true;
//     @Builder.Default
//     private boolean accountNonLocked = true;
//     @Builder.Default
//     private boolean credentialsNonExpired = true;
//     @Builder.Default
//     private boolean enabled = true;
//     @ManyToMany(fetch = FetchType.EAGER)
//     @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
//     @Builder.Default
//     private Set<Role> roles = new HashSet<>();
//     @Transient
//     @Setter(AccessLevel.NONE)
//     private Set<SimpleGrantedAuthority> authorities;
// 
//     @Override
//     public Set<SimpleGrantedAuthority> getAuthorities() {
//         if (authorities == null) {
//             authorities = new HashSet<>();
//             if (roles != null) {
//                 for (Role role : roles) {
//                     authorities.add(new SimpleGrantedAuthority(role.getName()));
//                 }
//             }
//         }
//         return authorities;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (!(o instanceof User)) {
//             return false;
//         }
//         User castedObj = (User) o;
//         return Objects.equals(username, castedObj.getUsername());
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(username);
//     }
// }


import com.pcalouche.spat.config.SpatProperties;
import com.pcalouche.spat.entity.User;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.authentication.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.Base64;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
    public void testGetDecodedBasicAuthFromRequestBadDecodeThrowsException() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .buildRequest(new MockServletContext());
        assertThatThrownBy(() -> SecurityUtils.getDecodedBasicAuthFromRequest(request))
                .isInstanceOf(BadCredentialsException.class)
                .hasMessage("Basic Authentication header is invalid");
    }

    @Test
    public void testGetDecodedBasicAuthFromRequestBadHeaderPrefixThrowsException() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .header(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BASIC_PREFIX + Base64.getEncoder().encodeToString("invalidHeader".getBytes()))
                .buildRequest(new MockServletContext());

        assertThatThrownBy(() -> SecurityUtils.getDecodedBasicAuthFromRequest(request))
                .isInstanceOf(BadCredentialsException.class)
                .hasMessage("Basic Authentication header is invalid");
    }

    @Test
    public void testGetTokenFromRequest() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .header(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BEARER_PREFIX + "YWN0aXZlVXNlcjpwYXNzd29yZA==")
                .buildRequest(new MockServletContext());

        request.addHeader(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BEARER_PREFIX + "YWN0aXZlVXNlcjpwYXNzd29yZA==");
        assertThat(SecurityUtils.getTokenFromRequest(request)).isNotEmpty();
    }

    @Test
// Path: spat-services/src/main/java/com/pcalouche/spat/config/SpatProperties.java
// @Getter
// @Setter
// @Component
// @ConfigurationProperties(prefix = "spat")
// @Validated
// public class SpatProperties {
//     /**
//      * The current version. This is set use Spring Boot's automatic
//      * property expansion.
//      */
//     private String version;
//     /**
//      * What origins to allow access from
//      */
//     private String[] corsAllowedOrigins;
//     /**
//      * The signing key used for JWTs.
//      */
//     @NotEmpty
//     private String jwtSigningKey;
//     /**
//      * How long JWT tokens are good for
//      */
//     @NonNull
//     private Duration jwtTokenDuration;
//     /**
//      * How long JWT refresh tokens are good for
//      */
//     @NotNull
//     private Duration refreshTokenDuration;
//     /**
//      * The hostname of the environment
//      */
//     @NotEmpty
//     private String hostname;
// 
//     public boolean isHttpsEnvironment() {
//         return !"localhost".equals(hostname);
//     }
// }
// 
// Path: spat-services/src/main/java/com/pcalouche/spat/entity/User.java
// @Entity
// @Table(name = "users")
// @Getter
// @Setter
// @Builder
// @NoArgsConstructor
// @AllArgsConstructor
// public class User implements UserDetails {
//     @Id
//     @GeneratedValue(strategy = GenerationType.IDENTITY)
//     private Integer id;
//     @NotBlank
//     @Column(unique = true, nullable = false)
//     private String username;
//     @NotBlank
//     @Column(nullable = false)
//     private String password;
//     @Builder.Default
//     private boolean accountNonExpired = true;
//     @Builder.Default
//     private boolean accountNonLocked = true;
//     @Builder.Default
//     private boolean credentialsNonExpired = true;
//     @Builder.Default
//     private boolean enabled = true;
//     @ManyToMany(fetch = FetchType.EAGER)
//     @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
//     @Builder.Default
//     private Set<Role> roles = new HashSet<>();
//     @Transient
//     @Setter(AccessLevel.NONE)
//     private Set<SimpleGrantedAuthority> authorities;
// 
//     @Override
//     public Set<SimpleGrantedAuthority> getAuthorities() {
//         if (authorities == null) {
//             authorities = new HashSet<>();
//             if (roles != null) {
//                 for (Role role : roles) {
//                     authorities.add(new SimpleGrantedAuthority(role.getName()));
//                 }
//             }
//         }
//         return authorities;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (!(o instanceof User)) {
//             return false;
//         }
//         User castedObj = (User) o;
//         return Objects.equals(username, castedObj.getUsername());
//     }
// 
//     @Override
//     public int hashCode() {
//         return Objects.hash(username);
//     }
// }


// Path: spat-services/src/test/java/com/pcalouche/spat/security/util/SecurityUtilsTest.java
import com.pcalouche.spat.config.SpatProperties;
import com.pcalouche.spat.entity.User;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.security.authentication.*;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import java.util.Base64;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

    public void testGetDecodedBasicAuthFromRequestBadDecodeThrowsException() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .buildRequest(new MockServletContext());
        assertThatThrownBy(() -> SecurityUtils.getDecodedBasicAuthFromRequest(request))
                .isInstanceOf(BadCredentialsException.class)
                .hasMessage("Basic Authentication header is invalid");
    }

    @Test
    public void testGetDecodedBasicAuthFromRequestBadHeaderPrefixThrowsException() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .header(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BASIC_PREFIX + Base64.getEncoder().encodeToString("invalidHeader".getBytes()))
                .buildRequest(new MockServletContext());

        assertThatThrownBy(() -> SecurityUtils.getDecodedBasicAuthFromRequest(request))
                .isInstanceOf(BadCredentialsException.class)
                .hasMessage("Basic Authentication header is invalid");
    }

    @Test
    public void testGetTokenFromRequest() {
        MockHttpServletRequest request = MockMvcRequestBuilders.get("/some-endpoint")
                .header(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BEARER_PREFIX + "YWN0aXZlVXNlcjpwYXNzd29yZA==")
                .buildRequest(new MockServletContext());

        request.addHeader(HttpHeaders.AUTHORIZATION, SecurityUtils.AUTH_HEADER_BEARER_PREFIX + "YWN0aXZlVXNlcjpwYXNzd29yZA==");
        assertThat(SecurityUtils.getTokenFromRequest(request)).isNotEmpty();
    }

    @Test
    public void testValidateUserAccountStatusAccountExpiredException() {