using System.Diagnostics.CodeAnalysis;

namespace DodoSSH.Client.Domain;

/// <summary>
/// What every kind of decrypted vault item has in common.
/// </summary>
/// <remarks>
/// <para>
/// Two members, and both are here because the sync layer needs them for every item type it handles: a
/// name to put in a message to a person, and the check that must pass before the item is sealed.
/// Everything else about an item — how it is encoded, how two versions of it merge, which plaintext
/// columns the server is allowed to see — is per-type behaviour that lives in the sync layer's item
/// kinds rather than on the record. The split is not arbitrary: a label and a validity rule are
/// intrinsic to the thing, whereas how it is encrypted is a decision about how it is stored.
/// </para>
/// <para>
/// An interface rather than a base record, because the implementations share no field — a base record
/// would exist solely to declare two abstract members, and would put a type in the equality contract of
/// records that have nothing else in common. The server's <c>IVaultItem</c> is an interface for a
/// sharper reason (EF Core maps a visible base class as a TPH hierarchy) but reaches the same place.
/// </para>
/// </remarks>
public interface IVaultSecret
{
    /// <summary>What the user calls this item. The only name it has anywhere.</summary>
    string Label { get; }

    /// <summary>Whether this is storable, and why not if it is not.</summary>
    /// <remarks>
    /// The out parameter is <c>reason</c> rather than the <c>error</c> every implementation used before
    /// this interface existed, because CA1716 refuses a reserved word from another CLR language on an
    /// interface member. Renamed at the implementations too: a parameter name that differs from the one it
    /// implements is legal and reads as an oversight.
    /// </remarks>
    bool TryValidate([NotNullWhen(false)] out string? reason);
}
