namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.Management;

// ─────────────────────────────────────────────────────────────────────────────
// OPC UA server-certificate trust management.
//
// Cert trust is SITE-LOCAL: there is no central persistence of trusted server
// certificates. The trusted-peer PKI store lives on each site node's file
// system, so a trust/remove decision must reach BOTH site nodes (node-a and
// node-b) or the two PKI stores diverge across failover.
//
// The public commands below are handled by the site Deployment Manager
// singleton (active node only). For trust/remove it broadcasts the
// corresponding per-node internal message to the per-node CertStoreActor on
// EVERY site cluster node; for list it answers from the local node.
// ─────────────────────────────────────────────────────────────────────────────

/// <summary>
/// Trust an OPC UA server certificate at every site node. Carries the raw
/// DER bytes (base64-encoded) so the certificate can be written into each
/// node's trusted-peer PKI store. The thumbprint is the store filename key.
/// </summary>
/// <param name="ConnectionName">The data-connection the certificate was captured from (diagnostics / correlation only).</param>
/// <param name="DerBase64">The server certificate's DER encoding, base64-encoded.</param>
/// <param name="Thumbprint">The certificate thumbprint — used as the store filename key.</param>
/// <param name="SiteIdentifier">
/// Target site identifier — REQUIRED when the command is invoked via the management
/// HTTP API/CLI (the actor must route it to a site); ignored on the site side, where
/// routing already happened. Additive per the message-contract evolution rules.
/// </param>
public record TrustServerCertCommand(string ConnectionName, string DerBase64, string Thumbprint, string? SiteIdentifier = null);

/// <summary>
/// Remove a previously-trusted OPC UA server certificate from every site
/// node's trusted-peer PKI store, identified by thumbprint.
/// </summary>
/// <param name="Thumbprint">The thumbprint of the certificate to remove.</param>
/// <param name="SiteIdentifier">
/// Target site identifier — REQUIRED when the command is invoked via the management
/// HTTP API/CLI (the actor must route it to a site); ignored on the site side, where
/// routing already happened. Additive per the message-contract evolution rules.
/// </param>
public record RemoveServerCertCommand(string Thumbprint, string? SiteIdentifier = null);

/// <summary>
/// List the certificates currently present in this site's trusted-peer and
/// rejected PKI stores. Answered from the local node (the Deployment Manager
/// singleton's own node).
/// </summary>
/// <param name="SiteIdentifier">
/// Target site identifier — REQUIRED when the command is invoked via the management
/// HTTP API/CLI (the actor must route it to a site); ignored on the site side, where
/// routing already happened. Additive per the message-contract evolution rules.
/// </param>
public record ListServerCertsCommand(string? SiteIdentifier = null);

/// <summary>
/// Read-only projection of a certificate found in a site PKI store.
/// </summary>
/// <param name="Thumbprint">The certificate thumbprint.</param>
/// <param name="Subject">The certificate subject distinguished name.</param>
/// <param name="Issuer">The certificate issuer distinguished name.</param>
/// <param name="NotBeforeUtc">Validity start (UTC).</param>
/// <param name="NotAfterUtc">Validity end (UTC).</param>
/// <param name="Rejected">True if the certificate is in the rejected store; false if trusted.</param>
public record TrustedCertInfo(
    string Thumbprint,
    string Subject,
    string Issuer,
    DateTime NotBeforeUtc,
    DateTime NotAfterUtc,
    bool Rejected);

/// <summary>
/// Aggregate result of a cert-trust command. For trust/remove, <paramref name="Success"/>
/// reflects whether every reachable site node acked; <paramref name="Error"/> carries the
/// first node error (or a partial-failure note when a node did not ack in time).
/// For list, <paramref name="Certs"/> carries the local node's store contents.
/// </summary>
/// <param name="Success">True when the operation succeeded on all targeted nodes.</param>
/// <param name="Error">First error encountered, or null on success.</param>
/// <param name="Certs">Listed certificates (list command only), otherwise null.</param>
public record CertTrustResult(bool Success, string? Error, IReadOnlyList<TrustedCertInfo>? Certs);

// ── Per-node internal messages (CertStoreActor wire protocol) ──
// Sent by the Deployment Manager singleton to each site node's CertStoreActor,
// or used directly in tests. Not part of the public management surface.

/// <summary>Per-node: decode <paramref name="DerBase64"/> and write it into the local trusted-peer store as <c>&lt;Thumbprint&gt;.der</c>.</summary>
/// <param name="DerBase64">The certificate's DER encoding, base64-encoded.</param>
/// <param name="Thumbprint">The thumbprint used as the store filename key.</param>
public record WriteCertToLocalStore(string DerBase64, string Thumbprint);

/// <summary>Per-node: delete the trusted-peer store file matching <paramref name="Thumbprint"/>.</summary>
/// <param name="Thumbprint">The thumbprint of the certificate to remove.</param>
public record RemoveCertFromLocalStore(string Thumbprint);

/// <summary>Per-node: enumerate the local trusted-peer and rejected stores.</summary>
public record ListLocalCerts();

/// <summary>
/// Per-node: export the trusted-peer store contents (thumbprint + raw DER bytes)
/// so the Deployment Manager singleton can reconcile the trusted set onto a
/// (re)joining site node. Trusted store only — rejected certs are never pushed.
/// </summary>
public record ExportLocalTrustedCerts();

/// <summary>
/// One exported trusted certificate: its thumbprint (store filename key) and the
/// raw DER bytes needed to re-write it into another node's trusted-peer store.
/// </summary>
/// <param name="Thumbprint">The certificate thumbprint.</param>
/// <param name="DerBytes">The certificate's raw DER encoding.</param>
public record ExportedCert(string Thumbprint, byte[] DerBytes);

/// <summary>
/// Per-node reply to <see cref="ExportLocalTrustedCerts"/>: the local trusted-peer
/// store's certificates, or a failure with the IO error.
/// </summary>
/// <param name="Success">True if the trusted store was enumerated successfully.</param>
/// <param name="Error">The error message on failure, otherwise null.</param>
/// <param name="Certs">Exported trusted certificates, empty on failure.</param>
public record LocalCertExport(bool Success, string? Error, IReadOnlyList<ExportedCert> Certs);

/// <summary>
/// Per-node ack for a <see cref="WriteCertToLocalStore"/>, <see cref="RemoveCertFromLocalStore"/>
/// or <see cref="ListLocalCerts"/> operation.
/// </summary>
/// <param name="Success">True if the local store operation succeeded.</param>
/// <param name="Error">The error message on failure, otherwise null.</param>
/// <param name="Certs">Listed certificates (list only), otherwise null.</param>
public record LocalCertOpAck(bool Success, string? Error, IReadOnlyList<TrustedCertInfo>? Certs);
