package dev.lions.unionflow.server.service;

import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.messaging.*;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.List;
import java.util.Optional;

/**
 * Service d'envoi de notifications push via Firebase Cloud Messaging (FCM).
 *
 * <p>Configuration requise (application-prod.properties) :
 * <pre>
 *   firebase.service-account-key-path=/opt/unionflow/firebase-service-account.json
 * </pre>
 *
 * <p>En dev/test, le service est désactivé si le fichier n'existe pas.
 */
@Slf4j
@ApplicationScoped
public class FirebasePushService {

    @ConfigProperty(name = "firebase.service-account-key-path")
    Optional<String> serviceAccountKeyPathOpt;

    String serviceAccountKeyPath;
    private boolean initialized = false;

    @PostConstruct
    void init() {
        serviceAccountKeyPath = serviceAccountKeyPathOpt.orElse("");
        if (serviceAccountKeyPath.isBlank()) {
            log.info("Firebase FCM désactivé (firebase.service-account-key-path non configuré)");
            return;
        }
        try {
            if (FirebaseApp.getApps().isEmpty()) {
                InputStream serviceAccount = new FileInputStream(serviceAccountKeyPath);
                FirebaseOptions options = FirebaseOptions.builder()
                        .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                        .build();
                FirebaseApp.initializeApp(options);
            }
            initialized = true;
            log.info("Firebase FCM initialisé depuis {}", serviceAccountKeyPath);
        } catch (Exception e) {
            log.warn("Firebase FCM non initialisé ({}): {} — les notifications push seront ignorées",
                    serviceAccountKeyPath, e.getMessage());
        }
    }

    /**
     * Envoie une notification push à un token FCM unique.
     *
     * @param token   token FCM du device cible
     * @param titre   titre de la notification
     * @param corps   corps de la notification
     * @param data    données supplémentaires (payload JSON key/value)
     * @return `true` si envoi réussi, `false` sinon
     */
    public boolean envoyerNotification(String token, String titre, String corps,
                                        java.util.Map<String, String> data) {
        if (!initialized || token == null || token.isBlank()) return false;

        try {
            Message.Builder builder = Message.builder()
                    .setToken(token)
                    .setNotification(Notification.builder()
                            .setTitle(titre)
                            .setBody(corps)
                            .build());

            if (data != null && !data.isEmpty()) {
                builder.putAllData(data);
            }

            String response = FirebaseMessaging.getInstance().send(builder.build());
            log.info("FCM push envoyé : messageId={}", response);
            return true;
        } catch (FirebaseMessagingException e) {
            if (MessagingErrorCode.UNREGISTERED.equals(e.getMessagingErrorCode())
                    || MessagingErrorCode.INVALID_ARGUMENT.equals(e.getMessagingErrorCode())) {
                log.warn("Token FCM invalide/expiré : {}", token);
            } else {
                log.error("Erreur FCM pour token {}: {} ({})", token, e.getMessage(), e.getMessagingErrorCode());
            }
            return false;
        }
    }

    /**
     * Envoie une notification push à une liste de tokens (multicast, max 500).
     *
     * @return nombre de messages envoyés avec succès
     */
    public int envoyerNotificationMulticast(List<String> tokens, String titre, String corps,
                                             java.util.Map<String, String> data) {
        if (!initialized || tokens == null || tokens.isEmpty()) return 0;

        // FCM multicast : max 500 tokens par appel
        List<String> validTokens = tokens.stream()
                .filter(t -> t != null && !t.isBlank())
                .limit(500)
                .toList();
        if (validTokens.isEmpty()) return 0;

        try {
            MulticastMessage.Builder builder = MulticastMessage.builder()
                    .addAllTokens(validTokens)
                    .setNotification(Notification.builder()
                            .setTitle(titre)
                            .setBody(corps)
                            .build());

            if (data != null && !data.isEmpty()) {
                builder.putAllData(data);
            }

            BatchResponse response = FirebaseMessaging.getInstance().sendEachForMulticast(builder.build());
            log.info("FCM multicast : {}/{} envoyés avec succès", response.getSuccessCount(), validTokens.size());
            return response.getSuccessCount();
        } catch (FirebaseMessagingException e) {
            log.error("Erreur FCM multicast : {}", e.getMessage(), e);
            return 0;
        }
    }

    public boolean isAvailable() {
        return initialized;
    }
}
