using adas_core.Domain.Enums;

namespace adas_core.LdapLogin.Configuration;

/// <summary>
/// Configuration class for LDAP authentication settings, including server details, user properties, and authority mappings.
/// </summary>
public class LdapConfig
{
    /// <summary>
    /// Indicates whether LDAP authentication is enabled. If set to true, the application will attempt to authenticate users against the configured LDAP server.
    /// </summary>
    public bool Enabled { get; set; }

    /// <summary>
    /// The address of the LDAP server. This can be an IP address or a domain name. It is used to establish a connection to the LDAP server for authentication and user information retrieval.
    /// </summary>
    public string? Server { get; set; }

    /// <summary>
    /// The port number on which the LDAP server is listening. The default value is 389, which is the standard port for LDAP communication. If your LDAP server uses a different port, you can specify it here.
    /// </summary>
    public int? Port { get; set; } = 389;

    /// <summary>
    /// The domain name of the LDAP server. This is typically used in conjunction with the username to form a fully qualified username (e.g., user@domain.com).
    /// </summary>
    public string? UserDomainName { get; set; }

    /// <summary>
    /// The property name in the LDAP directory that corresponds to the username. The default value is "sAMAccountName", which is commonly used in Active Directory environments. 
    /// This property is used to identify the user when performing authentication and retrieving user information from the LDAP server.
    /// </summary>
    public string? UserNameProperty { get; set; } = "sAMAccountName";

    /// <summary>
    /// The base distinguished name (DN) for searching users in the LDAP directory. This is the starting point for LDAP queries to find user entries.
    /// </summary>
    public string? SearchBase { get; set; }

    /// <summary>
    /// The property name in the LDAP directory that corresponds to the user's group memberships. The default value is "memberOf", which is commonly used in Active Directory environments to indicate the groups a user belongs to.
    /// </summary>
    public string? GroupsProperty { get; set; } = "memberOf";

    /// <summary>
    /// The username and password used to bind to the LDAP server for performing searches and authentication. If your LDAP server requires authentication for these operations, you can specify the credentials here.
    /// </summary>
    public string? LdapUser { get; set; }

    /// <summary>
    /// The password associated with the LdapUser for binding to the LDAP server. This should be kept secure and not hard-coded in production environments. 
    /// Consider using secure configuration management practices to handle sensitive information like this.
    /// </summary>
    public string? LdapPassword { get; set; }

    /// <summary>
    /// The property name in the LDAP directory that corresponds to the user's display name. The default value is "displayName", which is commonly used in LDAP directories to represent the full name of the user.
    /// </summary>
    public string? DisplayNameProperty { get; set; } = "displayName";

    /// <summary>
    /// The property name in the LDAP directory that corresponds to the user's first name and last name. 
    /// The default values are "givenName" for the first name and "sn" (surname) for the last name, which are commonly used in LDAP directories to represent these attributes.
    /// </summary>
    public string? FirstNameProperty { get; set; } = "givenName";

    /// <summary>
    /// The property name in the LDAP directory that corresponds to the user's last name. The default value is "sn" (surname), which is commonly used in LDAP directories to represent the last name of the user.
    /// </summary>
    public string? LastNameProperty { get; set; } = "sn";

    /// <summary>
    /// A list of authority mappings that define how LDAP groups are mapped to application roles and permissions. 
    /// Each mapping specifies a group name, the corresponding role in the application, the actions that the role is allowed to perform, and an optional display ID for user-friendly identification.
    /// </summary>
    public List<AuthorityMap> AuthoritiesMap { get; set; } = [];

    /// <summary>
    /// A list of users that are explicitly allowed to access the application, regardless of their LDAP group memberships. 
    /// Each entry specifies the user's name, username, role, actions, and an optional display ID for user-friendly identification.
    /// </summary>
    public List<UserLdap> WhiteList { get; set; } = [];
}

/// <summary>
/// Represents a user in the LDAP authentication context, including their name, username, role, allowed actions, and an optional display ID for user-friendly identification.
/// </summary>
public class UserLdap
{
    /// <summary>
    ///     
    /// </summary>
    public string? Name { get; set; }

    /// <summary>
    /// The username of the user, which is used for authentication and identification purposes. 
    /// This should correspond to the property defined in UserNameProperty in the LdapConfig class, such as "sAMAccountName" for Active Directory environments.
    /// </summary>
    public string? Username { get; set; }

    /// <summary>
    /// The role assigned to the user within the application. This role can be used to determine the user's permissions and access levels within the application.
    /// </summary>
    public string? Rol { get; set; }

    /// <summary>
    /// A list of actions that the user is allowed to perform within the application. These actions can be defined in an enumeration (e.g., ActionsEnum.Actions) 
    /// and can be used to control access to specific features or functionalities based on the user's role and permissions.
    /// </summary>
    public List<ActionsEnum.Actions> Actions { get; set; } = [];

    /// <summary>
    /// An optional display ID for the user, which can be used for user-friendly identification in the application. 
    /// This can be particularly useful in user interfaces or logs where a more descriptive identifier is preferred over the username.
    /// </summary>
    public string? DisplayId { get; set; }
}

/// <summary>
/// Represents a mapping between an LDAP group and an application role, including the group name, corresponding role, allowed actions, and an optional display ID for user-friendly identification.
/// </summary>
public class AuthorityMap
{
    /// <summary>
    /// The name of the LDAP group that is being mapped to an application role. 
    /// This should correspond to the group names defined in the LDAP directory, and it is used to determine which users belong to this group based on their group memberships in the LDAP directory.
    /// </summary>
    public string Group { get; set; } = null!;

    /// <summary>
    /// The role in the application that corresponds to the LDAP group. This role can be used to determine the permissions and access levels for users who belong to the specified LDAP group.
    /// </summary>
    public string? Rol { get; set; }

    /// <summary>
    /// A list of actions that users belonging to the specified LDAP group are allowed to perform within the application. These actions can be defined in an enumeration (e.g., ActionsEnum.Actions)
    /// </summary>
    public List<ActionsEnum.Actions> Actions { get; set; } = [];

    /// <summary>
    /// An optional display ID for the authority mapping, which can be used for user-friendly identification in the application.
    /// </summary>
    public string? DisplayId { get; set; } = null;
}