package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.entity.AlerteLcbFt;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.repository.AlerteLcbFtRepository;
import dev.lions.unionflow.server.repository.MembreRepository;
import dev.lions.unionflow.server.repository.OrganisationRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.UUID;

/**
 * Service pour la génération automatique d'alertes LCB-FT.
 *
 * @author UnionFlow Team
 * @version 1.0
 * @since 2026-03-15
 */
@Slf4j
@ApplicationScoped
public class AlerteLcbFtService {

    @Inject
    AlerteLcbFtRepository alerteLcbFtRepository;

    @Inject
    OrganisationRepository organisationRepository;

    @Inject
    MembreRepository membreRepository;

    /**
     * Génère une alerte lorsqu'un seuil LCB-FT est dépassé.
     */
    @Transactional
    public void genererAlerteSeuilDepasse(
            UUID organisationId,
            UUID membreId,
            String typeOperation,
            BigDecimal montant,
            BigDecimal seuil,
            String transactionRef,
            String origineFonds
    ) {
        try {
            Organisation organisation = organisationRepository.findByIdOptional(organisationId)
                    .orElse(null);

            Membre membre = membreId != null ? membreRepository.findByIdOptional(membreId).orElse(null) : null;

            String description = String.format(
                    "Transaction %s de %s FCFA dépassant le seuil LCB-FT de %s FCFA",
                    typeOperation != null ? typeOperation : "inconnue",
                    montant != null ? montant.toPlainString() : "0",
                    seuil != null ? seuil.toPlainString() : "0"
            );

            String details = String.format(
                    "Référence: %s | Origine des fonds: %s | Écart: %s FCFA",
                    transactionRef != null ? transactionRef : "N/A",
                    origineFonds != null && !origineFonds.isBlank() ? origineFonds : "NON FOURNI",
                    montant != null && seuil != null ? montant.subtract(seuil).toPlainString() : "N/A"
            );

            // Déterminer la sévérité selon l'écart avec le seuil
            String severite = "INFO";
            if (montant != null && seuil != null) {
                BigDecimal ecart = montant.subtract(seuil);
                BigDecimal ratio = seuil.compareTo(BigDecimal.ZERO) > 0 ?
                        ecart.divide(seuil, 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

                if (ratio.compareTo(new BigDecimal("2.0")) >= 0) { // > 200% du seuil
                    severite = "CRITICAL";
                } else if (ratio.compareTo(new BigDecimal("0.5")) >= 0) { // > 50% du seuil
                    severite = "WARNING";
                }
            }

            // Vérifier si origine des fonds est fournie
            if (origineFonds == null || origineFonds.isBlank()) {
                details += " | ⚠️ JUSTIFICATION MANQUANTE";
                severite = "WARNING"; // Toujours WARNING minimum si pas de justification
            }

            AlerteLcbFt alerte = AlerteLcbFt.builder()
                    .organisation(organisation)
                    .membre(membre)
                    .typeAlerte("SEUIL_DEPASSE")
                    .dateAlerte(LocalDateTime.now())
                    .description(description)
                    .details(details)
                    .montant(montant)
                    .seuil(seuil)
                    .typeOperation(typeOperation)
                    .transactionRef(transactionRef)
                    .severite(severite)
                    .traitee(false)
                    .build();

            alerteLcbFtRepository.persist(alerte);

            log.info("Alerte LCB-FT générée : {} - Sévérité: {} - Montant: {} FCFA",
                    alerte.getId(), severite, montant);

        } catch (Exception e) {
            // Ne pas bloquer la transaction si la génération d'alerte échoue
            log.error("Erreur lors de la génération d'alerte LCB-FT", e);
        }
    }

    /**
     * Marque une alerte comme traitée.
     *
     * @return l'alerte mise à jour, ou {@code null} si elle n'existe pas
     */
    @Transactional
    public AlerteLcbFt traiterAlerte(UUID alerteId, UUID traiteParId, String commentaire) {
        AlerteLcbFt alerte = alerteLcbFtRepository.findById(alerteId);
        if (alerte == null) return null;
        alerte.setTraitee(true);
        alerte.setDateTraitement(LocalDateTime.now());
        alerte.setTraitePar(traiteParId);
        alerte.setCommentaireTraitement(commentaire);
        alerteLcbFtRepository.persist(alerte);
        return alerte;
    }

    /**
     * Génère une alerte pour justification manquante.
     */
    @Transactional
    public void genererAlerteJustificationManquante(
            UUID organisationId,
            UUID membreId,
            String typeOperation,
            BigDecimal montant,
            String transactionRef
    ) {
        try {
            Organisation organisation = organisationRepository.findByIdOptional(organisationId)
                    .orElse(null);

            Membre membre = membreId != null ? membreRepository.findByIdOptional(membreId).orElse(null) : null;

            String description = String.format(
                    "Origine des fonds non fournie pour %s de %s FCFA",
                    typeOperation != null ? typeOperation : "transaction",
                    montant != null ? montant.toPlainString() : "0"
            );

            AlerteLcbFt alerte = AlerteLcbFt.builder()
                    .organisation(organisation)
                    .membre(membre)
                    .typeAlerte("JUSTIFICATION_MANQUANTE")
                    .dateAlerte(LocalDateTime.now())
                    .description(description)
                    .details("Référence: " + (transactionRef != null ? transactionRef : "N/A"))
                    .montant(montant)
                    .typeOperation(typeOperation)
                    .transactionRef(transactionRef)
                    .severite("WARNING")
                    .traitee(false)
                    .build();

            alerteLcbFtRepository.persist(alerte);

            log.warn("Alerte justification manquante générée pour transaction: {}", transactionRef);

        } catch (Exception e) {
            log.error("Erreur lors de la génération d'alerte justification manquante", e);
        }
    }
}
