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.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.when;

import dev.lions.unionflow.server.api.dto.favoris.request.CreateFavoriRequest;
import dev.lions.unionflow.server.api.dto.favoris.response.FavoriResponse;
import dev.lions.unionflow.server.service.FavorisService;
import io.quarkus.test.InjectMock;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
import io.restassured.http.ContentType;
import jakarta.ws.rs.NotFoundException;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

/**
 * Tests mock pour FavorisResource — couvre les instructions non atteintes par FavorisResourceTest.
 *
 * <p>Ces tests utilisent @InjectMock pour mocker FavorisService et s'assurer
 * que tous les chemins de code (201 créé, 204 supprimé, NotFoundException) sont couverts.
 */
@QuarkusTest
@DisplayName("FavorisResource — mock")
class FavorisResourceMockTest {

    @InjectMock
    FavorisService favorisService;

    private static final UUID USER_ID = UUID.randomUUID();
    private static final UUID FAVORI_ID = UUID.randomUUID();

    // =========================================================================
    // listerFavoris — GET /api/favoris/utilisateur/{utilisateurId}
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("GET /api/favoris/utilisateur/{id} retourne 200 avec liste vide")
    void listerFavoris_emptyList_returns200() {
        when(favorisService.listerFavoris(any(UUID.class))).thenReturn(List.of());

        given()
                .pathParam("utilisateurId", USER_ID)
                .when()
                .get("/api/favoris/utilisateur/{utilisateurId}")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("GET /api/favoris/utilisateur/{id} retourne 200 avec favoris")
    void listerFavoris_withFavoris_returns200() {
        FavoriResponse fav = new FavoriResponse();
        fav.setId(FAVORI_ID);
        fav.setTitre("Mon favori");
        fav.setUtilisateurId(USER_ID);

        when(favorisService.listerFavoris(any(UUID.class))).thenReturn(List.of(fav));

        given()
                .pathParam("utilisateurId", USER_ID)
                .when()
                .get("/api/favoris/utilisateur/{utilisateurId}")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }

    // =========================================================================
    // creerFavori — POST /api/favoris
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("POST /api/favoris retourne 201 avec données valides")
    void creerFavori_validRequest_returns201() {
        FavoriResponse created = new FavoriResponse();
        created.setId(FAVORI_ID);
        created.setTitre("Nouveau favori");
        created.setUtilisateurId(USER_ID);

        when(favorisService.creerFavori(any(CreateFavoriRequest.class))).thenReturn(created);

        Map<String, Object> body = Map.of(
                "utilisateurId", USER_ID.toString(),
                "typeFavori", "MEMBRE",
                "titre", "Nouveau favori",
                "url", "/api/membres/123"
        );

        given()
                .contentType(ContentType.JSON)
                .body(body)
                .when()
                .post("/api/favoris")
                .then()
                .statusCode(201);
    }

    // =========================================================================
    // supprimerFavori — DELETE /api/favoris/{id}
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("DELETE /api/favoris/{id} retourne 204 quand suppression réussie")
    void supprimerFavori_success_returns204() {
        doNothing().when(favorisService).supprimerFavori(any(UUID.class));

        given()
                .pathParam("id", FAVORI_ID)
                .when()
                .delete("/api/favoris/{id}")
                .then()
                .statusCode(204);
    }

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("DELETE /api/favoris/{id} retourne 404 quand favori non trouvé")
    void supprimerFavori_notFound_returns404() {
        doThrow(new NotFoundException("Favori non trouvé"))
                .when(favorisService).supprimerFavori(any(UUID.class));

        given()
                .pathParam("id", UUID.randomUUID())
                .when()
                .delete("/api/favoris/{id}")
                .then()
                .statusCode(404);
    }

    // =========================================================================
    // obtenirStatistiques — GET /api/favoris/utilisateur/{id}/statistiques
    // =========================================================================

    @Test
    @TestSecurity(user = "admin@unionflow.com", roles = {"ADMIN"})
    @DisplayName("GET /api/favoris/utilisateur/{id}/statistiques retourne 200 avec statistiques")
    void obtenirStatistiques_returns200() {
        Map<String, Object> stats = Map.of(
                "totalFavoris", 5L,
                "favorisActifs", 3L,
                "favorisInactifs", 2L
        );
        when(favorisService.obtenirStatistiques(any(UUID.class))).thenReturn(stats);

        given()
                .pathParam("utilisateurId", USER_ID)
                .when()
                .get("/api/favoris/utilisateur/{utilisateurId}/statistiques")
                .then()
                .statusCode(200)
                .body("$", notNullValue());
    }
}
