namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc;

/// <summary>
/// Site-side <see cref="ISitePskProvider"/> over a single fixed key — the one key a site node
/// presents on every control-plane call it makes to central (<c>CommunicationOptions.GrpcPsk</c>).
/// Central's provider resolves a key <em>per site</em>; a site has exactly one, so it ignores the
/// requested <c>siteId</c> and returns its own key.
/// </summary>
/// <remarks>
/// <b>Fail-closed.</b> An empty key throws, matching the contract on <see cref="ISitePskProvider"/>
/// and the interceptor's own posture: a node shipped without a key must not degrade to an
/// unauthenticated dial.
/// </remarks>
public sealed class StaticSitePskProvider : ISitePskProvider
{
    private readonly string _key;

    /// <summary>Creates the provider bound to a site's own preshared key.</summary>
    /// <param name="key">The site's <c>GrpcPsk</c>. Empty is permitted at construction but throws on use.</param>
    public StaticSitePskProvider(string key)
    {
        _key = key ?? string.Empty;
    }

    /// <inheritdoc />
    public ValueTask<string> GetAsync(string siteId, CancellationToken ct)
    {
        if (string.IsNullOrEmpty(_key))
        {
            throw new InvalidOperationException(
                "No gRPC preshared key is configured for this site (ScadaBridge:Communication:GrpcPsk). "
                + "The control plane is fail-closed: an unauthenticated dial does not happen.");
        }

        return new ValueTask<string>(_key);
    }

    /// <inheritdoc />
    public void Invalidate(string siteId)
    {
        // A single static key never changes for the process lifetime; nothing to drop.
    }
}
