using System;
using FinlyticEngine.Database;
using FinlyticEngine.Services.Trading;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace FinlyticEngine.Tests.TestSupport;
///
/// Builds a real wired against an EF Core InMemory-backed
/// resolved through a genuine — the same
/// DI shape production code uses (a fresh scoped DbContext per call). This is deliberately NOT a fake
/// DbContext: using the real EngineDbContext against the InMemory provider means the tenant-filtering LINQ
/// predicates in TradeLifecycleService are actually evaluated by EF Core, not bypassed.
///
/// DB approach: see the "DB-Ansatz" section of the final task report for why InMemory was chosen over
/// SQLite and Testcontainers/real Postgres.
///
public sealed class TradeLifecycleServiceHarness : IDisposable
{
private readonly ServiceProvider _provider;
public TradeLifecycleService Sut { get; }
public FakeEngineRpcClient RpcClient { get; }
public FakeSettingsService SettingsService { get; }
public IServiceScopeFactory ScopeFactory { get; }
public TradeLifecycleServiceHarness()
{
var dbName = Guid.NewGuid().ToString("N");
var services = new ServiceCollection();
services.AddDbContext(o => o.UseInMemoryDatabase(dbName));
_provider = services.BuildServiceProvider();
ScopeFactory = _provider.GetRequiredService();
RpcClient = new FakeEngineRpcClient();
SettingsService = new FakeSettingsService();
Sut = new TradeLifecycleService(
ScopeFactory,
new NeverInvokedCompositeOpportunityScorer(),
new NeverInvokedAiReasoningGateService(),
new NeverInvokedKnockOutDerivativeResolver(),
RpcClient,
SettingsService,
new FakeFinlyticLogger());
}
///
/// Opens a fresh scope and returns its , mirroring how the service itself
/// obtains a DbContext per call. Caller is responsible for disposing the returned scope via
/// semantics (use inside a using block on the returned context's
/// owning scope where needed) — for simplicity in tests we just dispose the DbContext itself, since the
/// InMemory provider keeps data keyed by database name, not by context instance.
///
public EngineDbContext OpenDbContext()
{
var scope = ScopeFactory.CreateScope();
return scope.ServiceProvider.GetRequiredService();
}
public void Dispose() => _provider.Dispose();
}