package dev.lions.unionflow.server.api.enums.organisation;

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.EnumSource;

@DisplayName("Tests pour TypeOrganisation")
class TypeOrganisationTest {

  @Test
  @DisplayName("Test de base - enum peut être utilisé")
  void testEnumUtilisable() {
    assertThat(TypeOrganisation.LIONS_CLUB).isNotNull();
  }

  @Nested
  @DisplayName("Tests des valeurs enum")
  class TestsValeursEnum {

    @Test
    @DisplayName("Test toutes les valeurs enum")
    void testToutesValeurs() {
      TypeOrganisation[] values = TypeOrganisation.values();
      assertThat(values).hasSize(8);
      assertThat(values).containsExactly(
          TypeOrganisation.LIONS_CLUB,
          TypeOrganisation.ASSOCIATION,
          TypeOrganisation.FEDERATION,
          TypeOrganisation.COOPERATIVE,
          TypeOrganisation.MUTUELLE,
          TypeOrganisation.SYNDICAT,
          TypeOrganisation.FONDATION,
          TypeOrganisation.ONG);
    }

    @Test
    @DisplayName("Test valueOf")
    void testValueOf() {
      assertThat(TypeOrganisation.valueOf("LIONS_CLUB")).isEqualTo(TypeOrganisation.LIONS_CLUB);
      assertThat(TypeOrganisation.valueOf("ASSOCIATION")).isEqualTo(TypeOrganisation.ASSOCIATION);
      assertThat(TypeOrganisation.valueOf("FEDERATION")).isEqualTo(TypeOrganisation.FEDERATION);
      assertThat(TypeOrganisation.valueOf("COOPERATIVE")).isEqualTo(TypeOrganisation.COOPERATIVE);
      assertThat(TypeOrganisation.valueOf("MUTUELLE")).isEqualTo(TypeOrganisation.MUTUELLE);
      assertThat(TypeOrganisation.valueOf("SYNDICAT")).isEqualTo(TypeOrganisation.SYNDICAT);
      assertThat(TypeOrganisation.valueOf("FONDATION")).isEqualTo(TypeOrganisation.FONDATION);
      assertThat(TypeOrganisation.valueOf("ONG")).isEqualTo(TypeOrganisation.ONG);

      assertThatThrownBy(() -> TypeOrganisation.valueOf("INEXISTANT"))
          .isInstanceOf(IllegalArgumentException.class);
    }

    @ParameterizedTest
    @EnumSource(TypeOrganisation.class)
    @DisplayName("Test getLibelle pour toutes les valeurs")
    void testGetLibelle(TypeOrganisation type) {
      assertThat(type.getLibelle()).isNotNull().isNotEmpty();
    }

    @ParameterizedTest
    @CsvSource({
        "LIONS_CLUB, Lions Club",
        "ASSOCIATION, Association",
        "FEDERATION, Fédération",
        "COOPERATIVE, Coopérative",
        "MUTUELLE, Mutuelle",
        "SYNDICAT, Syndicat",
        "FONDATION, Fondation",
        "ONG, ONG"
    })
    @DisplayName("Test getLibelle avec valeurs exactes")
    void testGetLibelleValeursExactes(TypeOrganisation type, String expectedLibelle) {
      assertThat(type.getLibelle()).isEqualTo(expectedLibelle);
    }

    @Test
    @DisplayName("Test ordinal et name")
    void testOrdinalEtName() {
      assertThat(TypeOrganisation.LIONS_CLUB.ordinal()).isEqualTo(0);
      assertThat(TypeOrganisation.ASSOCIATION.ordinal()).isEqualTo(1);
      assertThat(TypeOrganisation.FEDERATION.ordinal()).isEqualTo(2);
      assertThat(TypeOrganisation.COOPERATIVE.ordinal()).isEqualTo(3);
      assertThat(TypeOrganisation.MUTUELLE.ordinal()).isEqualTo(4);
      assertThat(TypeOrganisation.SYNDICAT.ordinal()).isEqualTo(5);
      assertThat(TypeOrganisation.FONDATION.ordinal()).isEqualTo(6);
      assertThat(TypeOrganisation.ONG.ordinal()).isEqualTo(7);
    }
  }
}

