using System;
using System.DirectoryServices;
using System.Web;

namespace CD67.ModeleMVC.MVC.Internal
{ 
    public static class UtilisateurConnecteFactory
    {
        /// <summary>
        /// Retourne un objet UtilisateurConnecté avec les informations pronvenant de l'AD :
        /// nom , prenom , libellé (displayname), email , login, employéID (AstreRH), GUID, SID
        /// Une fois récupéré, les valeurs sont stockées en variable de session, et ne seront récupérées à nouveau depuis l'AD que si nécessaire
        /// </summary>
        /// <returns>L'utilisateur connecté</returns>  
        public static Models.UtilisateurConnecte getUtilisateurConnecte()
        {
            //On récupère l'utilisateur depuis le cache de session
            Models.UtilisateurConnecte utilisateurConnecte = HttpContext.Current.Session["UtilisateurConnecte"] as Models.UtilisateurConnecte;

            //S'il est vide, on le met à jour
            if (utilisateurConnecte == null)
            {
                try
                {
                    DirectoryEntry userEntry = getUserEntry();
                    utilisateurConnecte = new Models.UtilisateurConnecte()
                    {
                        nom = userEntry.Properties["sn"].Value.ToString(),
                        prenom = userEntry.Properties["givenName"].Value.ToString(),
                        libelle = userEntry.Properties["displayName"].Value.ToString(),
                        email = userEntry.Properties["mail"].Value.ToString(),
                        login = userEntry.Properties["sAMAccountName"].Value.ToString(),
                        employeeID = userEntry.Properties["employeeID"].Value == null ? (int?)null : int.Parse(userEntry.Properties["employeeID"].Value.ToString()),
                        guid = userEntry.Properties["objectGUID"].Value as Guid?,
                        sid = userEntry.Properties["objectSid"].Value.ToString()
                    };
                    HttpContext.Current.Session["UtilisateurConnecte"] = utilisateurConnecte;
                }
                catch (Exception ex)
                {
                    throw new Exception("Erreur lors de l'interrogation AD", ex);
                }
            }

            return utilisateurConnecte;
        }

        /// <summary>
        /// Retourne l'entrée dans l'AD de l'utilisateur courant.
        /// Exemple d'accès aux propriétés : userEntry.Properties["givenName"].Value
        /// </summary>
        /// <returns>Entrée utilisateur</returns>
        private static DirectoryEntry getUserEntry()
        {
            try
            {
                string login = HttpContext.Current.User.Identity.Name.ToLower().Replace("cg67\\", "");
                if (login == null) throw new Exception("Impossible de récupérer le login de l'utilisateur courant.");

                DirectoryEntry ldap = new DirectoryEntry("LDAP://CG67.fr/OU=Organisation,dc=CG67,dc=fr", "LectureAD", "Adlecture!");
                DirectorySearcher searcher = new DirectorySearcher(ldap);

                searcher.Filter = $"(sAMAccountName={login})";
                SearchResult result = searcher.FindOne();

                DirectoryEntry userEntry = result.GetDirectoryEntry();
                return userEntry;
            }
            catch (NullReferenceException ex)
            {
                throw new Exception("Le nom d'utilisateur courant n'a pas été retrouvé dans l'AD.", ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Erreur dans la récupération des infos de l'utilisateur.", ex);
            }
        }
    }
}
