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

import dev.lions.unionflow.server.api.dto.vote.CampagneVoteRequest;
import dev.lions.unionflow.server.api.dto.vote.CampagneVoteResponse;
import dev.lions.unionflow.server.api.dto.vote.CandidatDTO;
import dev.lions.unionflow.server.api.enums.vote.StatutVote;
import dev.lions.unionflow.server.entity.Organisation;
import dev.lions.unionflow.server.entity.Membre;
import dev.lions.unionflow.server.entity.vote.CampagneVote;
import dev.lions.unionflow.server.entity.vote.Candidat;
import dev.lions.unionflow.server.mapper.vote.CampagneVoteMapper;
import dev.lions.unionflow.server.mapper.vote.CandidatMapper;
import dev.lions.unionflow.server.repository.OrganisationRepository;
import dev.lions.unionflow.server.repository.MembreRepository;
import dev.lions.unionflow.server.repository.vote.CampagneVoteRepository;
import dev.lions.unionflow.server.repository.vote.CandidatRepository;

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;

@ApplicationScoped
public class CampagneVoteService {

    @Inject
    CampagneVoteRepository campagneVoteRepository;

    @Inject
    CandidatRepository candidatRepository;

    @Inject
    OrganisationRepository organisationRepository;

    @Inject
    MembreRepository membreRepository;

    @Inject
    CampagneVoteMapper campagneVoteMapper;

    @Inject
    CandidatMapper candidatMapper;

    @Transactional
    public CampagneVoteResponse creerCampagne(CampagneVoteRequest request) {
        Organisation organisation = organisationRepository
                .findByIdOptional(UUID.fromString(request.getOrganisationId()))
                .orElseThrow(() -> new NotFoundException(
                        "Organisation non trouvée avec l'ID: " + request.getOrganisationId()));

        CampagneVote campagne = campagneVoteMapper.toEntity(request);
        campagne.setOrganisation(organisation);
        campagne.setStatut(StatutVote.BROUILLON);

        campagneVoteRepository.persist(campagne);
        return campagneVoteMapper.toDto(campagne);
    }

    public CampagneVoteResponse getCampagneById(UUID id) {
        CampagneVote campagne = campagneVoteRepository.findByIdOptional(id)
                .orElseThrow(() -> new NotFoundException("Campagne de vote non trouvée avec l'ID: " + id));
        return campagneVoteMapper.toDto(campagne);
    }

    public List<CampagneVoteResponse> getCampagnesByOrganisation(UUID organisationId) {
        return campagneVoteRepository.find("organisation.id = ?1 and actif = true", organisationId)
                .stream()
                .map(campagneVoteMapper::toDto)
                .collect(Collectors.toList());
    }

    @Transactional
    public CampagneVoteResponse changerStatut(UUID id, StatutVote statut) {
        CampagneVote campagne = campagneVoteRepository.findByIdOptional(id)
                .orElseThrow(() -> new NotFoundException("Campagne de vote non trouvée avec l'ID: " + id));
        campagne.setStatut(statut);
        return campagneVoteMapper.toDto(campagne);
    }

    @Transactional
    public CandidatDTO ajouterCandidat(UUID campagneId, CandidatDTO dto) {
        CampagneVote campagne = campagneVoteRepository.findByIdOptional(campagneId)
                .orElseThrow(() -> new NotFoundException("Campagne de vote non trouvée avec l'ID: " + campagneId));

        Candidat candidat = candidatMapper.toEntity(dto);
        candidat.setCampagneVote(campagne);

        if (dto.getMembreIdAssocie() != null) {
            // Dans l'entité Candidat actuelle, membreIdAssocie est un String
            candidat.setMembreIdAssocie(dto.getMembreIdAssocie());
        }

        candidatRepository.persist(candidat);
        return candidatMapper.toDto(candidat);
    }
}
