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

import dev.lions.unionflow.server.security.AuditTrailService;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Service de screening PEP avec cache 24 h et audit trail.
 *
 * <p>Délègue au {@link PepScreeningProvider} configuré (par défaut {@link
 * InMemoryPepScreeningProvider}). Toute requête de screening est tracée dans {@code
 * audit_trail_operations} (action_type {@code KYC_VALIDE} ou {@code SOD_OVERRIDE} si match
 * critique).
 *
 * <p>Cache 24 h pour éviter de surconsommer les API commerciales (Youverify facture par
 * requête).
 *
 * @since 2026-04-25 (P1-NEW-11)
 */
@ApplicationScoped
public class PepScreeningService {

  private static final Duration CACHE_TTL = Duration.ofHours(24);
  private static final int CACHE_MAX_SIZE = 5_000;

  @Inject PepScreeningProvider provider;
  @Inject AuditTrailService auditTrail;

  private final Map<String, CachedResult> cache = new LinkedHashMap<>(CACHE_MAX_SIZE) {
    @Override
    protected boolean removeEldestEntry(Map.Entry<String, CachedResult> eldest) {
      return size() > CACHE_MAX_SIZE;
    }
  };

  /**
   * Vérifie si une personne est PEP. Utilise le cache 24 h, puis le provider.
   *
   * @param entityId UUID du membre/UBO concerné (pour audit trail)
   */
  public synchronized PepScreeningProvider.PepScreeningResult verifierPep(
      UUID entityId, String nom, String prenoms, LocalDate dateNaissance, String nationalite) {

    String key = cacheKey(nom, prenoms, dateNaissance, nationalite);
    CachedResult cached = cache.get(key);
    Instant now = Instant.now();
    if (cached != null && cached.expiresAt.isAfter(now)) {
      return cached.result;
    }

    PepScreeningProvider.PepScreeningResult result =
        provider.screen(nom, prenoms, dateNaissance, nationalite);
    cache.put(key, new CachedResult(result, now.plus(CACHE_TTL)));

    if (result.estPep()) {
      auditTrail.logSimple("Membre", entityId, "KYC_VALIDE",
          "PEP match détecté via " + provider.providerName()
              + " : " + result.matches().size() + " match(es)");
    }

    return result;
  }

  private static String cacheKey(String nom, String prenoms, LocalDate dn, String nat) {
    return String.join("|",
        nom == null ? "" : nom.toLowerCase(),
        prenoms == null ? "" : prenoms.toLowerCase(),
        dn == null ? "" : dn.toString(),
        nat == null ? "" : nat.toUpperCase());
  }

  private record CachedResult(
      PepScreeningProvider.PepScreeningResult result,
      Instant expiresAt
  ) {}
}
