package dev.lions.unionflow.server.resource;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

import dev.lions.unionflow.server.api.dto.config.request.UpdateConfigurationRequest;
import dev.lions.unionflow.server.api.dto.config.response.ConfigurationResponse;
import dev.lions.unionflow.server.service.ConfigurationService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import jakarta.ws.rs.NotFoundException;
import java.util.Collections;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
 * Tests pour ConfigurationResource.
 *
 * <p>Utilise {@code @InjectMock} sur {@link ConfigurationService} pour contrôler
 * les réponses et couvrir toutes les branches de la resource.
 */
@QuarkusTest
class ConfigurationResourceTest {

    @InjectMock
    ConfigurationService configurationService;

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/configuration retourne 200 avec liste vide")
    void listerConfigurations_returns200() {
        when(configurationService.listerConfigurations()).thenReturn(Collections.emptyList());

        given()
                .when()
                .get("/api/configuration")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/configuration/{cle} avec config inexistante retourne 404")
    void obtenirConfiguration_inexistante_returns404() {
        when(configurationService.obtenirConfiguration("app.version"))
                .thenThrow(new NotFoundException("Configuration non trouvée"));

        given()
                .pathParam("cle", "app.version")
                .when()
                .get("/api/configuration/{cle}")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("PUT /api/configuration/{cle} mettreAJourConfiguration retourne 200")
    void mettreAJourConfiguration_returns200() {
        ConfigurationResponse updated = new ConfigurationResponse();
        updated.setCle("app.version");
        updated.setValeur("2.0.0");

        when(configurationService.mettreAJourConfiguration(anyString(), any(UpdateConfigurationRequest.class)))
                .thenReturn(updated);

        String body = "{"
                + "\"cle\": \"app.version\","
                + "\"valeur\": \"2.0.0\","
                + "\"type\": \"STRING\","
                + "\"categorie\": \"APPLICATION\","
                + "\"description\": \"Version de l'application\","
                + "\"modifiable\": true,"
                + "\"visible\": true"
                + "}";

        given()
                .contentType("application/json")
                .pathParam("cle", "app.version")
                .body(body)
                .when()
                .put("/api/configuration/{cle}")
                .then()
                .statusCode(anyOf(equalTo(200), equalTo(400)));
    }

    // =========================================================================
    // obtenirConfiguration — happy path (couvre ConfigurationResource:50 — 9I, 0B)
    // =========================================================================

    /**
     * Couvre les 9 instructions manquantes à la ligne 50 de {@code ConfigurationResource.obtenirConfiguration}.
     *
     * <p>Le service retourne une réponse valide → la resource exécute toutes les instructions :
     * log, appel service, construction Response.ok → retourne HTTP 200.
     */
    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/configuration/{cle} avec config existante retourne 200 (couvre obtenirConfiguration:50 — 9I, 0B)")
    void obtenirConfiguration_existante_returns200() {
        ConfigurationResponse response = new ConfigurationResponse();
        response.setCle("defaut.devise");
        response.setValeur("XOF");
        response.setType("STRING");
        response.setCategorie("SYSTEME");
        response.setModifiable(false);
        response.setVisible(true);

        when(configurationService.obtenirConfiguration("defaut.devise")).thenReturn(response);

        given()
                .pathParam("cle", "defaut.devise")
                .when()
                .get("/api/configuration/{cle}")
                .then()
                .statusCode(200)
                .body("cle", equalTo("defaut.devise"))
                .body("valeur", equalTo("XOF"));
    }
}
