package org.apereo.cas.authentication.handler.support;

import org.apereo.cas.authentication.AuthenticationHandler;
import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
import org.apereo.cas.authentication.DefaultAuthenticationServiceSelectionPlan;
import org.apereo.cas.authentication.principal.PrincipalResolver;
import org.apereo.cas.config.CasCoreAuthenticationConfiguration;
import org.apereo.cas.config.CasCoreAuthenticationHandlersConfiguration;
import org.apereo.cas.config.CasCoreAuthenticationPolicyConfiguration;
import org.apereo.cas.config.CasCoreAuthenticationPrincipalConfiguration;
import org.apereo.cas.config.CasCoreAuthenticationSupportConfiguration;
import org.apereo.cas.config.CasCoreHttpConfiguration;
import org.apereo.cas.config.CasCoreUtilConfiguration;
import org.apereo.cas.config.CasCoreWebConfiguration;
import org.apereo.cas.config.support.CasWebApplicationServiceFactoryConfiguration;
import org.apereo.cas.services.ServicesManager;
import org.apereo.cas.util.CollectionUtils;

import lombok.SneakyThrows;
import lombok.val;
import org.apache.commons.io.IOUtils;
import org.apereo.services.persondir.IPersonAttributeDao;
import org.apereo.services.persondir.support.StubPersonAttributeDao;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

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

/**
 * This is {@link JaasAuthenticationHandlersConfigurationTests}.
 *
 * @author Misagh Moayyed
 * @since 6.3.0
 */
@Tag("Simple")
@SpringBootTest(classes = {
    RefreshAutoConfiguration.class,
    JaasAuthenticationHandlersConfigurationTests.JaasAuthenticationHandlersConfigurationTestConfiguration.class,
    CasCoreWebConfiguration.class,
    CasCoreHttpConfiguration.class,
    CasCoreUtilConfiguration.class,
    CasWebApplicationServiceFactoryConfiguration.class,
    CasCoreAuthenticationPrincipalConfiguration.class,
    CasCoreAuthenticationHandlersConfiguration.class,
    CasCoreAuthenticationPolicyConfiguration.class,
    CasCoreAuthenticationSupportConfiguration.class,
    CasCoreAuthenticationConfiguration.class
}, properties = {
    "cas.authn.accept.users=casuser::Mellon,casuser2::Mellon",
    "cas.authn.jaas[0].realm=CAS",
    "cas.authn.jaas[0].password-policy.enabled=true",
    "cas.authn.jaas[0].password-policy.account-state-handling-enabled=true",
    "cas.authn.jaas[0].login-config-type=JavaLoginConfig",
})
public class JaasAuthenticationHandlersConfigurationTests {
    @Autowired
    @Qualifier("jaasAuthenticationHandlers")
    private List<AuthenticationHandler> jaasAuthenticationHandlers;

    @Autowired
    @Qualifier("jaasPersonDirectoryPrincipalResolvers")
    private List<PrincipalResolver> jaasPersonDirectoryPrincipalResolvers;

    @Test
    public void verifyOperation() {
        assertFalse(jaasAuthenticationHandlers.isEmpty());
        assertFalse(jaasPersonDirectoryPrincipalResolvers.isEmpty());
    }

    @BeforeEach
    @SneakyThrows
    public void initialize() {
        val resource = new ClassPathResource("jaas-system.conf");
        val fileName = new File(System.getProperty("java.io.tmpdir"), "jaas-authn.conf");
        try (val writer = Files.newBufferedWriter(fileName.toPath(), StandardCharsets.UTF_8)) {
            IOUtils.copy(resource.getInputStream(), writer, Charset.defaultCharset());
            writer.flush();
        }
        if (fileName.exists()) {
            System.setProperty("java.security.auth.login.config", '=' + fileName.getCanonicalPath());
        }
    }

    @TestConfiguration("JaasAuthenticationHandlersConfigurationTestConfiguration")
    public static class JaasAuthenticationHandlersConfigurationTestConfiguration {

        @Bean
        public IPersonAttributeDao attributeRepository() {
            return new StubPersonAttributeDao();
        }
        
        @Bean
        public AuthenticationServiceSelectionPlan authenticationServiceSelectionPlan() {
            return new DefaultAuthenticationServiceSelectionPlan();
        }

        @Bean
        public ServicesManager servicesManager() {
            return mock(ServicesManager.class);
        }
    }
}

@@ -4442,32 +4442,96 @@
 %0A%0A        @Bean%0A
+        @ConditionalOnMissingBean(name = %22attributeRepository%22)%0A
         public I
@@ -4569,24 +4569,24 @@
 ository() %7B%0A
-
             
@@ -4647,32 +4647,111 @@
  %0A        @Bean%0A
+        @ConditionalOnMissingBean(name = %22authenticationServiceSelectionPlan%22)%0A
         public A
@@ -4898,24 +4898,24 @@
 %0A        %7D%0A%0A
-
         @Bea
@@ -4908,32 +4908,92 @@
 %0A%0A        @Bean%0A
+        @ConditionalOnMissingBean(name = %22servicesManager%22)%0A
         public S

add tests