package dev.lions.unionflow.server.api.dto.dashboard;

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

import java.time.LocalDateTime;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;

/**
 * Tests unitaires pour DashboardStatsResponse.
 * Couvre getFormattedContributionAmount (null, >= 1M, >= 1K, else),
 * getHasGrowth, getIsHighEngagement, getInactiveMembers, getActiveMemberPercentage,
 * getEngagementPercentage.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-02-21
 */
@DisplayName("Tests DashboardStatsResponse")
class DashboardStatsResponseTest {

  @Nested
  @DisplayName("Constructeur et getters/setters")
  class ConstructeurEtGetters {

    @Test
    @DisplayName("builder et getters")
    void testBuilder() {
      DashboardStatsResponse dto = DashboardStatsResponse.builder()
          .totalMembers(100)
          .activeMembers(80)
          .totalEvents(10)
          .lastUpdated(LocalDateTime.now())
          .build();
      assertThat(dto.getTotalMembers()).isEqualTo(100);
      assertThat(dto.getActiveMembers()).isEqualTo(80);
      assertThat(dto.getTotalEvents()).isEqualTo(10);
    }
  }

  @Nested
  @DisplayName("getFormattedContributionAmount")
  class GetFormattedContributionAmount {

    @Test
    @DisplayName("retourne 0 quand totalContributionAmount est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalContributionAmount(null);
      assertThat(dto.getFormattedContributionAmount()).isEqualTo("0");
    }

    @Test
    @DisplayName("retourne format M quand >= 1_000_000")
    void testMillions() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalContributionAmount(2_500_000.0);
      String formatted = dto.getFormattedContributionAmount();
      assertThat(formatted).matches("2[.,]5M");
    }

    @Test
    @DisplayName("retourne format K quand >= 1_000 et < 1_000_000")
    void testMilliers() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalContributionAmount(5_000.0);
      assertThat(dto.getFormattedContributionAmount()).isEqualTo("5K");
    }

    @Test
    @DisplayName("retourne format entier quand < 1_000")
    void testPetitMontant() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalContributionAmount(99.0);
      assertThat(dto.getFormattedContributionAmount()).isEqualTo("99");
    }
  }

  @Nested
  @DisplayName("getHasGrowth")
  class GetHasGrowth {

    @Test
    @DisplayName("retourne false quand monthlyGrowth est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setMonthlyGrowth(null);
      assertThat(dto.getHasGrowth()).isFalse();
    }

    @Test
    @DisplayName("retourne false quand monthlyGrowth <= 0")
    void testZeroOuNegatif() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setMonthlyGrowth(0.0);
      assertThat(dto.getHasGrowth()).isFalse();
      dto.setMonthlyGrowth(-1.0);
      assertThat(dto.getHasGrowth()).isFalse();
    }

    @Test
    @DisplayName("retourne true quand monthlyGrowth > 0")
    void testPositif() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setMonthlyGrowth(0.5);
      assertThat(dto.getHasGrowth()).isTrue();
    }
  }

  @Nested
  @DisplayName("getIsHighEngagement")
  class GetIsHighEngagement {

    @Test
    @DisplayName("retourne false quand engagementRate est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setEngagementRate(null);
      assertThat(dto.getIsHighEngagement()).isFalse();
    }

    @Test
    @DisplayName("retourne false quand engagementRate <= 0.7")
    void testFaible() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setEngagementRate(0.5);
      assertThat(dto.getIsHighEngagement()).isFalse();
      dto.setEngagementRate(0.7);
      assertThat(dto.getIsHighEngagement()).isFalse();
    }

    @Test
    @DisplayName("retourne true quand engagementRate > 0.7")
    void testEleve() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setEngagementRate(0.85);
      assertThat(dto.getIsHighEngagement()).isTrue();
    }
  }

  @Nested
  @DisplayName("getInactiveMembers")
  class GetInactiveMembers {

    @Test
    @DisplayName("retourne 0 quand totalMembers ou activeMembers est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalMembers(null);
      dto.setActiveMembers(10);
      assertThat(dto.getInactiveMembers()).isEqualTo(0.0);
      dto.setTotalMembers(100);
      dto.setActiveMembers(null);
      assertThat(dto.getInactiveMembers()).isEqualTo(0.0);
    }

    @Test
    @DisplayName("retourne totalMembers - activeMembers")
    void testCalcul() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalMembers(100);
      dto.setActiveMembers(30);
      assertThat(dto.getInactiveMembers()).isEqualTo(70.0);
    }
  }

  @Nested
  @DisplayName("getActiveMemberPercentage")
  class GetActiveMemberPercentage {

    @Test
    @DisplayName("retourne 0 quand totalMembers ou activeMembers est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalMembers(null);
      dto.setActiveMembers(50);
      assertThat(dto.getActiveMemberPercentage()).isEqualTo(0.0);
      dto.setTotalMembers(100);
      dto.setActiveMembers(null);
      assertThat(dto.getActiveMemberPercentage()).isEqualTo(0.0);
    }

    @Test
    @DisplayName("retourne 0 quand totalMembers est 0")
    void testTotalZero() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalMembers(0);
      dto.setActiveMembers(0);
      assertThat(dto.getActiveMemberPercentage()).isEqualTo(0.0);
    }

    @Test
    @DisplayName("retourne le pourcentage actif")
    void testPourcentage() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setTotalMembers(100);
      dto.setActiveMembers(25);
      assertThat(dto.getActiveMemberPercentage()).isEqualTo(25.0);
    }
  }

  @Nested
  @DisplayName("getEngagementPercentage")
  class GetEngagementPercentage {

    @Test
    @DisplayName("retourne 0 quand engagementRate est null")
    void testNull() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setEngagementRate(null);
      assertThat(dto.getEngagementPercentage()).isEqualTo(0.0);
    }

    @Test
    @DisplayName("retourne engagementRate * 100")
    void testCalcul() {
      DashboardStatsResponse dto = new DashboardStatsResponse();
      dto.setEngagementRate(0.75);
      assertThat(dto.getEngagementPercentage()).isEqualTo(75.0);
    }
  }
}
