package fr.titionfire.ffsaf.domain.service; import fr.titionfire.ffsaf.data.model.CardModel; import fr.titionfire.ffsaf.data.model.ClubCardModel; import fr.titionfire.ffsaf.data.model.CompetitionModel; import fr.titionfire.ffsaf.data.model.MatchModel; import fr.titionfire.ffsaf.data.repository.*; import fr.titionfire.ffsaf.rest.exception.DBadRequestException; import fr.titionfire.ffsaf.ws.recv.RCard; import io.quarkus.hibernate.reactive.panache.Panache; import io.quarkus.hibernate.reactive.panache.common.WithSession; import io.quarkus.panache.common.Sort; import io.smallrye.mutiny.Uni; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; @WithSession @ApplicationScoped public class CardService { @Inject CardRepository cardRepository; @Inject ClubCardRepository clubCardRepository; @Inject RegisterRepository registerRepository; @Inject CompetitionGuestRepository competitionGuestRepository; @Inject MatchRepository matchRepository; @Inject TradService trad; private static final List COMPETITION_LEVEL_CARDS = List.of( CardModel.CardType.YELLOW, CardModel.CardType.RED, CardModel.CardType.BLACK ); private List extractCombIds(MatchModel match) { List ids = new ArrayList<>(); if (match.getC1_id() != null) ids.add(match.getC1_id().getId()); if (match.getC2_id() != null) ids.add(match.getC2_id().getId()); if (match.getC1_guest() != null) ids.add(match.getC1_guest().getId() * -1); if (match.getC2_guest() != null) ids.add(match.getC2_guest().getId() * -1); return ids; } public Uni> getForMatch(MatchModel match) { return cardRepository.list( "competition = ?1 AND (type IN ?2 OR (type = CardType.BLUE AND category = ?4)) AND comb IN ?3", match.getCategory().getCompet(), COMPETITION_LEVEL_CARDS, extractCombIds(match), match.getCategory().getId()); } public Uni> getAll(CompetitionModel competition) { return cardRepository.list("competition = ?1", competition); } public Uni checkCanBeAdded(RCard.SendCardAdd card, MatchModel matchModel) { return cardRepository.find("competition = ?1 AND comb = ?2", Sort.descending("type"), matchModel.getCategory().getCompet(), card.combId()) .firstResult() .map(card_ -> { if (card.type() == CardModel.CardType.BLUE) { return card_ == null || (card_.getType() == CardModel.CardType.BLUE && !Objects.equals(card_.getCategory(), matchModel.getCategory().getId())); } if (card.type() == CardModel.CardType.BLACK) { return card_ != null && card_.getType() == CardModel.CardType.RED; } return card_ == null || card_.getType().ordinal() < card.type().ordinal(); }) .chain(b -> { if (b) return Uni.createFrom().item(card); else return Uni.createFrom().failure(new DBadRequestException(trad.t("card.cannot.be.added"))); }); } public Uni> addTeamCard(CompetitionModel competition, String teamUuid, String teamName, CardModel.CardType type, String reason) { return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3)", Sort.descending("type"), competition.getId(), teamUuid, teamName) .firstResult() .map(card_ -> { if (type == CardModel.CardType.BLACK) { return card_ != null && card_.getType() == CardModel.CardType.RED; } return card_ == null || card_.getType().ordinal() < type.ordinal(); }) .chain(b -> { if (!b) return Uni.createFrom().failure(new DBadRequestException(trad.t("card.cannot.be.added"))); if (teamUuid != null) { return registerRepository.list("competition = ?1 AND club.clubId = ?2", competition, teamUuid) .map(l -> l.stream().map(r -> r.getMembre().getId()).toList()); } else { return competitionGuestRepository.list("competition = ?1 AND club = ?2", competition, teamName) .map(l -> l.stream().map(r -> r.getId() * -1).toList()); } }) .chain(combIds -> cardRepository.list("competition = ?1 AND comb IN ?2", competition, combIds) .map(cards -> { List newCards = new ArrayList<>(); for (Long id : combIds) { Optional optional = cards.stream() .filter(c -> id.equals(c.getComb()) && c.getType() == type).findAny(); CardModel model = new CardModel(); model.setCompetition(competition); model.setCompetitionId(competition.getId()); model.setComb(id); model.setTeamCard(true); if (optional.isEmpty()) { model.setType(type); } else { model.setType( CardModel.CardType.values()[Math.min(optional.get().getType().ordinal() + 1, CardModel.CardType.BLACK.ordinal())]); } newCards.add(model); } return newCards; }) ) .call(newCards -> Panache.withTransaction(() -> cardRepository.persist(newCards))) .call(newCards -> { ClubCardModel model = new ClubCardModel(); model.setCompetition(competition.getId()); model.setTeamUuid(teamUuid); model.setTeamName(teamName); model.setType(type); model.setReason(reason); model.setCardIds(newCards.stream().map(CardModel::getId).toList()); return Panache.withTransaction(() -> clubCardRepository.persist(model)); }); } public Uni> recvReturnState(CompetitionModel competition, RCard.SendTeamCardReturnState state) { return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3) AND type = ?4", competition.getId(), state.teamUuid(), state.teamName(), state.type()) .firstResult() .chain(o -> cardRepository.list("id IN ?1", o.getCardIds())) .call(cards -> matchRepository.list("category.compet = ?1 AND category.id IN ?2", competition, state.selectedCategory()) .invoke(matches -> { for (CardModel card : cards) { for (MatchModel m : matches.stream() .filter(m -> extractCombIds(m).contains(card.getComb())).toList()) { if (state.state() == 1) { card.setCategory(m.getCategory().getId()); } else if (state.state() == 2) { card.setCategory(m.getCategory().getId()); if (Objects.equals(m.getId(), state.selectedMatch())) card.setMatch(m.getId()); } } } }) .chain(() -> Panache.withTransaction(() -> cardRepository.persist(cards)))); } public Uni> rmTeamCard(CompetitionModel competition, String teamUuid, String teamName, CardModel.CardType type) { return clubCardRepository.find("competition = ?1 AND (teamUuid = ?2 OR teamName = ?3) AND type = ?4", competition.getId(), teamUuid, teamName, type) .firstResult() .chain(card -> Uni.createFrom().item(card.getCardIds()) .call(() -> Panache.withTransaction(() -> cardRepository.delete("id IN ?1", card.getCardIds()))) .call(() -> Panache.withTransaction(() -> clubCardRepository.delete(card)))); } }