package fr.titionfire.ffsaf.domain.service;

import fr.titionfire.ffsaf.data.repository.LicenceRepository;
import fr.titionfire.ffsaf.rest.data.LicenceStats;
import fr.titionfire.ffsaf.utils.Categorie;
import fr.titionfire.ffsaf.utils.Genre;
import fr.titionfire.ffsaf.utils.Utils;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.hibernate.reactive.mutiny.Mutiny;

import java.util.concurrent.ConcurrentHashMap;

@WithSession
@ApplicationScoped
public class StatsService {

    @Inject
    LicenceRepository licenceRepository;

    public Uni<LicenceStats> getStats() {
        ConcurrentHashMap<Categorie, Integer> categories = new ConcurrentHashMap<>();
        LicenceStats stats = new LicenceStats();
        int currentSaison = Utils.getSaison();

        //noinspection ReactiveStreamsUnusedPublisher
        return licenceRepository.listAll()
                .onItem().transformToMulti(licences -> Multi.createFrom().iterable(licences))
                .call(licence -> Mutiny.fetch(licence.getMembre()))
                .invoke(licence -> {
                    if (!stats.getLicences().containsKey(licence.getSaison()))
                        stats.getLicences().put(licence.getSaison(), new LicenceStats.YearStats());

                    LicenceStats.YearStats yearStats = stats.getLicences().get(licence.getSaison());

                    // System.out.println("stats: " + licence.getMembre().getFname());
                    if (licence.isValidate()) {
                        if (licence.getMembre().getGenre() == Genre.H)
                            yearStats.addH();
                        else if (licence.getMembre().getGenre() == Genre.F)
                            yearStats.addF();
                        else
                            yearStats.addNa();

                        if (licence.getSaison() == currentSaison && licence.getMembre().getCategorie() != null) {
                            categories.put(licence.getMembre().getCategorie(),
                                    categories.getOrDefault(licence.getMembre().getCategorie(), 0) + 1);
                        }
                    } else {
                        yearStats.addNotValid();
                    }

                })
                .collect().asList()
                .map(__ -> {
                    for (Categorie c : Categorie.values()) {
                        LicenceStats.CategoriesStats o = new LicenceStats.CategoriesStats();

                        o.setName(c.getName());
                        o.setCount(categories.getOrDefault(c, 0));

                        stats.getCategories().add(o);
                    }

                    return stats;
                });
    }
}
