package dev.lions.unionflow.server.resource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;

import dev.lions.unionflow.server.service.MigrerOrganisationsVersKeycloakService;
import dev.lions.unionflow.server.service.MigrerOrganisationsVersKeycloakService.MigrationReport;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.Map;

/**
 * Tests unitaires Mockito pour {@link AdminKeycloakOrganisationResource}.
 *
 * <p>Couvre tous les chemins d'exécution :
 * <ul>
 *   <li>Migration réussie (success=true) → 200 OK</li>
 *   <li>Migration partielle (erreurs > 0) → 207 Multi-Status</li>
 *   <li>Exception lancée par le service → 500 Internal Server Error</li>
 * </ul>
 */
@ExtendWith(MockitoExtension.class)
@DisplayName("Tests AdminKeycloakOrganisationResource")
class AdminKeycloakOrganisationResourceTest {

    @Mock
    MigrerOrganisationsVersKeycloakService migrationService;

    @InjectMocks
    AdminKeycloakOrganisationResource resource;

    // ── POST /api/admin/keycloak/migrer-organisations — succès total ──────────

    @Test
    @DisplayName("migrerOrganisations — tous créés sans erreur → 200 OK avec succes=true")
    void migrerOrganisations_allCreated_returns200() throws Exception {
        MigrationReport report = new MigrationReport(5, 5, 0, 0);
        when(migrationService.migrerToutesLesOrganisations()).thenReturn(report);

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(200);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity.get("total")).isEqualTo(5);
        assertThat(entity.get("crees")).isEqualTo(5);
        assertThat(entity.get("ignores")).isEqualTo(0);
        assertThat(entity.get("erreurs")).isEqualTo(0);
        assertThat(entity.get("succes")).isEqualTo(true);
    }

    @Test
    @DisplayName("migrerOrganisations — aucune organisation à migrer (toutes ignorées) → 200 OK")
    void migrerOrganisations_allIgnored_returns200() throws Exception {
        MigrationReport report = new MigrationReport(3, 0, 3, 0);
        when(migrationService.migrerToutesLesOrganisations()).thenReturn(report);

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(200);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity.get("crees")).isEqualTo(0);
        assertThat(entity.get("ignores")).isEqualTo(3);
        assertThat(entity.get("succes")).isEqualTo(true);
    }

    @Test
    @DisplayName("migrerOrganisations — liste vide → 200 OK avec total=0")
    void migrerOrganisations_emptyList_returns200() throws Exception {
        MigrationReport report = new MigrationReport(0, 0, 0, 0);
        when(migrationService.migrerToutesLesOrganisations()).thenReturn(report);

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(200);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity.get("total")).isEqualTo(0);
        assertThat(entity.get("succes")).isEqualTo(true);
    }

    // ── POST /api/admin/keycloak/migrer-organisations — erreurs partielles ───

    @Test
    @DisplayName("migrerOrganisations — quelques erreurs → 207 Multi-Status avec succes=false")
    void migrerOrganisations_withErrors_returns207() throws Exception {
        MigrationReport report = new MigrationReport(10, 7, 1, 2);
        when(migrationService.migrerToutesLesOrganisations()).thenReturn(report);

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(207);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity.get("total")).isEqualTo(10);
        assertThat(entity.get("crees")).isEqualTo(7);
        assertThat(entity.get("ignores")).isEqualTo(1);
        assertThat(entity.get("erreurs")).isEqualTo(2);
        assertThat(entity.get("succes")).isEqualTo(false);
    }

    @Test
    @DisplayName("migrerOrganisations — toutes en erreur → 207 Multi-Status")
    void migrerOrganisations_allErrors_returns207() throws Exception {
        MigrationReport report = new MigrationReport(4, 0, 0, 4);
        when(migrationService.migrerToutesLesOrganisations()).thenReturn(report);

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(207);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity.get("erreurs")).isEqualTo(4);
        assertThat(entity.get("succes")).isEqualTo(false);
    }

    // ── POST /api/admin/keycloak/migrer-organisations — exception ────────────

    @Test
    @DisplayName("migrerOrganisations — exception du service → 500 avec champ error")
    void migrerOrganisations_serviceThrowsException_returns500() throws Exception {
        when(migrationService.migrerToutesLesOrganisations())
                .thenThrow(new RuntimeException("Keycloak non joignable"));

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(500);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity).containsKey("error");
        assertThat(entity.get("error")).isEqualTo("Keycloak non joignable");
    }

    @Test
    @DisplayName("migrerOrganisations — exception avec message null → 500 avec error=null")
    void migrerOrganisations_exceptionWithNullMessage_returns500() throws Exception {
        when(migrationService.migrerToutesLesOrganisations())
                .thenThrow(new RuntimeException((String) null));

        Response response = resource.migrerOrganisations();

        assertThat(response.getStatus()).isEqualTo(500);
        @SuppressWarnings("unchecked")
        Map<String, Object> entity = (Map<String, Object>) response.getEntity();
        assertThat(entity).containsKey("error");
    }

    // ── MigrationReport.success() — couverture du record ────────────────────

    @Test
    @DisplayName("MigrationReport.success() → true quand erreurs=0")
    void migrationReport_success_trueWhenNoErrors() {
        MigrationReport report = new MigrationReport(5, 5, 0, 0);
        assertThat(report.success()).isTrue();
    }

    @Test
    @DisplayName("MigrationReport.success() → false quand erreurs > 0")
    void migrationReport_success_falseWhenErrors() {
        MigrationReport report = new MigrationReport(5, 3, 0, 2);
        assertThat(report.success()).isFalse();
    }

    @Test
    @DisplayName("MigrationReport — accesseurs total/crees/ignores/erreurs")
    void migrationReport_accessors_returnCorrectValues() {
        MigrationReport report = new MigrationReport(10, 3, 5, 2);
        assertThat(report.total()).isEqualTo(10);
        assertThat(report.crees()).isEqualTo(3);
        assertThat(report.ignores()).isEqualTo(5);
        assertThat(report.erreurs()).isEqualTo(2);
    }
}
