using Ablera.Serdica.Authority.Plugins.Base.Models;
using Ablera.Serdica.Common.Tools.Extensions;
using Ablera.Serdica.Extensions.Novell.Directory.Ldap.Attributes;
using Ablera.Serdica.Extensions.Novell.Directory.Ldap.Contracts;
using Ablera.Serdica.Extensions.Novell.Directory.Ldap.Models;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
using Ablera.Serdica.Authority.Plugins.LdapUtilities.Services;

namespace Ablera.Serdica.Authority.Plugin.Ldap;

public sealed class LdapIdentityFacade : LdapIdentityFacadeBase<LdapIdentity, string>
{
    private readonly ILogger<LdapIdentityFacade> logger;

    public LdapIdentityFacade(
        ILogger<LdapIdentityFacade> logger,
        ILogger<LdapIdentityFacadeBase<LdapIdentity, string>> logger2,
        LdapSettingsProvider ldapSettingsProvider,
        IEmailNormalizer emailNormalizer,
        IUsernameNormalizer usernameNormalizer)
            : base(logger2, ldapSettingsProvider, emailNormalizer, usernameNormalizer)
    {
        this.logger = logger;
    }

    public override async Task<AuthenticationResult> AuthenticateAsync(LdapIdentity user, string password, bool lockoutOnFailure = false, CancellationToken ct = default)
    {
        var result = await base.AuthenticateAsync(user, password, lockoutOnFailure, ct);
        if (result.Succeeded == false) return result;

        if (string.IsNullOrWhiteSpace(password))
            return AuthenticationResult.Fail(AuthenticationCode.EmptyCredentials.ToScreamingSnakeCase());

        if (string.IsNullOrWhiteSpace(user.DistinguishedName))
            return AuthenticationResult.Fail(AuthenticationCode.AccountIsNotAuthenticaAble.ToScreamingSnakeCase());


        // Ensure account is active.
        if (user.BulstradAccountStatus != null && !string.Equals(user.BulstradAccountStatus, "active", StringComparison.OrdinalIgnoreCase))
        {
            logger.LogInformation("Bulstrad account {User} is not active (bstDStatus={Status})", user.Username, user.BulstradAccountStatus);
            return AuthenticationResult.Fail(AuthenticationCode.AccountIsNotActive.ToScreamingSnakeCase());
        }

        // Build extra claims and append to principal
        var extraClaims = new[]
        {
                new Claim("bstRole",             user.BulstradRole             ?? string.Empty),
                new Claim("bstContractId",       user.BulstradContractId       ?? string.Empty),
                new Claim("bstManId",            user.BulstradManId            ?? string.Empty),
                new Claim(ClaimTypes.GroupSid,   user.BulstradDepartmentNumber ?? string.Empty)
        };

        return result;
    }
}

