package dev.lions.unionflow.server.service;

import dev.lions.unionflow.server.entity.MembreOrganisation;
import dev.lions.unionflow.server.entity.MembreRole;
import dev.lions.unionflow.server.repository.MembreRoleRepository;
import dev.lions.unionflow.server.repository.RoleRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.transaction.Transactional;
import java.time.LocalDate;
import org.jboss.logging.Logger;

/**
 * Synchronise le rôle DB (MembreRole) avec le rôle Keycloak au premier accès.
 *
 * <p>Lorsqu'un utilisateur est admin dans Keycloak (rôle {@code ADMIN_ORGANISATION})
 * mais n'a pas encore de ligne {@code MembreRole ORGADMIN} en base, ce service la
 * crée à la volée. Cela couvre deux cas :
 * <ol>
 *   <li>Comptes créés directement dans Keycloak sans passer par
 *       {@code MembreService#promouvoirAdminOrganisation}.</li>
 *   <li>Bases de données en dev qui ont démarré avant la migration V30.</li>
 * </ol>
 */
@ApplicationScoped
public class MembreRoleSyncService {

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

    @Inject
    MembreRoleRepository membreRoleRepository;

    @Inject
    RoleRepository roleRepository;

    @PersistenceContext
    EntityManager entityManager;

    /**
     * Assure qu'un MembreRole ORGADMIN existe pour ce MembreOrganisation.
     * Idempotent : sans effet si l'entrée existe déjà.
     *
     * @param mo MembreOrganisation de l'admin (non null)
     */
    @Transactional
    public void ensureOrgAdminRole(MembreOrganisation mo) {
        if (mo == null || mo.getId() == null || mo.getOrganisation() == null) {
            return;
        }

        // Vérifier si un MembreRole ORGADMIN actif existe déjà pour ce membre dans cette org
        long existing = membreRoleRepository.count(
            "membreOrganisation.id = ?1 AND role.code = ?2 AND actif = true",
            mo.getId(), "ORGADMIN");

        if (existing > 0) {
            return; // Déjà en place — rien à faire
        }

        // Chercher le rôle ORGADMIN dans la table roles
        roleRepository.findByCode("ORGADMIN").ifPresentOrElse(
            role -> {
                MembreRole mr = new MembreRole();
                mr.setMembreOrganisation(mo);
                mr.setOrganisation(mo.getOrganisation());
                mr.setRole(role);
                mr.setActif(true);
                mr.setDateDebut(LocalDate.now());
                entityManager.persist(mr);
                LOG.infof(
                    "MembreRole ORGADMIN auto-sync créé pour membre %s dans org %s",
                    mo.getMembre() != null ? mo.getMembre().getId() : "?",
                    mo.getOrganisation().getId());
            },
            () -> LOG.warnf(
                "Rôle ORGADMIN introuvable dans la table roles — "
                + "vérifier que V13__Seed_Standard_Roles.sql a été appliqué")
        );
    }
}
