using AyCode.Core.Enums;
using AyCode.Core.Loggers;
using AyCode.Core.Serializers.Binaries;
using AyCode.Services.SignalRs;
using FruitBank.Common;
using FruitBank.Common.Loggers;
using FruitBankHybrid.Shared.Services.Loggers;
using FruitBankHybrid.Shared.Services.SignalRs;
using Microsoft.AspNetCore.Http.Connections;
using Microsoft.AspNetCore.SignalR.Client;

namespace FruitBankHybrid.Shared.Tests;

/// <summary>
/// Test-only factory for <see cref="FruitBankSignalRClient"/>. Builds a <c>HubConnectionBuilder</c>
/// with the same connection settings a production <c>Program.cs</c> would use, wires a logger factory
/// backed by a single <c>SignaRClientLogItemWriter</c> (test-unit AppType, Detail level),
/// and uses <see cref="BinaryProtocolMode.AsyncSegment"/> for the protocol.
/// </summary>
internal static class TestSignalRClientFactory
{
    public static FruitBankSignalRClient Create(string testCategoryName)
    {
        var logWriters = new List<IAcLogWriterClientBase>
        {
            new SignaRClientLogItemWriter(AppType.TestUnit, LogLevel.Detail, testCategoryName)
        };

        Func<string, LoggerClient> loggerFactory =
            categoryName => new LoggerClient(categoryName, logWriters.ToArray());

        var connectionOptions = new AcHubConnectionOptions
        {
            Url = $"{FruitBankConstClient.BaseUrl}/{FruitBankConstClient.DefaultHubName}",
            TransportMaxBufferSize = 30_000_000,
            ApplicationMaxBufferSize = 30_000_000,
            CloseTimeout = TimeSpan.FromSeconds(10),
            KeepAliveInterval = TimeSpan.FromSeconds(60),
            ServerTimeout = TimeSpan.FromSeconds(180),
            SkipNegotiation = true,
            Transports = HttpTransportType.WebSockets,
            UseAutomaticReconnect = true,
            UseStatefulReconnect = true
        };

        var logger = loggerFactory(nameof(FruitBankSignalRClient));

        var hubBuilder = new HubConnectionBuilder().AddAcDefaults(logger, connectionOptions);
        hubBuilder.AddAcBinaryProtocol(opts => opts.ProtocolMode = BinaryProtocolMode.AsyncSegment);

        return new FruitBankSignalRClient(hubBuilder, loggerFactory);
    }
}
