package dev.lions.unionflow.server.service.pep;

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

import java.time.LocalDate;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class InMemoryPepScreeningProviderTest {

  private final InMemoryPepScreeningProvider provider = new InMemoryPepScreeningProvider();

  @Test
  @DisplayName("providerName + isAvailable")
  void infoBase() {
    assertThat(provider.providerName()).isEqualTo("InMemory");
    assertThat(provider.isAvailable()).isTrue();
  }

  @Test
  @DisplayName("Match exact retourne PEP=true avec score 1.0")
  void matchExact() {
    var result = provider.screen("EXEMPLE", "Demo Pep", LocalDate.of(1970, 1, 1), "CIV");
    assertThat(result.estPep()).isTrue();
    assertThat(result.matches()).hasSize(1);
    assertThat(result.matches().get(0).scoreSimilarite()).isEqualTo(1.0);
    assertThat(result.warningMessage()).contains("non exhaustive");
  }

  @Test
  @DisplayName("Nationalité différente filtre le match")
  void nationaliteDifferente() {
    var result = provider.screen("EXEMPLE", "Demo Pep", LocalDate.of(1970, 1, 1), "FRA");
    assertThat(result.estPep()).isFalse();
  }

  @Test
  @DisplayName("Aucune nationalité spécifiée → match toujours")
  void nationaliteAbsenteMatch() {
    var result = provider.screen("EXEMPLE", "Demo Pep", null, null);
    assertThat(result.estPep()).isTrue();
  }

  @Test
  @DisplayName("Nom inconnu retourne PEP=false")
  void nomInconnu() {
    var result = provider.screen("Inconnu", "Personne", LocalDate.of(1980, 6, 15), "CIV");
    assertThat(result.estPep()).isFalse();
    assertThat(result.matches()).isEmpty();
  }

  @Test
  @DisplayName("Nom/prénoms vides retourne PEP=false sans erreur")
  void nomVide() {
    assertThat(provider.screen(null, null, null, null).estPep()).isFalse();
    assertThat(provider.screen("", "", null, null).estPep()).isFalse();
  }

  @Test
  @DisplayName("Similarité Levenshtein : strings identiques = 1.0")
  void similarityIdentical() {
    assertThat(InMemoryPepScreeningProvider.computeSimilarity("abc", "abc")).isEqualTo(1.0);
  }

  @Test
  @DisplayName("Similarité Levenshtein : strings vides = 0.0")
  void similarityEmpty() {
    assertThat(InMemoryPepScreeningProvider.computeSimilarity("", "")).isEqualTo(0.0);
  }

  @Test
  @DisplayName("Similarité Levenshtein : 1 substitution sur 3 chars ≈ 0.667")
  void similarityOneSub() {
    assertThat(InMemoryPepScreeningProvider.computeSimilarity("abc", "abd"))
        .isCloseTo(0.667, org.assertj.core.data.Offset.offset(0.01));
  }
}
