package org.innovateuk.ifs.starters.stubdev;

import com.google.common.collect.ImmutableList;
import org.innovateuk.ifs.IfsProfileConstants;
import org.innovateuk.ifs.starter.common.util.ProfileUtils;
import org.innovateuk.ifs.starters.stubdev.cfg.StubDevConfigurationProperties;
import org.innovateuk.ifs.starters.stubdev.filter.RewriteFilter;
import org.innovateuk.ifs.starters.stubdev.security.StubUidSupplier;
import org.innovateuk.ifs.starters.stubdev.thymeleaf.IfsThymeleafPostProcessorDialect;
import org.innovateuk.ifs.starters.stubdev.util.TimerAspect;
import org.innovateuk.ifs.starters.stubdev.util.WarningLogger;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.devtools.autoconfigure.LocalDevToolsAutoConfiguration;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import org.thymeleaf.templateresolver.ITemplateResolver;

import java.util.List;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.innovateuk.ifs.IfsProfileConstants.STUBDEV;
import static org.innovateuk.ifs.starters.stubdev.cfg.StubDevConfigurationProperties.STUB_DEV_PROPS_PREFIX;
import static org.junit.jupiter.api.Assertions.assertThrows;

class IfsStubDevAutoConfigurationTest {

    private static final List COMMON = ImmutableList.of(
            WarningLogger.class,
            StubUidSupplier.class,
            ITemplateResolver.class,
            RewriteFilter.class,
            StubDevConfigurationProperties.class,
            IfsStubDevAutoConfiguration.class
    );

    // Require properties to be set
    private static final List UNCOMMON = ImmutableList.of(
            IfsThymeleafPostProcessorDialect.class,
            TimerAspect.class
    );

    @Test
    @ResourceLock("COMMON")
    void testConfigWithDevtoolsAndProfileAndThymleafDebug() {
        new ApplicationContextRunner()
                .withSystemProperties(ProfileUtils.activeProfilesString(STUBDEV))
                .withSystemProperties(
                        STUB_DEV_PROPS_PREFIX + ".validateHtml=true",
                        STUB_DEV_PROPS_PREFIX + ".enableClientMethodTiming=true",
                        STUB_DEV_PROPS_PREFIX + ".logThymeLeafTemplates=true",
                        STUB_DEV_PROPS_PREFIX + ".defaultUuid=123-456-789"
                )
                .withConfiguration(
                        AutoConfigurations.of(LocalDevToolsAutoConfiguration.class, IfsStubDevAutoConfiguration.class)
                ).withBean(TimerAspect.class).run((context) -> {
                    assertFound(context, COMMON);
                    assertFound(context, UNCOMMON);
                });
    }

    @Test
    @ResourceLock("COMMON")
    void testConfigWithDevtoolsAndWrongProfile() {
        new ApplicationContextRunner()
                .withSystemProperties(ProfileUtils.activeProfilesString(IfsProfileConstants.LOCAL_STORAGE))
                .withConfiguration(
                        AutoConfigurations.of(LocalDevToolsAutoConfiguration.class, IfsStubDevAutoConfiguration.class)
                ).run((context) -> {
                    assertNotFound(context, COMMON);
                    assertNotFound(context, UNCOMMON);
                });
    }

    @Test
    @ResourceLock("COMMON")
    void testConfigWithDevtoolsAndProfile() {
        new ApplicationContextRunner()
                .withSystemProperties(
                    ProfileUtils.activeProfilesString(STUBDEV),
                    STUB_DEV_PROPS_PREFIX + ".defaultUuid=123-456-789"
                )
                .withConfiguration(
                        AutoConfigurations.of(LocalDevToolsAutoConfiguration.class, IfsStubDevAutoConfiguration.class)
                ).run((context) -> {
                    assertFound(context, COMMON);
                    assertNotFound(context, UNCOMMON);
                });
    }

    @Test
    @ResourceLock("COMMON")
    void testConfigWithDevtoolsNoProfile() {
        new ApplicationContextRunner()
                .withConfiguration(
                        AutoConfigurations.of(LocalDevToolsAutoConfiguration.class, IfsStubDevAutoConfiguration.class)
                ).run((context) -> {
                    assertNotFound(context, COMMON);
                    assertNotFound(context, UNCOMMON);
                });
    }

    @Test
    @ResourceLock("COMMON")
    void testConfigNoDevtoolsNoProfile() {
        new ApplicationContextRunner()
                .withConfiguration(
                        AutoConfigurations.of(IfsStubDevAutoConfiguration.class)
                ).run((context) -> {
                    assertNotFound(context, COMMON);
                    assertNotFound(context, UNCOMMON);
                });
    }

    private static void assertNotFound(ApplicationContext context, List<Class> clzs) {
        clzs.stream().forEach(clz -> assertThrows(BeansException.class, () -> context.getBean(clz)));
    }

    private static void assertFound(ApplicationContext context, List<Class> clzs) {
        clzs.stream().forEach(clz -> assertThat(context.getBean(clz), is(notNullValue())));
    }
}
@@ -903,24 +903,107 @@
 figuration;%0A
+import org.springframework.boot.test.context.assertj.AssertableApplicationContext;%0A
 import org.s
@@ -1064,24 +1064,24 @@
 textRunner;%0A
-
 import org.s
@@ -1298,60 +1298,9 @@
 ers.
-is;%0Aimport static org.hamcrest.Matchers.notNullValue
+*
 ;%0Aim
@@ -1699,45 +1699,8 @@
 ss,%0A
-            ITemplateResolver.class,%0A
     
@@ -2863,32 +2863,103 @@
 ntext, COMMON);%0A
+                    assertNFound(context, ITemplateResolver.class, 2);%0A
                 
@@ -4133,32 +4133,103 @@
 ntext, COMMON);%0A
+                    assertNFound(context, ITemplateResolver.class, 2);%0A
                 
@@ -4286,32 +4286,34 @@
      %7D);%0A    %7D%0A%0A
+%0A%0A
     @Test%0A    @R
@@ -5426,32 +5426,32 @@
 %3CClass%3E clzs) %7B%0A
-
         clzs.str
@@ -5531,10 +5531,185 @@
 );%0A    %7D
+%0A%0A    private void assertNFound(AssertableApplicationContext context, Class clz, int howMany) %7B%0A        assertThat(context.getBeansOfType(clz).size(), equalTo(howMany));%0A    %7D
 %0A%7D

update test to match