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.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.jboss.logging.Logger;
import java.util.stream.Collectors;

@Named("documentsBean")
@SessionScoped
public class DocumentsBean implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(DocumentsBean.class);
    
    // Constantes de navigation outcomes (WOU/DRY - réutilisables)
    private static final String OUTCOME_DOCUMENTS_VERSIONS = "documentsVersionsPage";
    
    private List<Document> tousLesDocuments;
    private List<Document> documentsFiltres;
    private List<Document> documentsSelectionnes;
    private List<Dossier> dossiersAffichage;
    private List<Dossier> dossiersDisponibles;
    private List<NiveauNavigation> cheminNavigation;
    
    private Document documentSelectionne;
    private Dossier dossierSelectionne;
    private NouveauDocument nouveauDocument;
    private Filtres filtres;
    private StatistiquesDocuments statistiques;
    
    private String modeAffichage = "GRID"; // GRID ou LIST
    private UUID dossierActuelId;
    
    @PostConstruct
    public void init() {
        initializeFiltres();
        initializeStatistiques();
        initializeDossiers();
        initializeDocuments();
        initializeNouveauDocument();
        initializeNavigation();
        appliquerFiltres();
    }
    
    private void initializeFiltres() {
        filtres = new Filtres();
        documentsSelectionnes = new ArrayList<>();
    }
    
    private void initializeStatistiques() {
        statistiques = new StatistiquesDocuments();
        try {
            // Les statistiques seront calculées depuis les documents réels
            // Pour l'instant, initialiser avec des valeurs par défaut
            statistiques.setTotalDocuments(tousLesDocuments != null ? tousLesDocuments.size() : 0);
            statistiques.setTotalDossiers(dossiersDisponibles != null ? dossiersDisponibles.size() : 0);
            statistiques.setEspaceUtilise("0 GB");
            statistiques.setPartagesMois(0);
        } catch (Exception e) {
            LOG.errorf(e, "Erreur lors du calcul des statistiques");
            statistiques.setTotalDocuments(0);
            statistiques.setTotalDossiers(0);
            statistiques.setEspaceUtilise("0 GB");
            statistiques.setPartagesMois(0);
        }
    }
    
    private void initializeDossiers() {
        dossiersAffichage = new ArrayList<>();
        dossiersDisponibles = new ArrayList<>();
        // Les dossiers seront chargés depuis l'API backend
        // Pour l'instant, laisser les listes vides plutôt que des données mockées
    }
    
    private void initializeDocuments() {
        tousLesDocuments = new ArrayList<>();
        // Les documents seront chargés depuis l'API backend
        // Pour l'instant, laisser la liste vide plutôt que des données mockées
    }
    
    private void initializeNouveauDocument() {
        nouveauDocument = new NouveauDocument();
        nouveauDocument.setAccesRestreint(false);
    }
    
    private void initializeNavigation() {
        cheminNavigation = new ArrayList<>();
        
        NiveauNavigation racine = new NiveauNavigation();
        racine.setNom("📁 Racine");
        racine.setDossierId(null);
        cheminNavigation.add(racine);
        
        // Si on est dans un dossier spécifique, ajouter le niveau
        if (dossierActuelId != null) {
            Dossier dossierActuel = dossiersDisponibles.stream()
                    .filter(d -> d.getId().equals(dossierActuelId))
                    .findFirst()
                    .orElse(null);
            
            if (dossierActuel != null) {
                NiveauNavigation niveau = new NiveauNavigation();
                niveau.setNom(dossierActuel.getNom());
                niveau.setDossierId(dossierActuel.getId());
                cheminNavigation.add(niveau);
            }
        }
    }
    
    private void appliquerFiltres() {
        documentsFiltres = tousLesDocuments.stream()
                .filter(this::appliquerFiltre)
                .collect(Collectors.toList());
    }
    
    private boolean appliquerFiltre(Document document) {
        // Filtre par dossier actuel
        if (dossierActuelId != null) {
            if (document.getDossierId() == null || !document.getDossierId().equals(dossierActuelId)) {
                return false;
            }
        } else {
            // Si on est à la racine, ne montrer que les documents sans dossier parent
            if (document.getDossierId() != null) {
                return false;
            }
        }
        
        if (filtres.getNom() != null && !filtres.getNom().trim().isEmpty()) {
            if (!document.getNom().toLowerCase().contains(filtres.getNom().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
            if (!document.getType().equals(filtres.getType())) {
                return false;
            }
        }
        
        if (filtres.getCategorie() != null && !filtres.getCategorie().trim().isEmpty()) {
            if (!document.getCategorie().equals(filtres.getCategorie())) {
                return false;
            }
        }
        
        if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
            if (!document.getStatut().equals(filtres.getStatut())) {
                return false;
            }
        }
        
        if (filtres.getAuteur() != null && !filtres.getAuteur().trim().isEmpty()) {
            if (!document.getAuteur().toLowerCase().contains(filtres.getAuteur().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getMotsCles() != null && !filtres.getMotsCles().trim().isEmpty()) {
            if (!document.getMotsCles().toLowerCase().contains(filtres.getMotsCles().toLowerCase())) {
                return false;
            }
        }
        
        if (filtres.getDateDebut() != null) {
            if (document.getDateCreation().toLocalDate().isBefore(filtres.getDateDebut())) {
                return false;
            }
        }
        
        if (filtres.getDateFin() != null) {
            if (document.getDateCreation().toLocalDate().isAfter(filtres.getDateFin())) {
                return false;
            }
        }
        
        if (filtres.getTailleMax() != null && filtres.getTailleMax() > 0) {
            long tailleMaxBytes = filtres.getTailleMax().longValue() * 1024 * 1024; // Conversion MB vers bytes
            if (document.getTailleBytes() > tailleMaxBytes) {
                return false;
            }
        }
        
        return true;
    }
    
    // Actions
    public void rechercher() {
        appliquerFiltres();
    }
    
    public void reinitialiserFiltres() {
        filtres = new Filtres();
        appliquerFiltres();
    }
    
    public void changerModeAffichage(String mode) {
        this.modeAffichage = mode;
    }
    
    public void naviguerVersDossier(Dossier dossier) {
        this.dossierActuelId = dossier.getId();
        initializeNavigation();
        appliquerFiltres();
    }
    
    public void telechargerNouveauDocument() {
        Document nouveau = new Document();
        nouveau.setId(UUID.randomUUID());
        nouveau.setNom("Nouveau Document " + (tousLesDocuments.size() + 1));
        nouveau.setCategorie(nouveauDocument.getCategorie());
        nouveau.setDescription(nouveauDocument.getDescription());
        nouveau.setMotsCles(nouveauDocument.getMotsCles());
        nouveau.setDossierId(nouveauDocument.getDossierId());
        nouveau.setStatut("BROUILLON");
        nouveau.setAuteur("Utilisateur Actuel");
        nouveau.setDateCreation(LocalDateTime.now());
        nouveau.setDateModification(LocalDateTime.now());
        nouveau.setTailleBytes(1024000L); // 1MB par défaut
        nouveau.setNombreVues(0);
        nouveau.setNombreTelecharements(0);
        nouveau.setType("PDF"); // Type par défaut
        
        tousLesDocuments.add(nouveau);
        appliquerFiltres();
        
        LOG.infof("Document téléchargé: %s", nouveau.getNom());
        initializeNouveauDocument();
    }
    
    public void telechargerDocument(Document document) {
        document.setNombreTelecharements(document.getNombreTelecharements() + 1);
        LOG.infof("Téléchargement du document: %s", document.getNom());
    }
    
    public void supprimerDocument(Document document) {
        tousLesDocuments.remove(document);
        appliquerFiltres();
        LOG.infof("Document supprimé: %s", document.getNom());
    }
    
    public void dupliquerDocument() {
        if (documentSelectionne != null) {
            Document copie = new Document();
            copie.setId(UUID.randomUUID());
            copie.setNom(documentSelectionne.getNom() + " (Copie)");
            copie.setType(documentSelectionne.getType());
            copie.setCategorie(documentSelectionne.getCategorie());
            copie.setStatut("BROUILLON");
            copie.setAuteur("Utilisateur Actuel");
            copie.setDescription(documentSelectionne.getDescription());
            copie.setMotsCles(documentSelectionne.getMotsCles());
            copie.setDossierId(documentSelectionne.getDossierId());
            copie.setTailleBytes(documentSelectionne.getTailleBytes());
            copie.setDateCreation(LocalDateTime.now());
            copie.setDateModification(LocalDateTime.now());
            copie.setNombreVues(0);
            copie.setNombreTelecharements(0);
            
            tousLesDocuments.add(copie);
            appliquerFiltres();
            LOG.infof("Document dupliqué: %s", copie.getNom());
        }
    }
    
    public void archiverDocument() {
        if (documentSelectionne != null) {
            documentSelectionne.setStatut("ARCHIVE");
            LOG.infof("Document archivé: %s", documentSelectionne.getNom());
            appliquerFiltres();
        }
    }
    
    public void supprimerDefinitivement() {
        if (documentSelectionne != null) {
            tousLesDocuments.remove(documentSelectionne);
            appliquerFiltres();
            LOG.infof("Document supprimé définitivement: %s", documentSelectionne.getNom());
        }
    }
    
    public String voirHistoriqueVersions() {
        // Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
        return OUTCOME_DOCUMENTS_VERSIONS + "?id=" + documentSelectionne.getId() + "&faces-redirect=true";
    }
    
    public boolean estSelectionne(Document document) {
        return documentsSelectionnes.contains(document);
    }
    
    public void toggleSelection(Document document) {
        if (documentsSelectionnes.contains(document)) {
            documentsSelectionnes.remove(document);
        } else {
            documentsSelectionnes.add(document);
        }
    }
    
    // Getters et Setters
    public List<Document> getTousLesDocuments() { return tousLesDocuments; }
    public void setTousLesDocuments(List<Document> tousLesDocuments) { this.tousLesDocuments = tousLesDocuments; }
    
    public List<Document> getDocumentsFiltres() { return documentsFiltres; }
    public void setDocumentsFiltres(List<Document> documentsFiltres) { this.documentsFiltres = documentsFiltres; }
    
    public List<Document> getDocumentsSelectionnes() { return documentsSelectionnes; }
    public void setDocumentsSelectionnes(List<Document> documentsSelectionnes) { this.documentsSelectionnes = documentsSelectionnes; }
    
    public List<Dossier> getDossiersAffichage() { return dossiersAffichage; }
    public void setDossiersAffichage(List<Dossier> dossiersAffichage) { this.dossiersAffichage = dossiersAffichage; }
    
    public List<Dossier> getDossiersDisponibles() { return dossiersDisponibles; }
    public void setDossiersDisponibles(List<Dossier> dossiersDisponibles) { this.dossiersDisponibles = dossiersDisponibles; }
    
    public List<NiveauNavigation> getCheminNavigation() { return cheminNavigation; }
    public void setCheminNavigation(List<NiveauNavigation> cheminNavigation) { this.cheminNavigation = cheminNavigation; }
    
    public Document getDocumentSelectionne() { return documentSelectionne; }
    public void setDocumentSelectionne(Document documentSelectionne) { this.documentSelectionne = documentSelectionne; }
    
    public Dossier getDossierSelectionne() { return dossierSelectionne; }
    public void setDossierSelectionne(Dossier dossierSelectionne) { this.dossierSelectionne = dossierSelectionne; }
    
    public NouveauDocument getNouveauDocument() { return nouveauDocument; }
    public void setNouveauDocument(NouveauDocument nouveauDocument) { this.nouveauDocument = nouveauDocument; }
    
    public Filtres getFiltres() { return filtres; }
    public void setFiltres(Filtres filtres) { this.filtres = filtres; }
    
    public StatistiquesDocuments getStatistiques() { return statistiques; }
    public void setStatistiques(StatistiquesDocuments statistiques) { this.statistiques = statistiques; }
    
    public String getModeAffichage() { return modeAffichage; }
    public void setModeAffichage(String modeAffichage) { this.modeAffichage = modeAffichage; }
    
    public UUID getDossierActuelId() { return dossierActuelId; }
    public void setDossierActuelId(UUID dossierActuelId) { this.dossierActuelId = dossierActuelId; }
    
    // Classes internes
    public static class Document {
        private UUID id;
        private String nom;
        private String description;
        private String type;
        private String categorie;
        private String statut;
        private String auteur;
        private String motsCles;
        private UUID dossierId;
        private long tailleBytes;
        private LocalDateTime dateCreation;
        private LocalDateTime dateModification;
        private int nombreVues;
        private int nombreTelecharements;
        private boolean accesRestreint;
        
        // Getters et setters
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        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 getCategorie() { return categorie; }
        public void setCategorie(String categorie) { this.categorie = categorie; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getAuteur() { return auteur; }
        public void setAuteur(String auteur) { this.auteur = auteur; }
        
        public String getMotsCles() { return motsCles; }
        public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
        
        public UUID getDossierId() { return dossierId; }
        public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
        
        public long getTailleBytes() { return tailleBytes; }
        public void setTailleBytes(long tailleBytes) { this.tailleBytes = tailleBytes; }
        
        public LocalDateTime getDateCreation() { return dateCreation; }
        public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
        
        public LocalDateTime getDateModification() { return dateModification; }
        public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
        
        public int getNombreVues() { return nombreVues; }
        public void setNombreVues(int nombreVues) { this.nombreVues = nombreVues; }
        
        public int getNombreTelecharements() { return nombreTelecharements; }
        public void setNombreTelecharements(int nombreTelecharements) { this.nombreTelecharements = nombreTelecharements; }
        
        public boolean isAccesRestreint() { return accesRestreint; }
        public void setAccesRestreint(boolean accesRestreint) { this.accesRestreint = accesRestreint; }
        
        // Propriétés dérivées
        public String getTypeIcon() {
            return switch (type) {
                case "PDF" -> "pi-file-pdf";
                case "WORD" -> "pi-file-word";
                case "EXCEL" -> "pi-file-excel";
                case "POWERPOINT" -> "pi-file";
                case "IMAGE" -> "pi-image";
                default -> "pi-file";
            };
        }
        
        public String getTypeCouleur() {
            return switch (type) {
                case "PDF" -> "red-500";
                case "WORD" -> "blue-500";
                case "EXCEL" -> "green-500";
                case "POWERPOINT" -> "orange-500";
                case "IMAGE" -> "purple-500";
                default -> "gray-500";
            };
        }
        
        public String getCategorieLibelle() {
            return switch (categorie) {
                case "ADMINISTRATIF" -> "Administratif";
                case "FINANCIER" -> "Financier";
                case "JURIDIQUE" -> "Juridique";
                case "COMMUNICATION" -> "Communication";
                case "FORMATION" -> "Formation";
                case "AUTRE" -> "Autre";
                default -> categorie;
            };
        }
        
        public String getCategorieSeverity() {
            return switch (categorie) {
                case "ADMINISTRATIF" -> "info";
                case "FINANCIER" -> "success";
                case "JURIDIQUE" -> "danger";
                case "COMMUNICATION" -> "warning";
                case "FORMATION" -> "primary";
                case "AUTRE" -> "secondary";
                default -> "secondary";
            };
        }
        
        public String getStatutLibelle() {
            return switch (statut) {
                case "BROUILLON" -> "Brouillon";
                case "VALIDE" -> "Validé";
                case "ARCHIVE" -> "Archivé";
                case "EXPIRE" -> "Expiré";
                default -> statut;
            };
        }
        
        public String getStatutSeverity() {
            return switch (statut) {
                case "BROUILLON" -> "warning";
                case "VALIDE" -> "success";
                case "ARCHIVE" -> "secondary";
                case "EXPIRE" -> "danger";
                default -> "secondary";
            };
        }
        
        public String getTaille() {
            if (tailleBytes < 1024) {
                return tailleBytes + " B";
            } else if (tailleBytes < 1024 * 1024) {
                return Math.round(tailleBytes / 1024.0) + " KB";
            } else {
                return Math.round(tailleBytes / (1024.0 * 1024)) + " MB";
            }
        }
        
        public String getDateCreationFormatee() {
            if (dateCreation == null) return "";
            return dateCreation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
        }
        
        public String getDateCreationRelative() {
            if (dateCreation == null) return "";
            long jours = ChronoUnit.DAYS.between(dateCreation.toLocalDate(), LocalDate.now());
            if (jours == 0) return "Aujourd'hui";
            if (jours == 1) return "Hier";
            if (jours < 7) return "Il y a " + jours + " jours";
            if (jours < 30) return "Il y a " + (jours / 7) + " semaine" + (jours / 7 > 1 ? "s" : "");
            return "Il y a " + (jours / 30) + " mois";
        }
    }
    
    public static class Dossier {
        private UUID id;
        private String nom;
        private String couleur;
        private int nombreDocuments;
        private LocalDateTime derniereModification;
        private String cheminComplet;
        
        // Getters et setters
        public UUID getId() { return id; }
        public void setId(UUID id) { this.id = id; }
        
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        public String getCouleur() { return couleur; }
        public void setCouleur(String couleur) { this.couleur = couleur; }
        
        public int getNombreDocuments() { return nombreDocuments; }
        public void setNombreDocuments(int nombreDocuments) { this.nombreDocuments = nombreDocuments; }
        
        public LocalDateTime getDerniereModification() { return derniereModification; }
        public void setDerniereModification(LocalDateTime derniereModification) { this.derniereModification = derniereModification; }
        
        public String getCheminComplet() { return cheminComplet; }
        public void setCheminComplet(String cheminComplet) { this.cheminComplet = cheminComplet; }
        
        public String getDerniereModificationRelative() {
            if (derniereModification == null) return "";
            long jours = ChronoUnit.DAYS.between(derniereModification.toLocalDate(), LocalDate.now());
            if (jours == 0) return "aujourd'hui";
            if (jours == 1) return "hier";
            return "il y a " + jours + " jours";
        }
    }
    
    public static class NouveauDocument {
        private String categorie;
        private String description;
        private String motsCles;
        private UUID dossierId;
        private boolean accesRestreint;
        
        // Getters et setters
        public String getCategorie() { return categorie; }
        public void setCategorie(String categorie) { this.categorie = categorie; }
        
        public String getDescription() { return description; }
        public void setDescription(String description) { this.description = description; }
        
        public String getMotsCles() { return motsCles; }
        public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
        
        public UUID getDossierId() { return dossierId; }
        public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
        
        public boolean isAccesRestreint() { return accesRestreint; }
        public void setAccesRestreint(boolean accesRestreint) { this.accesRestreint = accesRestreint; }
    }
    
    public static class Filtres {
        private String nom;
        private String type;
        private String categorie;
        private String statut;
        private String auteur;
        private String motsCles;
        private LocalDate dateDebut;
        private LocalDate dateFin;
        private Double tailleMax;
        
        // Getters et setters
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        public String getType() { return type; }
        public void setType(String type) { this.type = type; }
        
        public String getCategorie() { return categorie; }
        public void setCategorie(String categorie) { this.categorie = categorie; }
        
        public String getStatut() { return statut; }
        public void setStatut(String statut) { this.statut = statut; }
        
        public String getAuteur() { return auteur; }
        public void setAuteur(String auteur) { this.auteur = auteur; }
        
        public String getMotsCles() { return motsCles; }
        public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
        
        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 Double getTailleMax() { return tailleMax; }
        public void setTailleMax(Double tailleMax) { this.tailleMax = tailleMax; }
    }
    
    public static class StatistiquesDocuments {
        private int totalDocuments;
        private int totalDossiers;
        private String espaceUtilise;
        private int partagesMois;
        
        // Getters et setters
        public int getTotalDocuments() { return totalDocuments; }
        public void setTotalDocuments(int totalDocuments) { this.totalDocuments = totalDocuments; }
        
        public int getTotalDossiers() { return totalDossiers; }
        public void setTotalDossiers(int totalDossiers) { this.totalDossiers = totalDossiers; }
        
        public String getEspaceUtilise() { return espaceUtilise; }
        public void setEspaceUtilise(String espaceUtilise) { this.espaceUtilise = espaceUtilise; }
        
        public int getPartagesMois() { return partagesMois; }
        public void setPartagesMois(int partagesMois) { this.partagesMois = partagesMois; }
    }
    
    public static class NiveauNavigation {
        private String nom;
        private UUID dossierId;
        
        // Getters et setters
        public String getNom() { return nom; }
        public void setNom(String nom) { this.nom = nom; }
        
        public UUID getDossierId() { return dossierId; }
        public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
    }
}
