package dev.lions.unionflow.server;

import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * Tests pour UnionFlowServerApplication
 * 
 * @author Lions Dev Team
 * @since 2025-01-10
 */
@QuarkusTest
@DisplayName("Tests UnionFlowServerApplication")
class UnionFlowServerApplicationTest {

    @Test
    @DisplayName("Test de l'application - Contexte Quarkus")
    void testApplicationContext() {
        // Given & When & Then
        // Le simple fait que ce test s'exécute sans erreur
        // prouve que l'application Quarkus démarre correctement
        assertThat(true).isTrue();
    }

    @Test
    @DisplayName("Test de l'application - Classe principale existe")
    void testMainClassExists() {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class).isNotNull();
        assertThat(UnionFlowServerApplication.class.getAnnotation(io.quarkus.runtime.annotations.QuarkusMain.class))
                .isNotNull();
    }

    @Test
    @DisplayName("Test de l'application - Implémente QuarkusApplication")
    void testImplementsQuarkusApplication() {
        // Given & When & Then
        assertThat(io.quarkus.runtime.QuarkusApplication.class)
                .isAssignableFrom(UnionFlowServerApplication.class);
    }

    @Test
    @DisplayName("Test de l'application - Méthode main existe")
    void testMainMethodExists() throws NoSuchMethodException {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class.getMethod("main", String[].class))
                .isNotNull();
    }

    @Test
    @DisplayName("Test de l'application - Méthode run existe")
    void testRunMethodExists() throws NoSuchMethodException {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class.getMethod("run", String[].class))
                .isNotNull();
    }

    @Test
    @DisplayName("Test de l'application - Annotation ApplicationScoped")
    void testApplicationScopedAnnotation() {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class.getAnnotation(jakarta.enterprise.context.ApplicationScoped.class))
                .isNotNull();
    }

    @Test
    @DisplayName("Test de l'application - Logger statique")
    void testStaticLogger() throws NoSuchFieldException {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class.getDeclaredField("LOG"))
                .isNotNull();
    }

    @Test
    @DisplayName("Test de l'application - Instance créable")
    void testInstanceCreation() {
        // Given & When
        UnionFlowServerApplication app = new UnionFlowServerApplication();

        // Then
        assertThat(app).isNotNull();
        assertThat(app).isInstanceOf(io.quarkus.runtime.QuarkusApplication.class);
    }

    @Test
    @DisplayName("Test de la méthode main - Signature correcte")
    void testMainMethodSignature() throws NoSuchMethodException {
        // Given & When
        var mainMethod = UnionFlowServerApplication.class.getMethod("main", String[].class);

        // Then
        assertThat(mainMethod.getReturnType()).isEqualTo(void.class);
        assertThat(java.lang.reflect.Modifier.isStatic(mainMethod.getModifiers())).isTrue();
        assertThat(java.lang.reflect.Modifier.isPublic(mainMethod.getModifiers())).isTrue();
    }

    @Test
    @DisplayName("Test de la méthode run - Signature correcte")
    void testRunMethodSignature() throws NoSuchMethodException {
        // Given & When
        var runMethod = UnionFlowServerApplication.class.getMethod("run", String[].class);

        // Then
        assertThat(runMethod.getReturnType()).isEqualTo(int.class);
        assertThat(java.lang.reflect.Modifier.isPublic(runMethod.getModifiers())).isTrue();
        assertThat(runMethod.getExceptionTypes()).contains(Exception.class);
    }



    @Test
    @DisplayName("Test de l'implémentation QuarkusApplication")
    void testQuarkusApplicationImplementation() {
        // Given & When & Then
        assertThat(io.quarkus.runtime.QuarkusApplication.class.isAssignableFrom(UnionFlowServerApplication.class))
                .isTrue();
    }

    @Test
    @DisplayName("Test du package de la classe")
    void testPackageName() {
        // Given & When & Then
        assertThat(UnionFlowServerApplication.class.getPackage().getName())
                .isEqualTo("dev.lions.unionflow.server");
    }

    @Test
    @DisplayName("Test de la classe - Modificateurs")
    void testClassModifiers() {
        // Given & When & Then
        assertThat(java.lang.reflect.Modifier.isPublic(UnionFlowServerApplication.class.getModifiers())).isTrue();
        assertThat(java.lang.reflect.Modifier.isFinal(UnionFlowServerApplication.class.getModifiers())).isFalse();
        assertThat(java.lang.reflect.Modifier.isAbstract(UnionFlowServerApplication.class.getModifiers())).isFalse();
    }

    @Test
    @DisplayName("Test des constructeurs")
    void testConstructors() {
        // Given & When
        var constructors = UnionFlowServerApplication.class.getConstructors();

        // Then
        assertThat(constructors).hasSize(1);
        assertThat(constructors[0].getParameterCount()).isEqualTo(0);
        assertThat(java.lang.reflect.Modifier.isPublic(constructors[0].getModifiers())).isTrue();
    }
}
