using System.Text; using System.Text.Json; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using LittleShop.Data; using LittleShop.Enums; using LittleShop.Models; namespace LittleShop.Services; public class TeleBotMessagingService : ITeleBotMessagingService { private readonly LittleShopContext _context; private readonly IConfiguration _configuration; private readonly ILogger _logger; private readonly HttpClient _httpClient; private readonly string? _teleBotApiUrl; private readonly string? _teleBotApiKey; public TeleBotMessagingService( LittleShopContext context, IConfiguration configuration, ILogger logger, HttpClient httpClient) { _context = context; _configuration = configuration; _logger = logger; _httpClient = httpClient; _teleBotApiUrl = _configuration["TeleBot:ApiUrl"]; _teleBotApiKey = _configuration["TeleBot:ApiKey"]; } public async Task SendOrderStatusUpdateAsync(Guid orderId, OrderStatus newStatus) { return newStatus switch { OrderStatus.PaymentReceived => await SendPaymentConfirmedAsync(orderId), OrderStatus.Accepted => await SendOrderAcceptedAsync(orderId), OrderStatus.Packing => await SendOrderPackingAsync(orderId), OrderStatus.Dispatched => await SendOrderDispatchedAsync(orderId), OrderStatus.Delivered => await SendOrderDeliveredAsync(orderId), OrderStatus.OnHold => await SendOrderOnHoldAsync(orderId), _ => false }; } public async Task SendPaymentConfirmedAsync(Guid orderId) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var message = $"πŸ’° *Payment Confirmed!*\n\n" + $"Your order #{orderId.ToString()[..8]} has been paid successfully. " + $"We'll start processing it shortly.\n\n" + $"πŸ“¦ Total: Β£{order.TotalAmount:F2}\n" + $"⏱️ Expected processing: Within 24 hours"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendOrderAcceptedAsync(Guid orderId) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var message = $"βœ… *Order Accepted!*\n\n" + $"Great news! Your order #{orderId.ToString()[..8]} has been accepted " + $"and is being prepared for packing.\n\n" + $"⏱️ Expected packing: Within 24 hours\n" + $"🚚 We'll notify you when it's dispatched"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendOrderPackingAsync(Guid orderId) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var message = $"πŸ“¦ *Being Packed!*\n\n" + $"Your order #{orderId.ToString()[..8]} is currently being packed with care.\n\n" + $"🚚 We'll send tracking details once dispatched.\n" + $"⏱️ Expected dispatch: Later today"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendOrderDispatchedAsync(Guid orderId, string? trackingNumber = null) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var trackingInfo = !string.IsNullOrEmpty(trackingNumber) ? $"πŸ“ Tracking: `{trackingNumber}`\n" : ""; var message = $"🚚 *Order Dispatched!*\n\n" + $"Your order #{orderId.ToString()[..8]} is on its way!\n\n" + $"{trackingInfo}" + $"⏱️ Estimated delivery: 1-3 working days\n" + $"πŸ“ Track your package for real-time updates"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendOrderDeliveredAsync(Guid orderId) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var message = $"πŸŽ‰ *Order Delivered!*\n\n" + $"Your order #{orderId.ToString()[..8]} has been delivered successfully!\n\n" + $"⭐ Please consider leaving a review using the /review command.\n" + $"πŸ›’ Thank you for choosing us for your order!"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendOrderOnHoldAsync(Guid orderId, string? reason = null) { var order = await GetOrderWithCustomerAsync(orderId); if (order?.Customer == null) return false; var reasonText = !string.IsNullOrEmpty(reason) ? $"\n\nπŸ“ Reason: {reason}" : ""; var message = $"⏸️ *Order On Hold*\n\n" + $"Your order #{orderId.ToString()[..8]} has been temporarily put on hold.{reasonText}\n\n" + $"πŸ’¬ Please contact support if you have any questions.\n" + $"⏱️ We'll resolve this as quickly as possible"; return await SendTeleBotMessageAsync(order.Customer.TelegramUserId, message); } public async Task SendTestMessageAsync(Guid customerId, string message) { var customer = await _context.Customers.FindAsync(customerId); if (customer == null) return false; var testMessage = $"πŸ§ͺ *Test Message*\n\n{message}"; return await SendTeleBotMessageAsync(customer.TelegramUserId, testMessage); } public async Task IsAvailableAsync() { if (string.IsNullOrEmpty(_teleBotApiUrl) || string.IsNullOrEmpty(_teleBotApiKey)) { return false; } try { var response = await _httpClient.GetAsync($"{_teleBotApiUrl}/health"); return response.IsSuccessStatusCode; } catch { return false; } } private async Task GetOrderWithCustomerAsync(Guid orderId) { return await _context.Orders .Include(o => o.Customer) .FirstOrDefaultAsync(o => o.Id == orderId); } private async Task SendTeleBotMessageAsync(long telegramUserId, string message) { if (!await IsAvailableAsync()) { _logger.LogWarning("TeleBot API not available, skipping message to user {UserId}", telegramUserId); return false; } try { var requestData = new { userId = telegramUserId, message = message, parseMode = "Markdown" }; var json = JsonSerializer.Serialize(requestData); var content = new StringContent(json, Encoding.UTF8, "application/json"); // Add API key header _httpClient.DefaultRequestHeaders.Clear(); _httpClient.DefaultRequestHeaders.Add("X-API-Key", _teleBotApiKey); var response = await _httpClient.PostAsync($"{_teleBotApiUrl}/api/messages/send", content); if (response.IsSuccessStatusCode) { _logger.LogInformation("Successfully sent TeleBot message to user {UserId}", telegramUserId); return true; } else { var responseContent = await response.Content.ReadAsStringAsync(); _logger.LogWarning("Failed to send TeleBot message to user {UserId}: {StatusCode} - {Response}", telegramUserId, response.StatusCode, responseContent); return false; } } catch (Exception ex) { _logger.LogError(ex, "Error sending TeleBot message to user {UserId}", telegramUserId); return false; } } }