package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.MembreSuivi;
import dev.lions.unionflow.server.repository.MembreRepository;
import dev.lions.unionflow.server.repository.MembreSuiviRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.jboss.logging.Logger;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Service pour la gestion du suivi entre membres (Réseau).
 */
@ApplicationScoped
public class MembreSuiviService {

    private static final Logger LOG = Logger.getLogger(MembreSuiviService.class);

    @Inject
    MembreSuiviRepository membreSuiviRepository;

    @Inject
    MembreRepository membreRepository;

    /**
     * Suit un membre. Si déjà suivi, reste suivi.
     *
     * @param currentUserEmail email du membre connecté
     * @param suiviId          id du membre à suivre (utilisateur)
     * @return true si le membre est suivi après l’appel
     */
    @Transactional
    public boolean follow(String currentUserEmail, UUID suiviId) {
        Membre follower = membreRepository.findByEmail(currentUserEmail)
            .orElseThrow(() -> new IllegalArgumentException("Membre connecté introuvable"));
        UUID followerId = follower.getId();
        if (followerId.equals(suiviId)) {
            throw new IllegalArgumentException("Impossible de se suivre soi-même");
        }
        if (membreRepository.findByIdOptional(suiviId).isEmpty()) {
            throw new IllegalArgumentException("Membre cible introuvable");
        }
        if (membreSuiviRepository.findByFollowerAndSuivi(followerId, suiviId).isPresent()) {
            LOG.infof("Déjà suivi: %s -> %s", followerId, suiviId);
            return true;
        }
        MembreSuivi suivi = MembreSuivi.builder()
            .followerUtilisateurId(followerId)
            .suiviUtilisateurId(suiviId)
            .build();
        membreSuiviRepository.persist(suivi);
        LOG.infof("Suivi ajouté: %s -> %s", followerId, suiviId);
        return true;
    }

    /**
     * Ne plus suivre un membre.
     *
     * @param currentUserEmail email du membre connecté
     * @param suiviId          id du membre à ne plus suivre
     * @return false (plus suivi)
     */
    @Transactional
    public boolean unfollow(String currentUserEmail, UUID suiviId) {
        Membre follower = membreRepository.findByEmail(currentUserEmail)
            .orElseThrow(() -> new IllegalArgumentException("Membre connecté introuvable"));
        UUID followerId = follower.getId();
        membreSuiviRepository.findByFollowerAndSuivi(followerId, suiviId)
            .ifPresent(membreSuiviRepository::delete);
        LOG.infof("Suivi supprimé: %s -> %s", followerId, suiviId);
        return false;
    }

    /**
     * Indique si le membre connecté suit le membre cible.
     */
    public boolean isFollowing(String currentUserEmail, UUID suiviId) {
        Membre follower = membreRepository.findByEmail(currentUserEmail).orElse(null);
        if (follower == null) return false;
        return membreSuiviRepository.findByFollowerAndSuivi(follower.getId(), suiviId).isPresent();
    }

    /**
     * Liste des ids des membres suivis par l’utilisateur connecté.
     */
    public List<UUID> getFollowedIds(String currentUserEmail) {
        Membre follower = membreRepository.findByEmail(currentUserEmail).orElse(null);
        if (follower == null) return List.of();
        return membreSuiviRepository.findByFollower(follower.getId()).stream()
            .map(MembreSuivi::getSuiviUtilisateurId)
            .collect(Collectors.toList());
    }
}
