package fr.titionfire.ffsaf.ws.send;

import fr.titionfire.ffsaf.data.model.CompetitionGuestModel;
import fr.titionfire.ffsaf.data.model.RegisterModel;
import fr.titionfire.ffsaf.domain.entity.CombEntity;
import fr.titionfire.ffsaf.domain.service.CardService;
import fr.titionfire.ffsaf.net2.MessageType;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import fr.titionfire.ffsaf.ws.MessageOut;
import fr.titionfire.ffsaf.ws.PermLevel;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.OpenConnections;
import io.quarkus.websockets.next.UserData;
import io.smallrye.mutiny.Uni;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.hibernate.reactive.mutiny.Mutiny;

import java.util.List;
import java.util.UUID;

@ApplicationScoped
@RegisterForReflection
public class SRegister {

    @SuppressWarnings("CdiInjectionPointsInspection")
    @Inject
    OpenConnections connections;

    @Inject
    CardService cardService;

    public Uni<Void> sendRegister(String uuid, RegisterModel registerModel) {
        return Mutiny.fetch(registerModel.getCategoriesInscrites()).chain(o ->
                send(uuid, "sendRegister", CombEntity.fromModel(registerModel).addCategoriesInscrites(o))
                        .call(__ -> registerModel.getClub2() == null ? Uni.createFrom().voidItem() :
                                cardService.addTeamCartToNewComb(registerModel.getMembre().getId(),
                                                registerModel.getClub2().getClubId(), registerModel.getClub2().getName(),
                                                registerModel.getCompetition())
                                        .chain(cardModels -> send(uuid, "sendCards", cardModels))));
    }

    public Uni<Void> sendRegisterNoFetch(String uuid, RegisterModel registerModel) {
        return send(uuid, "sendRegister",
                CombEntity.fromModel(registerModel).addCategoriesInscrites(registerModel.getCategoriesInscrites()))
                .call(__ -> registerModel.getClub2() == null ? Uni.createFrom().voidItem() :
                        cardService.addTeamCartToNewComb(registerModel.getMembre().getId(),
                                        registerModel.getClub2().getClubId(), registerModel.getClub2().getName(),
                                        registerModel.getCompetition())
                                .chain(cardModels -> send(uuid, "sendCards", cardModels)));
    }

    public Uni<Void> sendRegister(String uuid, CompetitionGuestModel model) {
        return Mutiny.fetch(model.getCategoriesInscrites()).chain(o ->
                send(uuid, "sendRegister", CombEntity.fromModel(model).addCategoriesInscrites(o))
                        .call(__ -> cardService.addTeamCartToNewComb(model.getId() * -1,
                                        null, model.getClub(), model.getCompetition())
                                .chain(cardModels -> send(uuid, "sendCards", cardModels))));
    }

    public Uni<Void> sendRegisterNoFetch(String uuid, CompetitionGuestModel model) {
        return send(uuid, "sendRegister",
                CombEntity.fromModel(model).addCategoriesInscrites(model.getCategoriesInscrites()))
                .call(__ -> cardService.addTeamCartToNewComb(model.getId() * -1,
                                null, model.getClub(), model.getCompetition())
                        .chain(cardModels -> send(uuid, "sendCards", cardModels)));
    }

    public Uni<Void> sendRegisterRemove(String uuid, Long combId) {
        return send(uuid, "sendRegisterRemove", combId)
                .call(__ -> cardService.rmTeamCardFromComb(combId, uuid));
    }

    public Uni<Void> send(String uuid, String code, Object data) {
        List<Uni<Void>> queue = connections.findByEndpointId(CompetitionWS.class.getCanonicalName()).stream()
                .filter(c -> c.pathParam("uuid").equals(uuid) && PermLevel.valueOf(
                        c.userData().get(UserData.TypedKey.forString("prem"))).ordinal() >= PermLevel.TABLE.ordinal())
                .map(c -> c.sendText(
                        new MessageOut(UUID.randomUUID(), code, MessageType.NOTIFY, data)))
                .toList();

        if (queue.isEmpty())
            return Uni.createFrom().voidItem();
        return Uni.join().all(queue).andCollectFailures().replaceWithVoid();
    }

}
