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

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

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 FormatExport")
class FormatExportTest {

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

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

    @Test
    @DisplayName("Test toutes les valeurs enum")
    void testToutesValeurs() {
      FormatExport[] values = FormatExport.values();
      assertThat(values).hasSize(11);
    }

    @ParameterizedTest
    @EnumSource(FormatExport.class)
    @DisplayName("Test getters de base pour toutes les valeurs")
    void testGettersBase(FormatExport format) {
      assertThat(format.getLibelle()).isNotNull().isNotEmpty();
      assertThat(format.getExtension()).isNotNull().isNotEmpty();
      assertThat(format.getMimeType()).isNotNull().isNotEmpty();
      assertThat(format.getDescription()).isNotNull().isNotEmpty();
    }
  }

  @Nested
  @DisplayName("Tests supporteGraphiques")
  class SupporteGraphiquesTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, true",
        "WORD, true",
        "EXCEL, true",
        "CSV, false",
        "JSON, false",
        "XML, false",
        "PNG, true",
        "JPEG, true",
        "SVG, true"
    })
    @DisplayName("supporteGraphiques - valeurs exactes")
    void testSupporteGraphiques(FormatExport format, Boolean expected) {
      assertThat(format.supporteGraphiques()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests supporteGrandesQuantitesDonnees")
  class SupporteGrandesQuantitesDonneesTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, true",
        "WORD, false",
        "EXCEL, true",
        "CSV, true",
        "JSON, true",
        "XML, false",
        "PNG, false",
        "JPEG, false"
    })
    @DisplayName("supporteGrandesQuantitesDonnees - valeurs exactes")
    void testSupporteGrandesQuantitesDonnees(FormatExport format, Boolean expected) {
      assertThat(format.supporteGrandesQuantitesDonnees()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests isFormatExecutif")
  class IsFormatExecutifTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, true",
        "POWERPOINT, true",
        "WORD, true",
        "EXCEL, false",
        "CSV, false",
        "JSON, false"
    })
    @DisplayName("isFormatExecutif - formats exécutifs")
    void testIsFormatExecutif(FormatExport format, Boolean expected) {
      assertThat(format.isFormatExecutif()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests isFormatAnalyse")
  class IsFormatAnalyseTests {

    @ParameterizedTest
    @CsvSource({
        "EXCEL, true",
        "CSV, true",
        "JSON, true",
        "PDF, false",
        "WORD, false",
        "XML, false"
    })
    @DisplayName("isFormatAnalyse - formats d'analyse")
    void testIsFormatAnalyse(FormatExport format, Boolean expected) {
      assertThat(format.isFormatAnalyse()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests isFormatWeb")
  class IsFormatWebTests {

    @ParameterizedTest
    @CsvSource({
        "HTML, true",
        "PNG, true",
        "SVG, true",
        "JSON, true",
        "PDF, false",
        "EXCEL, false",
        "WORD, false"
    })
    @DisplayName("isFormatWeb - formats web")
    void testIsFormatWeb(FormatExport format, Boolean expected) {
      assertThat(format.isFormatWeb()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests getIcone")
  class GetIconeTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, picture_as_pdf",
        "WORD, description",
        "EXCEL, table_chart",
        "CSV, grid_on",
        "JSON, code",
        "XML, code",
        "PNG, image",
        "JPEG, image",
        "SVG, vector_image",
        "POWERPOINT, slideshow",
        "HTML, web"
    })
    @DisplayName("getIcone - toutes les icônes")
    void testGetIcone(FormatExport format, String expectedIcone) {
      assertThat(format.getIcone()).isEqualTo(expectedIcone);
    }
  }

  @Nested
  @DisplayName("Tests getCouleur")
  class GetCouleurTests {

    @ParameterizedTest
    @EnumSource(FormatExport.class)
    @DisplayName("getCouleur - toutes les couleurs sont valides")
    void testGetCouleur(FormatExport format) {
      assertThat(format.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
    }
  }

  @Nested
  @DisplayName("Tests genererNomFichier")
  class GenererNomFichierTests {

    @Test
    @DisplayName("genererNomFichier - ajoute l'extension")
    void testGenererNomFichier() {
      assertThat(FormatExport.PDF.genererNomFichier("rapport")).isEqualTo("rapport.pdf");
      assertThat(FormatExport.EXCEL.genererNomFichier("donnees")).isEqualTo("donnees.xlsx");
      assertThat(FormatExport.CSV.genererNomFichier("export")).isEqualTo("export.csv");
    }
  }

  @Nested
  @DisplayName("Tests getTailleMaximaleRecommandee")
  class GetTailleMaximaleRecommandeeTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, 50",
        "WORD, 50",
        "POWERPOINT, 50",
        "EXCEL, 100",
        "CSV, 200",
        "JSON, 200",
        "XML, 200",
        "PNG, 10",
        "JPEG, 10",
        "SVG, 5",
        "HTML, 5"
    })
    @DisplayName("getTailleMaximaleRecommandee - toutes les tailles")
    void testGetTailleMaximaleRecommandee(FormatExport format, int expectedMB) {
      assertThat(format.getTailleMaximaleRecommandee()).isEqualTo(expectedMB);
    }
  }

  @Nested
  @DisplayName("Tests necessiteTraitementSpecial")
  class NecessiteTraitementSpecialTests {

    @ParameterizedTest
    @CsvSource({
        "PDF, true",
        "EXCEL, true",
        "POWERPOINT, true",
        "WORD, true",
        "CSV, false",
        "JSON, false",
        "PNG, false"
    })
    @DisplayName("necessiteTraitementSpecial - formats spéciaux")
    void testNecessiteTraitementSpecial(FormatExport format, Boolean expected) {
      assertThat(format.necessiteTraitementSpecial()).isEqualTo(expected);
    }
  }

  @Nested
  @DisplayName("Tests getFormatsRecommandes")
  class GetFormatsRecommandesTests {

    @Test
    @DisplayName("getFormatsRecommandes - executif")
    void testGetFormatsRecommandesExecutif() {
      FormatExport[] formats = FormatExport.getFormatsRecommandes("executif");
      assertThat(formats).containsExactly(FormatExport.PDF, FormatExport.POWERPOINT, FormatExport.WORD);
    }

    @Test
    @DisplayName("getFormatsRecommandes - analytique")
    void testGetFormatsRecommandesAnalytique() {
      FormatExport[] formats = FormatExport.getFormatsRecommandes("analytique");
      assertThat(formats).containsExactly(FormatExport.EXCEL, FormatExport.CSV, FormatExport.JSON, FormatExport.PDF);
    }

    @Test
    @DisplayName("getFormatsRecommandes - technique")
    void testGetFormatsRecommandesTechnique() {
      FormatExport[] formats = FormatExport.getFormatsRecommandes("technique");
      assertThat(formats).containsExactly(FormatExport.JSON, FormatExport.XML, FormatExport.CSV, FormatExport.HTML);
    }

    @Test
    @DisplayName("getFormatsRecommandes - partage")
    void testGetFormatsRecommandesPartage() {
      FormatExport[] formats = FormatExport.getFormatsRecommandes("partage");
      assertThat(formats).containsExactly(FormatExport.PDF, FormatExport.PNG, FormatExport.HTML);
    }

    @Test
    @DisplayName("getFormatsRecommandes - type inconnu")
    void testGetFormatsRecommandesInconnu() {
      FormatExport[] formats = FormatExport.getFormatsRecommandes("inconnu");
      assertThat(formats).containsExactly(FormatExport.PDF, FormatExport.EXCEL, FormatExport.CSV);
    }
  }
}

