using DigitalData.Core.Abstractions.Security.Key;
using System.Security.Cryptography;

namespace DigitalData.Core.Security.RSAKey.Base;

public class RSAPrivateKey : RSAKeyBase, IAsymmetricPrivateKey, IAsymmetricKey
{
    private string? _pem;

    public override string Content
    {
#pragma warning disable CS8603 // Possible null reference return.
        get => _pem;
#pragma warning restore CS8603 // Possible null reference return.
        init
        {
            _pem = value;
            Init();
        }
    }

    public bool IsPemNull => _pem is null;

    public bool IsEncrypted { get; init; }

    protected TPublicKey CreatePublicKey<TPublicKey>() where TPublicKey : RSAPublicKey, new()
        => new() { Content = RSA.ExportRSAPublicKeyPem() };

    private readonly Lazy<RSAPublicKey> _lazyPublicKey;

    public IAsymmetricPublicKey PublicKey => _lazyPublicKey.Value;

    public RSAPrivateKey()
    {
        _lazyPublicKey = new(CreatePublicKey<RSAPublicKey>);
    }

    internal void SetPem(string pem)
    {
        _pem = pem;
        Init();
    }

    private void Init()
    {
        if (string.IsNullOrEmpty(_pem))
            throw new InvalidOperationException($"The content of RSA private key is null or empty. Id: {Id}.");

        if (IsEncrypted)
            RSA.ImportFromEncryptedPem(Content, Secrets.PBE_PASSWORD.AsSpan());
        else
            RSA.ImportFromPem(Content);
    }
}