using Deal.Grpc.Hosting.Interceptors;
using Deal.Grpc.Hosting.Models;
using Deal.Grpc.Hosting.Options;
using Deal.Grpc.Hosting.Services;
using Deal.Telegram.Core;
using Deal.Telegram.Dialogs;
using Deal.Telegram.Discovery;
using Deal.Telegram.Hosting;
using Deal.Telegram.Sessions;
using Deal.Telegram.Telegram;
namespace Deal.Telegram;
///
/// Собирает WebApplication gRPC-хоста telegram-service.
///
public static class TelegramServiceHost
{
///
/// Создаёт (не запускает) хост
///
/// TCP-порт Kestrel.
/// Аргументы командной строки (Program.cs); в тестах не нужны.
/// Опциональный хук DI для тестов (подмена зависимостей фейками, напр. ITelegramClientFactory).
/// Опциональный хук конфигурации билдера для production-точки входа (Program.cs): Serilog. Тесты хост поднимают БЕЗ этого хука — логирование файлов/консоли тестам не нужно.
/// Собранный хост; запуск — StartAsync/RunAsync у вызывающего.
public static WebApplication Create(
int grpcPort,
string[]? args = null,
Action? configureServices = null,
Action? configureBuilder = null)
{
WebApplicationBuilder builder = WebApplication.CreateBuilder(args ?? []);
// Общая серверная обвязка (Deal.Grpc.Hosting, C31): mTLS env DEAL_MTLS_* — загрузка
// сертификатов сразу с fail-fast (compose-prod монтирует deploy/certs, scripts/mtls-certs.sh);
// Один экземпляр mtlsCertificates используют и Kestrel ниже, и исходящий канал в ядро
// (CoreIngressClient).
MtlsCertificates? mtlsCertificates = GrpcServer.LoadMtlsCertificates(builder);
GrpcServer.ConfigureKestrelHttp2Endpoint(builder, grpcPort, mtlsCertificates);
builder.Services.AddDealGrpcServer();
builder.Services.AddReadyHealthCheck("хост telegram-service готов");
// файлов data/sessions/.session (AES-GCM, ключ из env), пул 1 аккаунт/тенант и
// фоновый цикл auto_resume/heartbeat (30 с). DEAL_TELEGRAM_SESSION_KEY обязателен —
// иначе хост не стартует (сессии не могут храниться в открытом виде).
TgOptions sessionOptions = TgOptions.FromConfiguration(builder.Configuration, builder.Environment);
builder.Services.AddSingleton(sessionOptions);
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddHostedService();
CoreIngressOptions ingressOptions = CoreIngressOptions.FromConfiguration(builder.Configuration);
builder.Services.AddSingleton(ingressOptions);
builder.Services.AddSingleton(provider => new CoreIngressClient(
ingressOptions,
provider.GetRequiredService>(),
mtlsCertificates));
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddSingleton();
builder.Services.AddHostedService();
builder.Services.AddHostedService();
configureServices?.Invoke(builder.Services);
configureBuilder?.Invoke(builder);
WebApplication app = builder.Build();
app.MapGrpcService();
app.MapGrpcHealthChecksService();
return app;
}
}