using Tiku.Application; using Tiku.Application.Tenancy; using Tiku.Application.PlatformBilling; using Tiku.Application.Security; using Tiku.Infrastructure; using Tiku.Worker; using Tiku.Infrastructure.Messaging; using Tiku.Infrastructure.Security; var builder = Host.CreateApplicationBuilder(args); var connectionString = builder.Configuration.GetConnectionString("Database") ?? builder.Configuration["DATABASE_URL"] ?? throw new InvalidOperationException( "Database connection is required. Configure ConnectionStrings:Database or DATABASE_URL."); builder.Services.AddApplication(); builder.Services.AddInfrastructure(connectionString); var redisConnectionString = builder.Configuration.GetConnectionString("Redis") ?? builder.Configuration["REDIS_URL"]; builder.Services.AddOptions() .Configure(options => options.ConnectionString = redisConnectionString ?? string.Empty) .Validate( options => !builder.Environment.IsProduction() || !string.IsNullOrWhiteSpace(options.ConnectionString), "Redis is required in Production.") .ValidateOnStart(); if (!string.IsNullOrWhiteSpace(redisConnectionString)) { builder.Services.AddRedisSecurity(redisConnectionString, builder.Environment.EnvironmentName); } else if (builder.Environment.IsProduction()) { throw new InvalidOperationException( "Redis is required in Production. Configure ConnectionStrings:Redis or REDIS_URL."); } var messaging = builder.Configuration.GetSection("RabbitMq").Get() ?? new MessagingOptions(); builder.Services.AddOptions() .Bind(builder.Configuration.GetSection("RabbitMq")) .Validate( options => !builder.Environment.IsProduction() || (options.IsConfigured && !string.IsNullOrWhiteSpace(options.Username) && !string.IsNullOrWhiteSpace(options.Password)), "Production RabbitMQ requires a valid Host, Username and Password.") .Validate( options => options.OutboxBacklogAlertCount > 0 && options.OutboxOldestMessageAlertSeconds > 0, "RabbitMQ outbox alert thresholds must be positive.") .ValidateOnStart(); if (messaging.IsConfigured) { messaging.ConfigureConsumers = true; builder.Services.AddReliableMessaging(messaging); } else if (builder.Environment.IsProduction()) { throw new InvalidOperationException("RabbitMQ is required in Production. Configure RabbitMq:Host."); } builder.Services.AddOptions() .Bind(builder.Configuration.GetSection("TenantDomains")); builder.Services.AddOptions() .Bind(builder.Configuration.GetSection("SaasSubscriptions")); builder.Services.AddOptions() .Bind(builder.Configuration.GetSection("FeatureUsageReconciliation")); builder.Services.AddHostedService(); var host = builder.Build(); host.Run();