package dev.lions.freya.demo;

import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Named;

import org.primefaces.model.menu.DefaultMenuItem;
import org.primefaces.model.menu.DefaultMenuModel;
import org.primefaces.model.menu.MenuModel;

import java.io.Serializable;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Backing bean pour la page de démonstration des composants Freya Extension.
 *
 * Ce bean illustre l'utilisation des composants composites fr:field* et fr:actionDialog.
 */
@Named("demoBean")
@SessionScoped
public class DemoBean implements Serializable {

    private static final long serialVersionUID = 1L;

    // Données du formulaire principal
    private User user = new User();
    private String passwordConfirm;
    private List<String> availableInterests;

    // Données du dialog
    private DialogData dialogData = new DialogData();
    private FormDialogData formDialogData = new FormDialogData();

    // Données pour les nouveaux composants
    private List<SampleUser> sampleUsers;
    private SampleUser selectedUser; // Pour la sélection dans dataTable
    private MenuModel breadcrumbModel;
    private MenuModel stepsModel;
    private MenuModel splitButtonModel;
    private int activeStep = 1;
    private String tabField1;
    private String tabField2;
    private String inplaceValue = "Valeur éditable";
    private List<String> availableCities;

    public DemoBean() {
        availableInterests = new ArrayList<>();
        availableInterests.add("Sport");
        availableInterests.add("Musique");
        availableInterests.add("Voyage");
        availableInterests.add("Technologie");
        availableInterests.add("Cuisine");

        // Villes disponibles pour l'autocomplétion
        availableCities = new ArrayList<>();
        availableCities.add("Paris");
        availableCities.add("Lyon");
        availableCities.add("Marseille");
        availableCities.add("Toulouse");
        availableCities.add("Bordeaux");
        availableCities.add("Dakar");
        availableCities.add("Abidjan");
        availableCities.add("Montréal");
        availableCities.add("Québec");
    }

    @PostConstruct
    public void init() {
        initSampleUsers();
        initBreadcrumbModel();
        initStepsModel();
        initSplitButtonModel();
    }

    private void initSampleUsers() {
        sampleUsers = new ArrayList<>();
        sampleUsers.add(new SampleUser("Jean Dupont", "jean.dupont@email.com", true));
        sampleUsers.add(new SampleUser("Marie Martin", "marie.martin@email.com", true));
        sampleUsers.add(new SampleUser("Pierre Durand", "pierre.durand@email.com", false));
        sampleUsers.add(new SampleUser("Sophie Bernard", "sophie.bernard@email.com", true));
        sampleUsers.add(new SampleUser("Luc Petit", "luc.petit@email.com", false));
        sampleUsers.add(new SampleUser("Emma Leroy", "emma.leroy@email.com", true));
        sampleUsers.add(new SampleUser("Thomas Moreau", "thomas.moreau@email.com", true));
    }

    private void initBreadcrumbModel() {
        breadcrumbModel = new DefaultMenuModel();
        breadcrumbModel.getElements().add(DefaultMenuItem.builder().value("Accueil").outcome("/index").build());
        breadcrumbModel.getElements().add(DefaultMenuItem.builder().value("Composants").outcome("/components-demo").build());
        breadcrumbModel.getElements().add(DefaultMenuItem.builder().value("Démonstration").build());
    }

    private void initStepsModel() {
        stepsModel = new DefaultMenuModel();
        stepsModel.getElements().add(DefaultMenuItem.builder().value("Informations").build());
        stepsModel.getElements().add(DefaultMenuItem.builder().value("Vérification").build());
        stepsModel.getElements().add(DefaultMenuItem.builder().value("Confirmation").build());
    }

    private void initSplitButtonModel() {
        splitButtonModel = new DefaultMenuModel();
        splitButtonModel.getElements().add(DefaultMenuItem.builder().value("Exporter PDF").icon("pi pi-file-pdf").build());
        splitButtonModel.getElements().add(DefaultMenuItem.builder().value("Exporter Excel").icon("pi pi-file-excel").build());
        splitButtonModel.getElements().add(DefaultMenuItem.builder().value("Imprimer").icon("pi pi-print").build());
    }

    // ========================================
    // Actions
    // ========================================

    /**
     * Action d'inscription - valide et enregistre l'utilisateur.
     */
    public String register() {
        FacesContext context = FacesContext.getCurrentInstance();

        // Validation du mot de passe
        if (!user.getPassword().equals(passwordConfirm)) {
            context.addMessage(null, new FacesMessage(
                FacesMessage.SEVERITY_ERROR,
                "Erreur",
                "Les mots de passe ne correspondent pas"
            ));
            return null;
        }

        // Validation des conditions
        if (!user.isAcceptTerms()) {
            context.addMessage(null, new FacesMessage(
                FacesMessage.SEVERITY_WARN,
                "Attention",
                "Vous devez accepter les conditions d'utilisation"
            ));
            return null;
        }

        // Succès
        context.addMessage(null, new FacesMessage(
            FacesMessage.SEVERITY_INFO,
            "Succès",
            String.format("Bienvenue %s %s ! Votre compte a été créé.", user.getPrenom(), user.getNom())
        ));

        return null;
    }

