using System; using System.Collections.Concurrent; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using LittleShop.Data; namespace LittleShop.Services; public class TelegramBotManagerService : BackgroundService, ITelegramBotManagerService { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; private readonly ConcurrentDictionary _activeBots = new(); public TelegramBotManagerService(IServiceProvider serviceProvider, ILogger logger) { _serviceProvider = serviceProvider; _logger = logger; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("🤖 Telegram Bot Manager Service starting..."); try { // Load all active bots from database await LoadActiveBotsAsync(); // Keep service running while (!stoppingToken.IsCancellationRequested) { // Periodic health checks and cleanup await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken); await PerformHealthChecksAsync(); } } catch (OperationCanceledException) { _logger.LogInformation("Telegram Bot Manager Service is stopping."); } catch (Exception ex) { _logger.LogError(ex, "Error in Telegram Bot Manager Service"); } } public async Task StartAsync(CancellationToken cancellationToken) { _logger.LogInformation("Telegram Bot Manager Service started"); await base.StartAsync(cancellationToken); } public async Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("Stopping all Telegram bots..."); foreach (var bot in _activeBots.Values) { try { await bot.StopAsync(); } catch (Exception ex) { _logger.LogError(ex, "Error stopping bot {BotId}", bot.BotId); } } _activeBots.Clear(); await base.StopAsync(cancellationToken); } public async Task AddBotAsync(Guid botId, string botToken) { try { _logger.LogInformation("Adding bot {BotId} to Telegram manager", botId); // Validate token first using var httpClient = new HttpClient(); var response = await httpClient.GetAsync($"https://api.telegram.org/bot{botToken}/getMe"); if (!response.IsSuccessStatusCode) { _logger.LogWarning("Invalid bot token for bot {BotId}", botId); return false; } // Create bot instance (placeholder for now - will implement Telegram.Bot later) var botInstance = new BotInstance { BotId = botId, BotToken = botToken, IsRunning = false }; _activeBots.TryAdd(botId, botInstance); _logger.LogInformation("✅ Bot {BotId} added successfully", botId); return true; } catch (Exception ex) { _logger.LogError(ex, "Failed to add bot {BotId}", botId); return false; } } public async Task RemoveBotAsync(Guid botId) { if (_activeBots.TryRemove(botId, out var botInstance)) { await botInstance.StopAsync(); _logger.LogInformation("Bot {BotId} removed from Telegram manager", botId); return true; } return false; } public async Task UpdateBotSettingsAsync(Guid botId) { if (_activeBots.TryGetValue(botId, out var botInstance)) { // Reload settings from database _logger.LogInformation("Updating settings for bot {BotId}", botId); return true; } return false; } public Task GetActiveBotCount() { return Task.FromResult(_activeBots.Count(x => x.Value.IsRunning)); } private async Task LoadActiveBotsAsync() { try { using var scope = _serviceProvider.CreateScope(); var botService = scope.ServiceProvider.GetRequiredService(); var activeBots = await botService.GetActiveBots(); _logger.LogInformation("Loading {Count} active bots", activeBots.Count()); foreach (var bot in activeBots) { // Look for telegram token in settings if (bot.Settings.TryGetValue("telegram", out var telegramSettings) && telegramSettings is System.Text.Json.JsonElement telegramElement && telegramElement.TryGetProperty("botToken", out var tokenElement)) { var token = tokenElement.GetString(); if (!string.IsNullOrEmpty(token) && token != "YOUR_BOT_TOKEN_HERE") { await AddBotAsync(bot.Id, token); } } } } catch (Microsoft.Data.Sqlite.SqliteException ex) when (ex.Message.Contains("no such table")) { _logger.LogWarning("Bot tables don't exist yet. Skipping bot loading until database is fully initialized."); } catch (Exception ex) { _logger.LogError(ex, "Error loading active bots"); } } private async Task PerformHealthChecksAsync() { foreach (var kvp in _activeBots) { try { // Placeholder for health check logic // In real implementation, would ping Telegram API _logger.LogDebug("Health check for bot {BotId}", kvp.Key); } catch (Exception ex) { _logger.LogWarning(ex, "Health check failed for bot {BotId}", kvp.Key); } } } } public class BotInstance { public Guid BotId { get; set; } public string BotToken { get; set; } = string.Empty; public bool IsRunning { get; set; } public DateTime StartedAt { get; set; } public Task StopAsync() { IsRunning = false; return Task.CompletedTask; } }