package dev.lions.unionflow.client.view;

import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.math.BigDecimal;

@Named("evenementsBean")
@SessionScoped
public class EvenementsBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    
    private List<Evenement> tousLesEvenements;
    private List<Evenement> evenementsFiltres;
    private List<Evenement> evenementsSelectionnes;
    private List<Evenement> evenementsProchains;
    private Evenement evenementSelectionne;
    private NouvelEvenement nouvelEvenement;
    private Filtres filtres;
    private StatistiquesEvenements statistiques;
    
    @PostConstruct
    public void init() {
        initializeFiltres();
        initializeStatistiques();
        initializeEvenements();
        initializeNouvelEvenement();
        initializeEvenementsProchains();
        appliquerFiltres();
    }
    
    private void initializeFiltres() {
        filtres = new Filtres();
        evenementsSelectionnes = new ArrayList<>();
    }
    
    private void initializeStatistiques() {
        statistiques = new StatistiquesEvenements();
        statistiques.setTotalEvenements(42);
        statistiques.setEvenementsActifs(18);
        statistiques.setParticipantsTotal(1247);
        statistiques.setBudgetTotal("3 450 000 FCFA");
        statistiques.setMoyenneParticipants(69);
    }
    
    private void initializeEvenements() {
        tousLesEvenements = new ArrayList<>();
        
        String[] titres = {
            "Assemblée Générale Ordinaire", "Formation Leadership", "Action Sociale Quartier Nord",
            "Réunion Mensuelle Comité", "Conférence Développement Durable", "Collecte de Fonds",
            "Journée Portes Ouvertes", "Atelier Gestion Financière", "Campagne Sensibilisation",
            "Séminaire Jeunes Leaders", "Action Humanitaire", "Réunion Conseil Administration",
            "Formation Premiers Secours", "Festival Culturel", "Réunion Coordination Régionale"
        };
        
        String[] types = {
            "ASSEMBLEE_GENERALE", "FORMATION", "ACTION_SOCIALE", "REUNION", "FORMATION",
            "ACTION_SOCIALE", "EVENEMENT_FESTIF", "FORMATION", "ACTION_SOCIALE", "FORMATION",
            "ACTION_SOCIALE", "REUNION", "FORMATION", "EVENEMENT_FESTIF", "REUNION"
        };
        
        String[] statuts = {
            "PLANIFIE", "PLANIFIE", "EN_COURS", "TERMINE", "PLANIFIE",
            "PLANIFIE", "TERMINE", "PLANIFIE", "EN_COURS", "PLANIFIE",
            "TERMINE", "PLANIFIE", "PLANIFIE", "TERMINE", "PLANIFIE"
        };
        
        String[] priorites = {
            "CRITIQUE", "ELEVEE", "NORMALE", "NORMALE", "ELEVEE",
            "NORMALE", "FAIBLE", "NORMALE", "ELEVEE", "NORMALE",
            "CRITIQUE", "NORMALE", "FAIBLE", "FAIBLE", "NORMALE"
        };
        
        String[] lieux = {
            "Salle Principale", "Centre Formation", "Quartier Nord", "Salle Réunion A",
            "Auditorium Central", "Place Publique", "Hall d'Accueil", "Salle Formation B",
            "Centre-Ville", "Campus Universitaire", "Zone Rurale", "Salle Conseil",
            "Centre Médical", "Parc Municipal", "Siège Régional"
        };
        
        String[] organisateurs = {
            "Marie Kouassi", "Paul Traoré", "Fatou Sanogo", "Jean Ouattara", "Aissata Koné",
            "Ibrahim Touré", "Aminata Bakayoko", "Yves Koffi", "Mariam Coulibaly", "Seydou Cissé",
            "Adjoa Mensah", "Kwame Asante", "Ama Gyamfi", "Kofi Adjei", "Ahmed Diallo"
        };
        
        for (int i = 0; i < titres.length; i++) {
            Evenement evenement = new Evenement();
            evenement.setId((long) (i + 1));
            evenement.setTitre(titres[i]);
            evenement.setType(types[i]);
            evenement.setStatut(statuts[i]);
            evenement.setPriorite(priorites[i]);
            evenement.setLieu(lieux[i]);
            evenement.setAdresse("Adresse " + lieux[i] + ", Ville");
            evenement.setOrganisateur(organisateurs[i]);
            evenement.setOrganisateurEmail(organisateurs[i].toLowerCase().replace(" ", ".") + "@unionflow.app");
            
            // Dates aléatoires
            LocalDate baseDate = LocalDate.now().plusDays(i * 3 - 15);
            evenement.setDateDebut(baseDate);
            evenement.setDateFin(baseDate.plusDays(i % 3 == 0 ? 1 : 0));
            evenement.setHeureDebut(LocalTime.of(9 + (i % 8), 0));
            evenement.setHeureFin(LocalTime.of(11 + (i % 8), 30));
            
            // Participants et capacité
            int capacite = 50 + (i * 10);
            int inscrits = (int) (capacite * (0.3 + (i * 0.05) % 0.7));
            evenement.setCapaciteMax(capacite);
            evenement.setParticipantsInscrits(inscrits);
            
            // Budget
            BigDecimal budget = new BigDecimal(100000 + (i * 25000));
            evenement.setBudget(budget);
            
            // Description
            evenement.setDescription("Description détaillée pour " + titres[i] + " avec objectifs et programme.");
            
            tousLesEvenements.add(evenement);
        }
    }
    
    private void initializeEvenementsProchains() {
        evenementsProchains = tousLesEvenements.stream()
                .filter(e -> e.getDateDebut().isAfter(LocalDate.now()) || e.getDateDebut().equals(LocalDate.now()))
                .filter(e -> !e.getStatut().equals("ANNULE") && !e.getStatut().equals("TERMINE"))
                .sorted((e1, e2) -> e1.getDateDebut().compareTo(e2.getDateDebut()))
                .limit(6)
                .collect(Collectors.toList());
    }
    
    private void initializeNouvelEvenement() {
        nouvelEvenement = new NouvelEvenement();
        nouvelEvenement.setPriorite("NORMALE");
        nouvelEvenement.setDateDebut(LocalDate.now().plusWeeks(1));
    }
    
    private void appliquerFiltres() {
        evenementsFiltres = tousLesEvenements.stream()
                .filter(this::appliquerFiltre)
                .collect(Collectors.toList());
    }
    
    private boolean appliquerFiltre(Evenement evenement) {
        if (filtres.getTitre() != null && !filtres.getTitre().trim().isEmpty()) {
            if (!evenement.getTitre().toLowerCase().contains(filtres.getTitre().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
            if (!evenement.getType().equals(filtres.getType())) {
                return false;
            }
        }
        
        if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
            if (!evenement.getStatut().equals(filtres.getStatut())) {
                return false;
            }
        }
        
        if (filtres.getOrganisateur() != null && !filtres.getOrganisateur().trim().isEmpty()) {
            if (!evenement.getOrganisateur().toLowerCase().contains(filtres.getOrganisateur().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getPriorite() != null && !filtres.getPriorite().trim().isEmpty()) {
            if (!evenement.getPriorite().equals(filtres.getPriorite())) {
                return false;
            }
        }
        
        if (filtres.getDateDebut() != null) {
            if (evenement.getDateDebut().isBefore(filtres.getDateDebut())) {
                return false;
            }
        }
        
        if (filtres.getDateFin() != null) {
            if (evenement.getDateDebut().isAfter(filtres.getDateFin())) {
                return false;
            }
        }
        
        return true;
    }
    
    // Actions
    public void rechercher() {
        appliquerFiltres();
    }
    
    public void reinitialiserFiltres() {
        filtres = new Filtres();
        appliquerFiltres();
    }
    
    public void creerEvenement() {
        Evenement nouvelEvt = new Evenement();
        nouvelEvt.setId((long) (tousLesEvenements.size() + 1));
        nouvelEvt.setTitre(nouvelEvenement.getTitre());
        nouvelEvt.setType(nouvelEvenement.getType());
        nouvelEvt.setDateDebut(nouvelEvenement.getDateDebut());
        nouvelEvt.setDateFin(nouvelEvenement.getDateFin());
        nouvelEvt.setLieu(nouvelEvenement.getLieu());
        nouvelEvt.setAdresse(nouvelEvenement.getAdresse());
        nouvelEvt.setCapaciteMax(nouvelEvenement.getCapaciteMax());
        nouvelEvt.setBudget(nouvelEvenement.getBudget());
        nouvelEvt.setDescription(nouvelEvenement.getDescription());
        nouvelEvt.setPriorite(nouvelEvenement.getPriorite());
        nouvelEvt.setOrganisateur(nouvelEvenement.getOrganisateur());
        nouvelEvt.setStatut("PLANIFIE");
        nouvelEvt.setParticipantsInscrits(0);
        nouvelEvt.setHeureDebut(LocalTime.of(9, 0));
        nouvelEvt.setHeureFin(LocalTime.of(17, 0));
        
        tousLesEvenements.add(nouvelEvt);
        appliquerFiltres();
        initializeEvenementsProchains();
        
        System.out.println("Nouvel événement créé: " + nouvelEvt.getTitre());
        initializeNouvelEvenement();
    }
    
    public String gererParticipants() {
        return "/pages/admin/evenements/participants?id=" + evenementSelectionne.getId() + "&faces-redirect=true";
    }
    
    public void envoyerInvitations() {
        System.out.println("Invitations envoyées pour: " + evenementSelectionne.getTitre());
    }
    
    public String voirRapports() {
        return "/pages/admin/evenements/rapports?id=" + evenementSelectionne.getId() + "&faces-redirect=true";
    }
    
    public void annulerEvenement() {
        if (evenementSelectionne != null) {
            evenementSelectionne.setStatut("ANNULE");
            System.out.println("Événement annulé: " + evenementSelectionne.getTitre());
            appliquerFiltres();
            initializeEvenementsProchains();
        }
    }
    
    public void dupliquerEvenement() {
        if (evenementSelectionne != null) {
            Evenement copie = new Evenement();
            copie.setId((long) (tousLesEvenements.size() + 1));
            copie.setTitre(evenementSelectionne.getTitre() + " (Copie)");
            copie.setType(evenementSelectionne.getType());
            copie.setLieu(evenementSelectionne.getLieu());
            copie.setAdresse(evenementSelectionne.getAdresse());
            copie.setCapaciteMax(evenementSelectionne.getCapaciteMax());
            copie.setBudget(evenementSelectionne.getBudget());
            copie.setDescription(evenementSelectionne.getDescription());
            copie.setPriorite(evenementSelectionne.getPriorite());
            copie.setOrganisateur(evenementSelectionne.getOrganisateur());
            copie.setStatut("PLANIFIE");
            copie.setParticipantsInscrits(0);
            copie.setDateDebut(LocalDate.now().plusWeeks(2));
            copie.setDateFin(evenementSelectionne.getDateFin());
            copie.setHeureDebut(evenementSelectionne.getHeureDebut());
            copie.setHeureFin(evenementSelectionne.getHeureFin());
            
            tousLesEvenements.add(copie);
            appliquerFiltres();
            System.out.println("Événement dupliqué: " + copie.getTitre());
        }
    }
    
    public void exporterEvenements() {
        System.out.println("Export de " + evenementsFiltres.size() + " événements");
    }
    
    public void exporterExcel() {
        System.out.println("Export Excel de " + evenementsFiltres.size() + " événements");
    }
    
    // Getters et Setters
    public List<Evenement> getTousLesEvenements() { return tousLesEvenements; }
    public void setTousLesEvenements(List<Evenement> tousLesEvenements) { this.tousLesEvenements = tousLesEvenements; }
    
    public List<Evenement> getEvenementsFiltres() { return evenementsFiltres; }
    public void setEvenementsFiltres(List<Evenement> evenementsFiltres) { this.evenementsFiltres = evenementsFiltres; }
    
    public List<Evenement> getEvenementsSelectionnes() { return evenementsSelectionnes; }
    public void setEvenementsSelectionnes(List<Evenement> evenementsSelectionnes) { this.evenementsSelectionnes = evenementsSelectionnes; }
    
    public List<Evenement> getEvenementsProchains() { return evenementsProchains; }
    public void setEvenementsProchains(List<Evenement> evenementsProchains) { this.evenementsProchains = evenementsProchains; }
    
    public Evenement getEvenementSelectionne() { return evenementSelectionne; }
    public void setEvenementSelectionne(Evenement evenementSelectionne) { this.evenementSelectionne = evenementSelectionne; }
    
    public NouvelEvenement getNouvelEvenement() { return nouvelEvenement; }
    public void setNouvelEvenement(NouvelEvenement nouvelEvenement) { this.nouvelEvenement = nouvelEvenement; }
    
    public Filtres getFiltres() { return filtres; }
    public void setFiltres(Filtres filtres) { this.filtres = filtres; }
    
    public StatistiquesEvenements getStatistiques() { return statistiques; }
    public void setStatistiques(StatistiquesEvenements statistiques) { this.statistiques = statistiques; }
    
    // Classes internes
    public static class Evenement {
        private Long id;
        private String titre;
        private String description;
        private String type;
        private String statut;
        private String priorite;
        private LocalDate dateDebut;
        private LocalDate dateFin;
        private LocalTime heureDebut;
        private LocalTime heureFin;
        private String lieu;
        private String adresse;
        private String organisateur;
        private String organisateurEmail;
        private int capaciteMax;
        private int participantsInscrits;
        private BigDecimal budget;
        
        // Getters et setters
        public Long getId() { return id; }
        public void setId(Long id) { this.id = id; }
        
        public String getTitre() { return titre; }
        public void setTitre(String titre) { this.titre = titre; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getPriorite() { return priorite; }
        public void setPriorite(String priorite) { this.priorite = priorite; }
        
        public LocalDate getDateDebut() { return dateDebut; }
        public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
        
        public LocalDate getDateFin() { return dateFin; }
        public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
        
        public LocalTime getHeureDebut() { return heureDebut; }
        public void setHeureDebut(LocalTime heureDebut) { this.heureDebut = heureDebut; }
        
        public LocalTime getHeureFin() { return heureFin; }
        public void setHeureFin(LocalTime heureFin) { this.heureFin = heureFin; }
        
        public String getLieu() { return lieu; }
        public void setLieu(String lieu) { this.lieu = lieu; }
        
        public String getAdresse() { return adresse; }
        public void setAdresse(String adresse) { this.adresse = adresse; }
        
        public String getOrganisateur() { return organisateur; }
        public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
        
        public String getOrganisateurEmail() { return organisateurEmail; }
        public void setOrganisateurEmail(String organisateurEmail) { this.organisateurEmail = organisateurEmail; }
        
        public int getCapaciteMax() { return capaciteMax; }
        public void setCapaciteMax(int capaciteMax) { this.capaciteMax = capaciteMax; }
        
        public int getParticipantsInscrits() { return participantsInscrits; }
        public void setParticipantsInscrits(int participantsInscrits) { this.participantsInscrits = participantsInscrits; }
        
        public BigDecimal getBudget() { return budget; }
        public void setBudget(BigDecimal budget) { this.budget = budget; }
        
        // Propriétés dérivées
        public String getTypeLibelle() {
            return switch (type) {
                case "REUNION" -> "Réunion";
                case "FORMATION" -> "Formation";
                case "ACTION_SOCIALE" -> "Action Sociale";
                case "ASSEMBLEE_GENERALE" -> "Assemblée Générale";
                case "EVENEMENT_FESTIF" -> "Événement Festif";
                default -> type;
            };
        }
        
        public String getTypeSeverity() {
            return switch (type) {
                case "REUNION" -> "info";
                case "FORMATION" -> "success";
                case "ACTION_SOCIALE" -> "warning";
                case "ASSEMBLEE_GENERALE" -> "danger";
                case "EVENEMENT_FESTIF" -> "secondary";
                default -> "primary";
            };
        }
        
        public String getTypeIcon() {
            return switch (type) {
                case "REUNION" -> "pi-users";
                case "FORMATION" -> "pi-book";
                case "ACTION_SOCIALE" -> "pi-heart";
                case "ASSEMBLEE_GENERALE" -> "pi-sitemap";
                case "EVENEMENT_FESTIF" -> "pi-star";
                default -> "pi-calendar";
            };
        }
        
        public String getStatutSeverity() {
            return switch (statut) {
                case "PLANIFIE" -> "info";
                case "EN_COURS" -> "warning";
                case "TERMINE" -> "success";
                case "ANNULE" -> "danger";
                default -> "secondary";
            };
        }
        
        public String getStatutIcon() {
            return switch (statut) {
                case "PLANIFIE" -> "pi-clock";
                case "EN_COURS" -> "pi-play";
                case "TERMINE" -> "pi-check";
                case "ANNULE" -> "pi-ban";
                default -> "pi-circle";
            };
        }
        
        public String getPrioriteSeverity() {
            return switch (priorite) {
                case "FAIBLE" -> "secondary";
                case "NORMALE" -> "info";
                case "ELEVEE" -> "warning";
                case "CRITIQUE" -> "danger";
                default -> "primary";
            };
        }
        
        public String getDateDebutFormatee() {
            if (dateDebut == null) return "";
            return dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
        }
        
        public String getHeureDebutFormatee() {
            if (heureDebut == null) return "";
            return heureDebut.format(DateTimeFormatter.ofPattern("HH:mm"));
        }
        
        public String getHeureFinFormatee() {
            if (heureFin == null) return "";
            return heureFin.format(DateTimeFormatter.ofPattern("HH:mm"));
        }
        
        public String getBudgetFormatte() {
            if (budget == null) return "";
            return String.format("%,.0f FCFA", budget);
        }
        
        public int getTauxInscription() {
            if (capaciteMax == 0) return 0;
            return (int) ((double) participantsInscrits / capaciteMax * 100);
        }
        
        public long getJoursRestants() {
            if (dateDebut == null) return 0;
            return ChronoUnit.DAYS.between(LocalDate.now(), dateDebut);
        }
    }
    
    public static class NouvelEvenement {
        private String titre;
        private String description;
        private String type;
        private String priorite;
        private LocalDate dateDebut;
        private LocalDate dateFin;
        private String lieu;
        private String adresse;
        private String organisateur;
        private Integer capaciteMax;
        private BigDecimal budget;
        
        // Getters et setters
        public String getTitre() { return titre; }
        public void setTitre(String titre) { this.titre = titre; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getPriorite() { return priorite; }
        public void setPriorite(String priorite) { this.priorite = priorite; }
        
        public LocalDate getDateDebut() { return dateDebut; }
        public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
        
        public LocalDate getDateFin() { return dateFin; }
        public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
        
        public String getLieu() { return lieu; }
        public void setLieu(String lieu) { this.lieu = lieu; }
        
        public String getAdresse() { return adresse; }
        public void setAdresse(String adresse) { this.adresse = adresse; }
        
        public String getOrganisateur() { return organisateur; }
        public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
        
        public Integer getCapaciteMax() { return capaciteMax; }
        public void setCapaciteMax(Integer capaciteMax) { this.capaciteMax = capaciteMax; }
        
        public BigDecimal getBudget() { return budget; }
        public void setBudget(BigDecimal budget) { this.budget = budget; }
    }
    
    public static class Filtres {
        private String titre;
        private String type;
        private String statut;
        private String organisateur;
        private String priorite;
        private LocalDate dateDebut;
        private LocalDate dateFin;
        
        // Getters et setters
        public String getTitre() { return titre; }
        public void setTitre(String titre) { this.titre = titre; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getOrganisateur() { return organisateur; }
        public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
        
        public String getPriorite() { return priorite; }
        public void setPriorite(String priorite) { this.priorite = priorite; }
        
        public LocalDate getDateDebut() { return dateDebut; }
        public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
        
        public LocalDate getDateFin() { return dateFin; }
        public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
    }
    
    public static class StatistiquesEvenements {
        private int totalEvenements;
        private int evenementsActifs;
        private int participantsTotal;
        private String budgetTotal;
        private int moyenneParticipants;
        
        // Getters et setters
        public int getTotalEvenements() { return totalEvenements; }
        public void setTotalEvenements(int totalEvenements) { this.totalEvenements = totalEvenements; }
        
        public int getEvenementsActifs() { return evenementsActifs; }
        public void setEvenementsActifs(int evenementsActifs) { this.evenementsActifs = evenementsActifs; }
        
        public int getParticipantsTotal() { return participantsTotal; }
        public void setParticipantsTotal(int participantsTotal) { this.participantsTotal = participantsTotal; }
        
        public String getBudgetTotal() { return budgetTotal; }
        public void setBudgetTotal(String budgetTotal) { this.budgetTotal = budgetTotal; }
        
        public int getMoyenneParticipants() { return moyenneParticipants; }
        public void setMoyenneParticipants(int moyenneParticipants) { this.moyenneParticipants = moyenneParticipants; }
    }
}