using ZB.MOM.WW.Secrets.Abstractions;
using ZB.MOM.WW.Secrets.Replicator.SqlServer;
using ZB.MOM.WW.Secrets.Sqlite;

namespace ZB.MOM.WW.Secrets.Replicator.SqlServer.Tests.Fakes;

/// <summary>
/// An <see cref="ISecretReplicationHub"/> backed by a real SQLite store, standing in for the shared
/// SQL-Server hub in offline convergence tests.
/// </summary>
/// <remarks>
/// Deliberately backed by a real store rather than a dictionary: the behaviour under test is
/// last-writer-wins convergence, which lives in <c>ApplyReplicatedAsync</c>. A hand-rolled fake would
/// be re-implementing the very logic the tests exist to check, and would happily agree with a broken
/// reconciler. The live SQL-Server tests then confirm the T-SQL store behaves the same way.
/// </remarks>
/// <param name="store">The SQLite store standing in for the hub database.</param>
public sealed class SqliteBackedHub(SqliteSecretStore store) : ISecretReplicationHub
{
    /// <summary>Number of times the sweep asked this hub for rows — asserts the fetch was skipped.</summary>
    public int GetManyCallCount { get; private set; }

    /// <inheritdoc />
    public Task<IReadOnlyList<SecretManifestEntry>> GetManifestAsync(CancellationToken ct) =>
        store.GetManifestAsync(ct);

    /// <inheritdoc />
    public async Task<IReadOnlyList<StoredSecret>> GetManyAsync(
        IReadOnlyList<SecretName> names, CancellationToken ct)
    {
        GetManyCallCount++;

        var rows = new List<StoredSecret>(names.Count);

        foreach (SecretName name in names)
        {
            StoredSecret? row = await store.GetAsync(name, ct);

            if (row is not null)
            {
                rows.Add(row);
            }
        }

        return rows;
    }

    /// <inheritdoc />
    public Task ApplyReplicatedAsync(StoredSecret row, CancellationToken ct) =>
        store.ApplyReplicatedAsync(row, ct);
}
