package dev.lions.unionflow.server.resource;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.*;

import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@QuarkusTest
class AdhesionResourceTest {

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/{id} inexistant retourne 404")
    void obtenirParId_inexistant_returns404() {
        given()
                .pathParam("id", UUID.randomUUID())
                .when()
                .get("/api/adhesions/{id}")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/membre/{id} retourne 200 ou 404")
    void listerParMembre_returns200ou404() {
        given()
                .pathParam("membreId", UUID.randomUUID())
                .queryParam("page", 0)
                .queryParam("size", 20)
                .when()
                .get("/api/adhesions/membre/{membreId}")
                .then()
                .statusCode(anyOf(equalTo(200), equalTo(404)))
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/organisation/{id} retourne 200 ou 404")
    void listerParOrganisation_returns200ou404() {
        given()
                .pathParam("organisationId", UUID.randomUUID())
                .queryParam("page", 0)
                .queryParam("size", 20)
                .when()
                .get("/api/adhesions/organisation/{organisationId}")
                .then()
                .statusCode(anyOf(equalTo(200), equalTo(404)))
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/statut/EN_ATTENTE retourne 200")
    void listerParStatut_returns200() {
        given()
                .pathParam("statut", "EN_ATTENTE")
                .queryParam("page", 0)
                .queryParam("size", 20)
                .when()
                .get("/api/adhesions/statut/{statut}")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/en-attente retourne 200")
    void listerEnAttente_returns200() {
        given()
                .queryParam("page", 0)
                .queryParam("size", 20)
                .when()
                .get("/api/adhesions/en-attente")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/stats retourne 200")
    void getStats_returns200() {
        given()
                .when()
                .get("/api/adhesions/stats")
                .then()
                .statusCode(200);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions retourne 200 avec liste")
    void getAllAdhesions_returns200() {
        given()
                .queryParam("page", 0)
                .queryParam("size", 20)
                .when()
                .get("/api/adhesions")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("GET /api/adhesions/reference/{ref} avec référence inexistante retourne 404")
    void getByReference_inexistant_returns404() {
        given()
                .pathParam("numeroReference", "ADH-INEXISTANT-99999")
                .when()
                .get("/api/adhesions/reference/{numeroReference}")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("POST /api/adhesions avec données invalides retourne 400")
    void createAdhesion_invalidData_returns400() {
        java.util.Map<String, Object> body = java.util.Map.of(
                "membreId", UUID.randomUUID().toString(),
                "organisationId", UUID.randomUUID().toString(),
                "montantAdhesion", 5000
        );

        given()
                .contentType(io.restassured.http.ContentType.JSON)
                .body(body)
                .when()
                .post("/api/adhesions")
                .then()
                .statusCode(anyOf(equalTo(400), equalTo(404), equalTo(500)));
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("PUT /api/adhesions/{id} avec ID inexistant retourne 404")
    void updateAdhesion_inexistant_returns404() {
        java.util.Map<String, Object> body = java.util.Map.of(
                "statut", "EN_ATTENTE"
        );

        given()
                .contentType(io.restassured.http.ContentType.JSON)
                .pathParam("id", UUID.randomUUID())
                .body(body)
                .when()
                .put("/api/adhesions/{id}")
                .then()
                .statusCode(anyOf(equalTo(404), equalTo(500)));
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("DELETE /api/adhesions/{id} avec ID inexistant retourne 404")
    void deleteAdhesion_inexistant_returns404() {
        given()
                .pathParam("id", UUID.randomUUID())
                .when()
                .delete("/api/adhesions/{id}")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("POST /api/adhesions/{id}/approuver avec ID inexistant retourne 404")
    void approuverAdhesion_inexistant_returns404() {
        given()
                .pathParam("id", UUID.randomUUID())
                .queryParam("approuvePar", "admin@unionflow.com")
                .contentType(io.restassured.http.ContentType.JSON)
                .when()
                .post("/api/adhesions/{id}/approuver")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("POST /api/adhesions/{id}/rejeter avec ID inexistant retourne 404")
    void rejeterAdhesion_inexistant_returns404() {
        given()
                .pathParam("id", UUID.randomUUID())
                .queryParam("motifRejet", "Dossier incomplet")
                .contentType(io.restassured.http.ContentType.JSON)
                .when()
                .post("/api/adhesions/{id}/rejeter")
                .then()
                .statusCode(404);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = { "ADMIN" })
    @DisplayName("POST /api/adhesions/{id}/paiement avec ID inexistant retourne 404")
    void enregistrerPaiement_inexistant_returns404() {
        given()
                .pathParam("id", UUID.randomUUID())
                .queryParam("montantPaye", "5000")
                .queryParam("methodePaiement", "ESPECES")
                .contentType(io.restassured.http.ContentType.JSON)
                .when()
                .post("/api/adhesions/{id}/paiement")
                .then()
                .statusCode(anyOf(equalTo(404), equalTo(500)));
    }
}
