using System.Security.Cryptography.X509Certificates;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;

namespace FitConnect.Encryption;

public class CertificateHelper {
    private readonly ILogger? _logger;

    public CertificateHelper(ILogger? logger = null) {
        _logger = logger;
    }

    internal bool ValidateCertificate(string keyJson, LogLevel logLevel) =>
        ValidateCertificate(new JsonWebKey(keyJson), logLevel);

    internal bool ValidateCertificate(JsonWebKey key, LogLevel logLevel = LogLevel.Error) {
        var certificates = key.X5c.Select(s => new X509Certificate2(Convert.FromBase64String(s)))
            .ToList();

        _logger?.LogTrace("Found {Count} certificate(s)", certificates.Count);

        var valid = certificates.Aggregate(true,
            (result, cert) => result
                              && ValidateCertificate(cert, out var _, logLevel)
                              && cert.Verify()
        );
        return valid;
    }

    internal bool ValidateCertificate(X509Certificate2 certificateX509,
        out X509ChainStatus[] chainStatus, LogLevel logLevel = LogLevel.Warning) {
        var certificateChain = new X509Chain();
        certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
        certificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
        certificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
        certificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 30);
        certificateChain.Build(certificateX509);

        chainStatus = certificateChain.ChainStatus;

        _logger?.Log(logLevel, "Certificate status: {ObjStatusInformation}",
            certificateChain.ChainStatus.Aggregate("",
                (r, s) => r + "\n\t - " + s.Status + ": " + s.StatusInformation));
        return certificateChain.ChainStatus.Length == 0;
    }
}