    /**
     * Réinitialise le formulaire.
     */
    public void reset() {
        this.user = new User();
        this.passwordConfirm = null;

        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
            FacesMessage.SEVERITY_INFO,
            "Réinitialisé",
            "Le formulaire a été réinitialisé"
        ));
    }

    /**
     * Action de sauvegarde depuis le dialog.
     */
    public void saveFromDialog() {
        FacesContext context = FacesContext.getCurrentInstance();

        context.addMessage(null, new FacesMessage(
            FacesMessage.SEVERITY_INFO,
            "Dialog enregistré",
            String.format("Utilisateur '%s' avec rôle '%s' enregistré",
                dialogData.getUsername(),
                dialogData.getRole())
        ));
    }

    /**
     * Action de sauvegarde depuis le formDialog.
     */
    public void saveFormDialog() {
        FacesContext context = FacesContext.getCurrentInstance();

        context.addMessage(null, new FacesMessage(
            FacesMessage.SEVERITY_INFO,
            "FormDialog enregistré",
            String.format("Titre: '%s' sauvegardé avec succès",
                formDialogData.getTitle())
        ));
    }

    /**
     * Action générique de sauvegarde.
     */
    public void save() {
        FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
            FacesMessage.SEVERITY_INFO,
            "Sauvegardé",
            "Les données ont été sauvegardées avec succès"
        ));
    }

    /**
     * Autocomplétion des villes.
     */
    public List<String> completeVille(String query) {
        String lowerQuery = query.toLowerCase();
        return availableCities.stream()
            .filter(city -> city.toLowerCase().startsWith(lowerQuery))
            .collect(Collectors.toList());
    }

    // ========================================
    // Getters / Setters
    // ========================================

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String getPasswordConfirm() {
        return passwordConfirm;
    }

    public void setPasswordConfirm(String passwordConfirm) {
        this.passwordConfirm = passwordConfirm;
    }

    public DialogData getDialogData() {
        return dialogData;
    }

    public void setDialogData(DialogData dialogData) {
        this.dialogData = dialogData;
    }

    public List<String> getAvailableInterests() {
        return availableInterests;
    }

    public void setAvailableInterests(List<String> availableInterests) {
        this.availableInterests = availableInterests;
    }

    public FormDialogData getFormDialogData() {
        return formDialogData;
    }

    public void setFormDialogData(FormDialogData formDialogData) {
        this.formDialogData = formDialogData;
    }

    public List<SampleUser> getSampleUsers() {
        return sampleUsers;
    }

    public void setSampleUsers(List<SampleUser> sampleUsers) {
        this.sampleUsers = sampleUsers;
    }

    public SampleUser getSelectedUser() {
        return selectedUser;
    }

    public void setSelectedUser(SampleUser selectedUser) {
        this.selectedUser = selectedUser;
    }

    public MenuModel getBreadcrumbModel() {
        return breadcrumbModel;
    }

    public void setBreadcrumbModel(MenuModel breadcrumbModel) {
        this.breadcrumbModel = breadcrumbModel;
    }

    public MenuModel getStepsModel() {
        return stepsModel;
    }

    public void setStepsModel(MenuModel stepsModel) {
        this.stepsModel = stepsModel;
    }

    public MenuModel getSplitButtonModel() {
        return splitButtonModel;
    }

    public void setSplitButtonModel(MenuModel splitButtonModel) {
        this.splitButtonModel = splitButtonModel;
    }

    public int getActiveStep() {
        return activeStep;
    }

    public void setActiveStep(int activeStep) {
        this.activeStep = activeStep;
    }

    public String getTabField1() {
        return tabField1;
    }

    public void setTabField1(String tabField1) {
        this.tabField1 = tabField1;
    }

    public String getTabField2() {
        return tabField2;
    }

    public void setTabField2(String tabField2) {
        this.tabField2 = tabField2;
    }

    public String getInplaceValue() {
        return inplaceValue;
    }

    public void setInplaceValue(String inplaceValue) {
        this.inplaceValue = inplaceValue;
    }

    public List<String> getAvailableCities() {
        return availableCities;
    }

    public void setAvailableCities(List<String> availableCities) {
        this.availableCities = availableCities;
    }

    // ========================================
    // Nested Classes
    // ========================================

    /**
     * Modèle utilisateur pour le formulaire d'inscription.
     */
    public static class User implements Serializable {
        private static final long serialVersionUID = 1L;

        private String prenom;
        private String nom;
        private String email;
        private LocalDate dateNaissance;
        private String password;
        private String pays;
        private String bio;
        private boolean acceptTerms;
        private boolean newsletter;
        private Double solde = 1000.0;
        private boolean notifications = true;
        private List<String> interests = new ArrayList<>();
        private int note = 4;
        private List<String> tags = new ArrayList<>();
        private String favoriteColor = "3f51b5";
        private String genre = "M";
        // Nouveaux champs pour les composants additionnels
        private String telephone;
        private Integer quantity = 1;
        private Integer volume = 50;
        private String ville;

        // Getters / Setters

        public String getPrenom() {
            return prenom;
        }

        public void setPrenom(String prenom) {
            this.prenom = prenom;
        }

        public String getNom() {
            return nom;
        }

        public void setNom(String nom) {
            this.nom = nom;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public LocalDate getDateNaissance() {
            return dateNaissance;
        }

        public void setDateNaissance(LocalDate dateNaissance) {
            this.dateNaissance = dateNaissance;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public String getPays() {
            return pays;
        }

        public void setPays(String pays) {
            this.pays = pays;
        }

        public String getBio() {
            return bio;
        }

        public void setBio(String bio) {
            this.bio = bio;
        }

        public boolean isAcceptTerms() {
            return acceptTerms;
        }

        public void setAcceptTerms(boolean acceptTerms) {
            this.acceptTerms = acceptTerms;
        }

        public boolean isNewsletter() {
            return newsletter;
        }

        public void setNewsletter(boolean newsletter) {
            this.newsletter = newsletter;
        }

        public Double getSolde() {
            return solde;
        }

        public void setSolde(Double solde) {
            this.solde = solde;
        }

        public boolean isNotifications() {
            return notifications;
        }

        public void setNotifications(boolean notifications) {
            this.notifications = notifications;
        }

        public List<String> getInterests() {
            return interests;
        }

        public void setInterests(List<String> interests) {
            this.interests = interests;
        }

        public int getNote() {
            return note;
        }

        public void setNote(int note) {
            this.note = note;
        }

        public List<String> getTags() {
            return tags;
        }

        public void setTags(List<String> tags) {
            this.tags = tags;
        }

        public String getFavoriteColor() {
            return favoriteColor;
        }

        public void setFavoriteColor(String favoriteColor) {
            this.favoriteColor = favoriteColor;
        }

        public String getGenre() {
            return genre;
        }

        public void setGenre(String genre) {
            this.genre = genre;
        }

        public String getTelephone() {
            return telephone;
        }

        public void setTelephone(String telephone) {
            this.telephone = telephone;
        }

        public Integer getQuantity() {
            return quantity;
        }

        public void setQuantity(Integer quantity) {
            this.quantity = quantity;
        }

        public Integer getVolume() {
            return volume;
        }

        public void setVolume(Integer volume) {
            this.volume = volume;
        }

        public String getVille() {
            return ville;
        }

        public void setVille(String ville) {
            this.ville = ville;
        }
    }

    /**
     * Modèle pour les données du dialog de démonstration.
     */
    public static class DialogData implements Serializable {
        private static final long serialVersionUID = 1L;

        private String username;
        private String role;
        private boolean active;

        // Getters / Setters

        public String getUsername() {
            return username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getRole() {
            return role;
        }

        public void setRole(String role) {
            this.role = role;
        }

        public boolean isActive() {
            return active;
        }

        public void setActive(boolean active) {
            this.active = active;
        }
    }

    /**
     * Modèle pour les données du formDialog de démonstration.
     */
    public static class FormDialogData implements Serializable {
        private static final long serialVersionUID = 1L;

        private String title;
        private String description;
        private LocalDate date;

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        public LocalDate getDate() {
            return date;
        }

        public void setDate(LocalDate date) {
            this.date = date;
        }
    }

    /**
     * Modèle utilisateur pour la démonstration du dataTable.
     */
    public static class SampleUser implements Serializable {
        private static final long serialVersionUID = 1L;

        private String nom;
        private String email;
        private boolean active;

        public SampleUser() {}

        public SampleUser(String nom, String email, boolean active) {
            this.nom = nom;
            this.email = email;
            this.active = active;
        }

        public String getNom() {
            return nom;
        }

        public void setNom(String nom) {
            this.nom = nom;
        }

        public String getEmail() {
            return email;
        }

        public void setEmail(String email) {
            this.email = email;
        }

        public boolean isActive() {
            return active;
        }

        public void setActive(boolean active) {
            this.active = active;
        }
    }
}
