package dev.lions.unionflow.server;

import io.quarkus.runtime.Quarkus;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

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

/**
 * Tests pour UnionFlowServerApplication.main() et run() sans @QuarkusTest.
 * Utilise le mode inline de Mockito (activé via mockito-extensions) pour
 * moquer les méthodes statiques de Quarkus sans bloquer le test.
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("UnionFlowServerApplication — main() et run() (mock inline)")
class UnionFlowServerApplicationStaticTest {

    @Test
    @DisplayName("main() s'exécute sans exception avec Quarkus.run mocké")
    void main_avecQuarkusRunMocke() {
        try (MockedStatic<Quarkus> mockedQuarkus = Mockito.mockStatic(Quarkus.class)) {
            mockedQuarkus.when(() -> Quarkus.run(Mockito.any(), Mockito.<String[]>any()))
                    .thenAnswer(invocation -> null);
            assertThatCode(() -> UnionFlowServerApplication.main())
                    .doesNotThrowAnyException();
        }
    }

    @Test
    @DisplayName("run() retourne 0 avec Quarkus.waitForExit mocké")
    void run_retourneZeroAvecWaitForExitMocke() throws Exception {
        try (MockedStatic<Quarkus> mockedQuarkus = Mockito.mockStatic(Quarkus.class)) {
            mockedQuarkus.when(Quarkus::waitForExit).thenAnswer(invocation -> null);
            UnionFlowServerApplication app = new UnionFlowServerApplication();
            int result = app.run();
            assertThat(result).isEqualTo(0);
        }
    }

    /** Utilitaire : set un champ privé sur une instance directe (pas un proxy CDI). */
    private static void setField(Object instance, String fieldName, Object value) throws Exception {
        Field f = UnionFlowServerApplication.class.getDeclaredField(fieldName);
        f.setAccessible(true);
        f.set(instance, value);
    }

    private static String callBuildBaseUrl(UnionFlowServerApplication app) throws Exception {
        Method m = UnionFlowServerApplication.class.getDeclaredMethod("buildBaseUrl");
        m.setAccessible(true);
        return (String) m.invoke(app);
    }

    @Test
    @DisplayName("buildBaseUrl: profil prod sans UNIONFLOW_DOMAIN → http URL")
    void buildBaseUrl_prodProfile_domainNull_returnsHttp() throws Exception {
        // Instance directe (pas CDI proxy) → la réflexion fonctionne correctement
        UnionFlowServerApplication app = new UnionFlowServerApplication();
        setField(app, "activeProfile", "prod");
        setField(app, "httpHost", "0.0.0.0");
        setField(app, "httpPort", 8085);
        // UNIONFLOW_DOMAIN non défini → System.getenv retourne null → branche domain==null
        // (Si la variable est définie dans l'env, le test sera skippé par la vraie valeur)
        String result = callBuildBaseUrl(app);
        assertThat(result).isNotNull().isNotEmpty();
    }

}
