using GostCryptography.Gost_R3411;
using Hcs.Client.Api;
using Hcs.Client.Internal;
using System;
using System.Security.Cryptography.X509Certificates;

namespace Hcs.Client
{
    /// <summary>
    /// Универсальный клиент для вызова всех реализованных функций интеграции с ГИС ЖКХ
    /// </summary>
    public class UniClient : ClientBase
    {
        public BillsApi Bills => new(this);

        public DeviceMeteringApi DeviceMetering => new(this);

        public HouseManagementApi HouseManagement => new(this);

        public NsiApi Nsi => new(this);

        public NsiCommonApi NsiCommon => new(this);

        public OrgRegistryCommonApi OrgRegistryCommon => new(this);

        public PaymentsApi Payments => new(this);

        public void SetSigningCertificate(X509Certificate2 cert, string pin = null)
        {
            pin ??= Constants.DEFAULT_CERTIFICATE_PIN;

            Certificate = cert ?? throw new ArgumentNullException("Certificate not specified");
            CryptoProviderType = cert.GetProviderType();
            CertificateThumbprint = cert.Thumbprint;
            CertificatePassword = pin;
        }

        public X509Certificate2 FindCertificate(Func<X509Certificate2, bool> predicate)
        {
            return CertificateHelper.FindCertificate(predicate);
        }

        /// <summary>
        /// Производит для потока хэш по алгоритму "ГОСТ Р 34.11-94" в строке binhex
        /// </summary>
        public string ComputeGost94Hash(System.IO.Stream stream)
        {
            // API HouseManagement указывает, что файлы приложенные к договору должны размещаться
            // с AttachmentHASH по стандарту ГОСТ. Оказывается, ГИС ЖКХ требует применения устаревшего
            // алгоритма ГОСТ Р 34.11-94 (соответствует `rhash --gost94-cryptopro file` в linux).
            using var algorithm = new Gost_R3411_94_HashAlgorithm(GostCryptoProviderType);
            var savedPosition = stream.Position;
            stream.Position = 0;
            var hashValue = Util.ConvertToHexString(algorithm.ComputeHash(stream));
            stream.Position = savedPosition;
            return hashValue;
        }
    }
}
