using DevExpress.Pdf;
using DevExpress.Office.DigitalSignatures;

namespace DXApp.TemplateKitProject.Services;

/// <summary>
/// Service zum digitalen Signieren von PDF-Dokumenten mit DevExpress PdfDocumentSigner
/// </summary>
public class PdfSigningService(
    IConfiguration configuration,
    ILogger<PdfSigningService> logger)
{
    /// <summary>
    /// Signiert eine PDF-Datei mit einem PFX-Zertifikat
    /// </summary>
    public async Task<byte[]> SignPdfAsync(byte[] pdfBytes, PdfSigningOptions? options = null)
    {
        options ??= new PdfSigningOptions();

        return await Task.Run(() =>
        {
            try
            {
                // Zertifikat-Konfiguration laden
                var certPath = options.CertificatePath ?? configuration["PdfSigning:CertificatePath"]
                    ?? throw new InvalidOperationException("PdfSigning:CertificatePath nicht konfiguriert.");

                var certPassword = options.CertificatePassword ?? configuration["PdfSigning:CertificatePassword"]
                    ?? throw new InvalidOperationException("PdfSigning:CertificatePassword nicht konfiguriert.");

                logger.LogInformation("PDF wird signiert mit Zertifikat: {Path}", certPath);

                // PDF in MemoryStream laden
                using var inputStream = new MemoryStream(pdfBytes);
                using var signer = new PdfDocumentSigner(inputStream);

                // PKCS#7 Signatur erstellen
                var pkcs7Signature = new Pkcs7Signer(certPath, certPassword, HashAlgorithmType.SHA256);

                // Signatur-Feld definieren
                var fieldInfo = new PdfSignatureFieldInfo(signer.PageCount - 1); // Letzte Seite
                fieldInfo.Name = $"Signature_{DateTime.Now:yyyyMMdd_HHmmss}";
                fieldInfo.SignatureBounds = new PdfRectangle(
                    options.SignatureX,
                    options.SignatureY,
                    options.SignatureX + options.SignatureWidth,
                    options.SignatureY + options.SignatureHeight
                );

                // Signatur-Builder erstellen
                var signatureBuilder = new PdfSignatureBuilder(pkcs7Signature, fieldInfo);
                signatureBuilder.Name = options.SignerName;
                signatureBuilder.Location = options.Location;
                signatureBuilder.Reason = options.Reason;

                // Optional: Signatur-Bild hinzufügen
                if (!string.IsNullOrEmpty(options.SignatureImagePath) && File.Exists(options.SignatureImagePath))
                {
                    signatureBuilder.SetImageData(File.ReadAllBytes(options.SignatureImagePath));
                    logger.LogDebug("Signatur-Bild hinzugefügt: {Path}", options.SignatureImagePath);
                }

                // Signierte PDF in MemoryStream speichern
                using var outputStream = new MemoryStream();
                signer.SaveDocument(outputStream, signatureBuilder);

                logger.LogInformation(
                    "PDF erfolgreich signiert. Größe: {Original} KB ? {Signed} KB",
                    pdfBytes.Length / 1024,
                    outputStream.Length / 1024
                );

                return outputStream.ToArray();
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Fehler beim Signieren der PDF-Datei.");
                throw;
            }
        });
    }

    /// <summary>
    /// Liest Signatur-Informationen aus einer signierten PDF
    /// </summary>
    public async Task<List<SignatureInformation>> GetSignatureInfoAsync(byte[] pdfBytes)
    {
        return await Task.Run(() =>
        {
            try
            {
                using var stream = new MemoryStream(pdfBytes);
                using var signer = new PdfDocumentSigner(stream);

                var signatures = signer.GetSignatureInfo();
                var result = new List<SignatureInformation>();

                foreach (var sig in signatures)
                {
                    var info = new SignatureInformation
                    {
                        FieldName = sig.FieldName,
                        SignerName = sig.SignerName,
                        Location = sig.Location,
                        Reason = sig.Reason,
                        Date = DateTime.Now, // Wird später aus PKCS#7 gelesen
                        CertificationLevel = sig.CertificationLevel.ToString()
                    };

                    // PKCS#7 Details auslesen
                    try
                    {
                        var pkcs7 = signer.GetPdfPkcs7Signature(sig.FieldName);
                        var cert = pkcs7.GetSignatureCertificate();

                        // Signatur-Datum: GetTimeStampDate oder aktuelles Datum
                        var timestampDate = pkcs7.GetTimeStampDate();
                        info.Date = timestampDate ?? DateTime.Now;

                        info.IsSignatureValid = pkcs7.VerifySignature();
                        info.IsCertificateValid = cert.Verify();
                        info.CertificateIssuer = cert.IssuerName.Name ?? string.Empty;
                        info.CertificateSubject = cert.SubjectName.Name ?? string.Empty;
                        info.CertificateValidUntil = cert.NotAfter;
                    }
                    catch (Exception ex)
                    {
                        logger.LogWarning(ex, "Fehler beim Auslesen der PKCS#7-Details für Signatur '{Name}'", sig.FieldName);
                    }

                    result.Add(info);
                }

                logger.LogInformation("PDF enthält {Count} Signatur(en)", result.Count);
                return result;
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Fehler beim Auslesen der Signatur-Informationen.");
                throw;
            }
        });
    }
}

/// <summary>
/// Optionen für die PDF-Signatur
/// </summary>
public class PdfSigningOptions
{
    public string? CertificatePath { get; set; }
    public string? CertificatePassword { get; set; }
    public string SignerName { get; set; } = "DXApp System";
    public string Location { get; set; } = "Digital Data AG";
    public string Reason { get; set; } = "Dokument digital signiert";

    // Position und Größe der sichtbaren Signatur (in Points, 72 DPI)
    public double SignatureX { get; set; } = 50;
    public double SignatureY { get; set; } = 50;
    public double SignatureWidth { get; set; } = 200;
    public double SignatureHeight { get; set; } = 80;

    public string? SignatureImagePath { get; set; }
}

/// <summary>
/// Informationen über eine PDF-Signatur
/// </summary>
public class SignatureInformation
{
    public string FieldName { get; set; } = string.Empty;
    public string SignerName { get; set; } = string.Empty;
    public string Location { get; set; } = string.Empty;
    public string Reason { get; set; } = string.Empty;
    public DateTime Date { get; set; }
    public string CertificationLevel { get; set; } = string.Empty;

    public bool IsSignatureValid { get; set; }
    public bool IsCertificateValid { get; set; }
    public string CertificateIssuer { get; set; } = string.Empty;
    public string CertificateSubject { get; set; } = string.Empty;
    public DateTime CertificateValidUntil { get; set; }
}
