package fr.titionfire.ffsaf.ws.recv;

import fr.titionfire.ffsaf.data.model.MatchModel;
import fr.titionfire.ffsaf.data.repository.CombRepository;
import fr.titionfire.ffsaf.data.repository.CompetitionGuestRepository;
import fr.titionfire.ffsaf.data.repository.MatchRepository;
import fr.titionfire.ffsaf.domain.entity.MatchEntity;
import fr.titionfire.ffsaf.rest.exception.DForbiddenException;
import fr.titionfire.ffsaf.rest.exception.DNotFoundException;
import fr.titionfire.ffsaf.ws.CompetitionWS;
import fr.titionfire.ffsaf.ws.PermLevel;
import io.quarkus.hibernate.reactive.panache.Panache;
import io.quarkus.hibernate.reactive.panache.common.WithSession;
import io.quarkus.runtime.annotations.RegisterForReflection;
import io.quarkus.websockets.next.WebSocketConnection;
import io.smallrye.mutiny.Uni;
import io.smallrye.mutiny.unchecked.Unchecked;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.jboss.logging.Logger;

@WithSession
@ApplicationScoped
@RegisterForReflection
public class RMatch {
    private static final Logger LOGGER = Logger.getLogger(RMatch.class);

    @Inject
    MatchRepository matchRepository;

    @Inject
    CombRepository combRepository;

    @Inject
    CompetitionGuestRepository competitionGuestRepository;

    private Uni<MatchModel> getById(long id, WebSocketConnection connection) {
        return matchRepository.findById(id)
                .invoke(Unchecked.consumer(o -> {
                    if (o == null)
                        throw new DNotFoundException("Matche non trouver");
                    if (!o.getCategory().getCompet().getUuid().equals(connection.pathParam("uuid")))
                        throw new DForbiddenException("Permission denied");
                }));
    }

    @WSReceiver(code = "getAllMatch")
    public Uni<?> getAllMatch(WebSocketConnection connection, Long l) {
        LOGGER.info("getAllMatch " + l);

        return Uni.createFrom().item(l);
        //return matchRepository.count();
    }

    @WSReceiver(code = "updateMatchComb", permission = PermLevel.ADMIN)
    public Uni<Void> updateMatchComb(WebSocketConnection connection, MatchComb match) {
        return getById(match.id(), connection)
                .call(mm -> match.c1() != null ?
                        match.c1() >= 0 ?
                                combRepository.findById(match.c1()).invoke(model -> {
                                    mm.setC1_id(model);
                                    mm.setC1_guest(null);
                                }) :
                                competitionGuestRepository.findById(match.c1() * -1).invoke(model -> {
                                    mm.setC1_id(null);
                                    mm.setC1_guest(model);

                                }) :
                        Uni.createFrom().nullItem().invoke(__ -> {
                            mm.setC1_id(null);
                            mm.setC1_guest(null);
                        }))
                .call(mm -> match.c2() != null ?
                        match.c2() >= 0 ?
                                combRepository.findById(match.c2()).invoke(model -> {
                                    mm.setC2_id(model);
                                    mm.setC2_guest(null);
                                }) :
                                competitionGuestRepository.findById(match.c2() * -1).invoke(model -> {
                                    mm.setC2_id(null);
                                    mm.setC2_guest(model);
                                }) :
                        Uni.createFrom().nullItem().invoke(__ -> {
                            mm.setC2_id(null);
                            mm.setC2_guest(null);
                        }))
                .chain(mm -> Panache.withTransaction(() -> matchRepository.persist(mm)))
                .call(mm -> CompetitionWS.sendNotifyToOtherEditor(connection, "sendMatch",
                        MatchEntity.fromModel(mm)))
                .replaceWithVoid();
    }

    @RegisterForReflection
    public record MatchComb(long id, Long c1, Long c2) {
    }
}
