package dev.lions.unionflow.server.service.tontine;

import dev.lions.unionflow.server.api.dto.tontine.TontineRequest;
import dev.lions.unionflow.server.api.dto.tontine.TontineResponse;
import dev.lions.unionflow.server.api.enums.tontine.StatutTontine;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.tontine.Tontine;
import dev.lions.unionflow.server.mapper.tontine.TontineMapper;
import dev.lions.unionflow.server.repository.OrganisationRepository;
import dev.lions.unionflow.server.repository.tontine.TontineRepository;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.ws.rs.NotFoundException;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Service métier pour la gestion des tontines.
 */
@ApplicationScoped
public class TontineService {

    @Inject
    TontineRepository tontineRepository;

    @Inject
    OrganisationRepository organisationRepository;

    @Inject
    TontineMapper tontineMapper;

    /**
     * Crée une nouvelle tontine.
     *
     * @param request Le DTO de la tontine.
     * @return Le DTO de la tontine créée.
     */
    @Transactional
    public TontineResponse creerTontine(TontineRequest request) {
        Organisation organisation = organisationRepository
                .findByIdOptional(UUID.fromString(request.getOrganisationId()))
                .orElseThrow(() -> new NotFoundException(
                        "Organisation non trouvée avec l'ID: " + request.getOrganisationId()));

        Tontine tontine = tontineMapper.toEntity(request);
        tontine.setOrganisation(organisation);
        tontine.setStatut(StatutTontine.PLANIFIEE);

        tontineRepository.persist(tontine);
        return tontineMapper.toDto(tontine);
    }

    /**
     * Récupère une tontine par son ID.
     *
     * @param id L'UUID de la tontine.
     * @return Le DTO de la tontine.
     */
    public TontineResponse getTontineById(UUID id) {
        Tontine tontine = tontineRepository.findByIdOptional(id)
                .orElseThrow(() -> new NotFoundException("Tontine non trouvée avec l'ID: " + id));
        return tontineMapper.toDto(tontine);
    }

    /**
     * Liste les tontines d'une organisation.
     *
     * @param organisationId L'UUID de l'organisation.
     * @return La liste des tontines.
     */
    public List<TontineResponse> getTontinesByOrganisation(UUID organisationId) {
        return tontineRepository.find("organisation.id = ?1 and actif = true", organisationId)
                .stream()
                .map(tontineMapper::toDto)
                .collect(Collectors.toList());
    }

    /**
     * Change le statut d'une tontine (Démarrage, Clôture, etc.).
     *
     * @param id     L'UUID de la tontine.
     * @param statut Le nouveau statut.
     * @return Le DTO mis à jour.
     */
    @Transactional
    public TontineResponse changerStatut(UUID id, StatutTontine statut) {
        Tontine tontine = tontineRepository.findByIdOptional(id)
                .orElseThrow(() -> new NotFoundException("Tontine non trouvée avec l'ID: " + id));

        tontine.setStatut(statut);
        return tontineMapper.toDto(tontine);
    }
}
