namespace ZB.MOM.WW.Secrets.Abstractions;

/// <summary>
/// Persists encrypted secret rows and exposes the read, list, and replication operations the
/// core services build on. The store only ever handles the encrypted <see cref="StoredSecret"/>
/// representation and its safe <see cref="SecretMetadata"/> projection — it never sees plaintext.
/// Deletes are soft (tombstones) so removals can propagate across a cluster.
/// </summary>
public interface ISecretStore
{
    /// <summary>
    /// Returns the row for <paramref name="name"/>, including a tombstoned row, or <c>null</c>
    /// if no row exists.
    /// </summary>
    /// <param name="name">The secret to fetch.</param>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns>The stored row, or <c>null</c> if absent.</returns>
    Task<StoredSecret?> GetAsync(SecretName name, CancellationToken ct);

    /// <summary>
    /// Inserts the row, or overwrites an existing row in place, bumping its revision and
    /// updated timestamp.
    /// </summary>
    /// <param name="row">The encrypted row to persist.</param>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns>A task that completes when the row is persisted.</returns>
    Task UpsertAsync(StoredSecret row, CancellationToken ct);

    /// <summary>
    /// Soft-deletes (tombstones) the row for <paramref name="name"/> so the deletion can
    /// propagate to peers.
    /// </summary>
    /// <param name="name">The secret to tombstone.</param>
    /// <param name="actor">The principal to record as <c>updated_by</c>, if known.</param>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns><c>true</c> if a row was tombstoned; <c>false</c> if the row was absent.</returns>
    Task<bool> DeleteAsync(SecretName name, string? actor, CancellationToken ct);

    /// <summary>
    /// Lists the safe metadata projection for all secrets — never ciphertext.
    /// </summary>
    /// <param name="includeDeleted">
    /// When <c>true</c>, tombstoned rows are included; otherwise they are omitted.
    /// </param>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns>The metadata for the matching secrets.</returns>
    Task<IReadOnlyList<SecretMetadata>> ListAsync(bool includeDeleted, CancellationToken ct);

    /// <summary>
    /// Returns a compact manifest — name, revision, updated timestamp, and tombstone flag per
    /// secret — used for cluster anti-entropy reconciliation without exchanging ciphertext.
    /// </summary>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns>The manifest entries for all secrets.</returns>
    Task<IReadOnlyList<SecretManifestEntry>> GetManifestAsync(CancellationToken ct);

    /// <summary>
    /// Applies a row received from a peer using last-writer-wins on
    /// (<see cref="StoredSecret.UpdatedUtc"/>, <see cref="StoredSecret.Revision"/>). A row that
    /// is not newer than the local row is ignored.
    /// </summary>
    /// <param name="row">The replicated encrypted row to apply.</param>
    /// <param name="ct">A token to cancel the operation.</param>
    /// <returns>A task that completes when the row has been applied or ignored.</returns>
    Task ApplyReplicatedAsync(StoredSecret row, CancellationToken ct);
}
