package dev.lions.unionflow.client.view;

import dev.lions.unionflow.client.service.TicketService;
import dev.lions.unionflow.server.api.dto.ticket.request.*;
import dev.lions.unionflow.server.api.dto.ticket.response.*;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import jakarta.inject.Inject;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.logging.Logger;
import dev.lions.unionflow.client.service.ErrorHandlerService;
import dev.lions.unionflow.client.service.RetryService;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Bean JSF pour la gestion des tickets support
 * 
 * @author UnionFlow Team
 * @version 1.0
 */
@Named("ticketBean")
@ViewScoped
public class TicketBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(TicketBean.class);
    
    @Inject
    @RestClient
    private TicketService ticketService;
    
    @Inject
    private UserSession userSession;
    
    @Inject
    ErrorHandlerService errorHandler;
    
    @Inject
    RetryService retryService;
    
    // Données
    private List<TicketResponse> tickets = new ArrayList<>();
    private TicketResponse ticketSelectionne;
    private TicketResponse nouveauTicket;
    
    // Filtres
    private String statutFiltre;
    private String prioriteFiltre;
    private String categorieFiltre;
    private String recherche;
    
    // Statistiques
    private int totalTickets = 0;
    private int ticketsEnAttente = 0;
    private int ticketsResolus = 0;
    private int ticketsFermes = 0;
    
    // Utilisateur actuel (récupéré depuis la session)
    private UUID utilisateurId;
    
    // Dialog
    private boolean afficherDialogNouveauTicket = false;
    
    @PostConstruct
    public void init() {
        // Récupérer l'utilisateur depuis la session
        if (userSession != null && userSession.getCurrentUser() != null) {
            utilisateurId = userSession.getCurrentUser().getId();
            LOG.infof("Utilisateur récupéré depuis la session: %s", utilisateurId);
        } else {
            LOG.warn("Aucun utilisateur trouvé dans la session");
        }
        nouveauTicket = new TicketResponse();
        chargerTickets();
        chargerStatistiques();
    }
    
    // Tous les tickets non filtrés (cache pour le filtrage côté client)
    private List<TicketResponse> tousLesTickets = new ArrayList<>();

    public void chargerTickets() {
        try {
            if (utilisateurId != null) {
                tousLesTickets = retryService.executeWithRetrySupplier(
                    () -> ticketService.listerTickets(utilisateurId),
                    "chargement des tickets"
                );
                appliquerFiltres();
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des tickets");
            errorHandler.handleException(e, "lors du chargement des tickets", null);
            tousLesTickets = new ArrayList<>();
            tickets = new ArrayList<>();
        }
    }

    private void appliquerFiltres() {
        tickets = tousLesTickets.stream()
            .filter(t -> statutFiltre == null || statutFiltre.isEmpty() || statutFiltre.equals(t.getStatut()))
            .filter(t -> prioriteFiltre == null || prioriteFiltre.isEmpty() || prioriteFiltre.equals(t.getPriorite()))
            .filter(t -> categorieFiltre == null || categorieFiltre.isEmpty() || categorieFiltre.equals(t.getCategorie()))
            .filter(t -> {
                if (recherche == null || recherche.isBlank()) return true;
                String r = recherche.toLowerCase();
                return (t.getSujet() != null && t.getSujet().toLowerCase().contains(r))
                    || (t.getDescription() != null && t.getDescription().toLowerCase().contains(r))
                    || (t.getNumeroTicket() != null && t.getNumeroTicket().toLowerCase().contains(r));
            })
            .collect(java.util.stream.Collectors.toList());
    }
    
    public void chargerStatistiques() {
        try {
            if (utilisateurId != null) {
                Map<String, Object> stats = retryService.executeWithRetrySupplier(
                    () -> ticketService.obtenirStatistiques(utilisateurId),
                    "chargement des statistiques de tickets"
                );
                totalTickets = ((Number) stats.getOrDefault("totalTickets", 0)).intValue();
                ticketsEnAttente = ((Number) stats.getOrDefault("ticketsEnAttente", 0)).intValue();
                ticketsResolus = ((Number) stats.getOrDefault("ticketsResolus", 0)).intValue();
                ticketsFermes = ((Number) stats.getOrDefault("ticketsFermes", 0)).intValue();
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du chargement des statistiques");
        }
    }
    
    public void voirDetails() {
        if (ticketSelectionne != null) {
            try {
                ticketSelectionne = retryService.executeWithRetrySupplier(
                    () -> ticketService.obtenirTicket(ticketSelectionne.getId()),
                    "récupération des détails d'un ticket"
                );
            } catch (Exception e) {
                LOG.errorf(e, "Erreur lors de la récupération du ticket");
                errorHandler.handleException(e, "lors de la récupération d'un ticket", null);
            }
        }
    }
    
    public void creerTicket() {
        try {
            if (nouveauTicket != null && utilisateurId != null) {
                nouveauTicket.setUtilisateurId(utilisateurId);
                // Mapper TicketResponse vers CreateTicketRequest
                CreateTicketRequest request = new CreateTicketRequest(
                    nouveauTicket.getUtilisateurId(),
                    nouveauTicket.getSujet(),
                    nouveauTicket.getDescription(),
                    nouveauTicket.getCategorie(),
                    nouveauTicket.getPriorite(),
                    nouveauTicket.getPiecesJointes()
                );
                TicketResponse created = retryService.executeWithRetrySupplier(
                    () -> ticketService.creerTicket(request),
                    "création d'un ticket"
                );
                tickets.add(0, created); // Ajouter en tête de liste
                nouveauTicket = new TicketResponse();
                afficherDialogNouveauTicket = false;
                chargerStatistiques();
                errorHandler.showSuccess("Succès", "Ticket créé avec succès");
            }
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors de la création du ticket");
            errorHandler.handleException(e, "lors de la création d'un ticket", null);
        }
    }
    
    public void filtrer() {
        appliquerFiltres();
    }
    
    public void ouvrirDialogNouveauTicket() {
        nouveauTicket = new TicketResponse();
        afficherDialogNouveauTicket = true;
    }
    
    public void fermerDialogNouveauTicket() {
        afficherDialogNouveauTicket = false;
        nouveauTicket = new TicketResponse();
    }
    
    
    // Getters et Setters
    public List<TicketResponse> getTickets() { return tickets; }
    public void setTickets(List<TicketResponse> tickets) { this.tickets = tickets; }
    
    public TicketResponse getTicketSelectionne() { return ticketSelectionne; }
    public void setTicketSelectionne(TicketResponse ticketSelectionne) { this.ticketSelectionne = ticketSelectionne; }
    
    public TicketResponse getNouveauTicket() { return nouveauTicket; }
    public void setNouveauTicket(TicketResponse nouveauTicket) { this.nouveauTicket = nouveauTicket; }
    
    public String getStatutFiltre() { return statutFiltre; }
    public void setStatutFiltre(String statutFiltre) { this.statutFiltre = statutFiltre; }
    
    public String getPrioriteFiltre() { return prioriteFiltre; }
    public void setPrioriteFiltre(String prioriteFiltre) { this.prioriteFiltre = prioriteFiltre; }
    
    public String getCategorieFiltre() { return categorieFiltre; }
    public void setCategorieFiltre(String categorieFiltre) { this.categorieFiltre = categorieFiltre; }
    
    public String getRecherche() { return recherche; }
    public void setRecherche(String recherche) { this.recherche = recherche; }
    
    public int getTotalTickets() { return totalTickets; }
    public void setTotalTickets(int totalTickets) { this.totalTickets = totalTickets; }
    
    public int getTicketsEnAttente() { return ticketsEnAttente; }
    public void setTicketsEnAttente(int ticketsEnAttente) { this.ticketsEnAttente = ticketsEnAttente; }
    
    public int getTicketsResolus() { return ticketsResolus; }
    public void setTicketsResolus(int ticketsResolus) { this.ticketsResolus = ticketsResolus; }
    
    public int getTicketsFermes() { return ticketsFermes; }
    public void setTicketsFermes(int ticketsFermes) { this.ticketsFermes = ticketsFermes; }
    
    public boolean isAfficherDialogNouveauTicket() { return afficherDialogNouveauTicket; }
    public void setAfficherDialogNouveauTicket(boolean afficherDialogNouveauTicket) { 
        this.afficherDialogNouveauTicket = afficherDialogNouveauTicket; 
    }
}

