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

import dev.lions.unionflow.server.entity.Devise;
import dev.lions.unionflow.server.entity.KycDossier;
import dev.lions.unionflow.server.entity.Membre;
import jakarta.enterprise.context.ApplicationScoped;
import java.math.BigDecimal;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * Validations spécifiques aux membres diaspora (non-résidents UEMOA).
 *
 * <p>Couvre :
 * <ul>
 *   <li>Cohérence des champs diaspora (passeport, pays résidence, fiscalité)</li>
 *   <li>Détermination du niveau de due diligence (Instruction BCEAO 001-03-2025)</li>
 *   <li>Validation du seuil AML pour transferts internationaux</li>
 * </ul>
 *
 * <p>La liste FATF grey-list est synchronisée manuellement (à automatiser via veille).
 *
 * @since 2026-04-25 (P2-NEW-7)
 */
@ApplicationScoped
public class KycDiasporaService {

  /** Pays UEMOA (résidents non-diaspora). */
  static final Set<String> PAYS_UEMOA = Set.of(
      "CIV", // Côte d'Ivoire
      "BEN", // Bénin
      "BFA", // Burkina Faso
      "GNB", // Guinée-Bissau
      "MLI", // Mali
      "NER", // Niger
      "SEN", // Sénégal
      "TGO"  // Togo
  );

  /** Liste FATF grey-list au 2026-04-25 (snapshot manuel). */
  static final Set<String> PAYS_GREY_LIST_FATF = Set.of(
      "BLZ", "BGR", "BFA", "CMR", "COD", "GIB", "HTI", "JAM", "KEN",
      "MLI", "MOZ", "NAM", "NGA", "PHL", "SEN", "SYR", "TZA", "TUR",
      "VEN", "VNM", "YEM", "ZAF"
  );

  /** Seuil AML (en EUR) au-delà duquel un transfert international déclenche reporting. */
  static final BigDecimal SEUIL_AML_INTERNATIONAL_EUR = new BigDecimal("1000");

  /** Format passeport générique (alphanumérique 5-15 caractères selon pays). */
  static final Pattern PASSEPORT_PATTERN = Pattern.compile("^[A-Z0-9]{5,15}$");

  /**
   * Valide la cohérence des champs diaspora d'un membre.
   *
   * @return liste des erreurs de validation (vide si tout est OK)
   */
  public List<String> validerCoherence(Membre membre) {
    if (membre == null) {
      return List.of("Membre null");
    }

    List<String> erreurs = new java.util.ArrayList<>();

    if (Boolean.TRUE.equals(membre.getEstDiaspora())) {
      // Si est_diaspora=true, paysResidence doit être renseigné et hors UEMOA
      if (membre.getPaysResidence() == null || membre.getPaysResidence().isBlank()) {
        erreurs.add("Membre diaspora : pays_residence obligatoire (ISO-3)");
      } else if (PAYS_UEMOA.contains(membre.getPaysResidence())) {
        erreurs.add("Membre diaspora : pays_residence ne peut être un pays UEMOA");
      }
      if (membre.getNumeroPasseport() == null || membre.getNumeroPasseport().isBlank()) {
        erreurs.add("Membre diaspora : numero_passeport obligatoire");
      } else if (!PASSEPORT_PATTERN.matcher(membre.getNumeroPasseport()).matches()) {
        erreurs.add("numero_passeport : format invalide (5-15 caractères alphanumériques)");
      }
    } else {
      // Membre non-diaspora : si paysResidence est posé, il doit être UEMOA
      if (membre.getPaysResidence() != null && !membre.getPaysResidence().isBlank()
          && !PAYS_UEMOA.contains(membre.getPaysResidence())) {
        erreurs.add(
            "Incohérence : pays_residence hors UEMOA mais est_diaspora=false. "
                + "Mettre est_diaspora=true ou corriger pays_residence.");
      }
    }

    return erreurs;
  }

  /**
   * Détermine le niveau de due diligence applicable selon profil membre + KYC.
   *
   * <p>Règles :
   * <ul>
   *   <li>RENFORCE — diaspora hors UE/G7, PEP, FATF grey-list</li>
   *   <li>STANDARD — diaspora UE/G7, KYC validé</li>
   *   <li>SIMPLIFIE — résident UEMOA, opérations &lt; seuil et risque faible</li>
   * </ul>
   */
  public String determinerNiveauDueDiligence(Membre membre, KycDossier kyc) {
    if (membre == null || kyc == null) {
      return "STANDARD";
    }

    if (kyc.isEstPep()) return "RENFORCE";

    if (Boolean.TRUE.equals(membre.getEstDiaspora())) {
      String pays = membre.getPaysResidence();
      if (pays == null) return "RENFORCE";
      if (PAYS_GREY_LIST_FATF.contains(pays)) return "RENFORCE";

      // Diaspora "occidentale" sécurisée → STANDARD
      Set<String> paysSecurises = Set.of("FRA", "BEL", "DEU", "CHE", "ITA", "ESP", "PRT",
          "GBR", "IRL", "USA", "CAN", "AUS", "NZL", "JPN", "KOR");
      if (paysSecurises.contains(pays)) return "STANDARD";

      // Autres pays diaspora → RENFORCE par défaut
      return "RENFORCE";
    }

    return "STANDARD";
  }

  /**
   * Vérifie si un transfert international dépasse le seuil de reporting AML.
   *
   * @param montant         montant du transfert
   * @param devise          devise du montant
   * @param tauxVersEur     taux de change devise → EUR (BigDecimal). Si null et devise=EUR, OK.
   * @return true si le transfert nécessite un reporting AML renforcé
   */
  public boolean depasseSeuilAmlInternational(BigDecimal montant, Devise devise,
                                               BigDecimal tauxVersEur) {
    if (montant == null) return false;
    if (devise == null) return false;
    // Seules les devises internationales déclenchent le reporting AML international.
    // XOF/XAF et autres devises locales restent dans le seuil AML domestique BCEAO 001-03-2025.
    if (!devise.estInternationale()) return false;

    BigDecimal montantEur;
    if (devise == Devise.EUR) {
      montantEur = montant;
    } else if (tauxVersEur == null) {
      // Pas de taux disponible → considérer comme dépassé par prudence (false positive AML > false negative)
      return true;
    } else {
      montantEur = montant.multiply(tauxVersEur);
    }

    return montantEur.compareTo(SEUIL_AML_INTERNATIONAL_EUR) >= 0;
  }
}
