littleshop/LittleShop/Services/TeleBotMessagingService.cs

189 lines
7.5 KiB
C#

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using LittleShop.Data;
using LittleShop.DTOs;
using LittleShop.Enums;
using LittleShop.Models;
namespace LittleShop.Services;
public class TeleBotMessagingService : ITeleBotMessagingService
{
private readonly LittleShopContext _context;
private readonly ICustomerMessageService _customerMessageService;
private readonly ILogger<TeleBotMessagingService> _logger;
public TeleBotMessagingService(
LittleShopContext context,
ICustomerMessageService customerMessageService,
ILogger<TeleBotMessagingService> logger)
{
_context = context;
_customerMessageService = customerMessageService;
_logger = logger;
}
public async Task<bool> 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<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.OrderUpdate, "Payment Confirmed", message);
}
public async Task<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.OrderUpdate, "Order Accepted", message);
}
public async Task<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.OrderUpdate, "Order Packing", message);
}
public async Task<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.ShippingInfo, "Order Dispatched", message);
}
public async Task<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.OrderUpdate, "Order Delivered", message);
}
public async Task<bool> 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 QueueMessageAsync(order.Customer.Id, orderId, MessageType.OrderUpdate, "Order On Hold", message);
}
public async Task<bool> 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 QueueMessageAsync(customerId, null, MessageType.CustomerService, "Test Message", testMessage);
}
public async Task<bool> IsAvailableAsync()
{
// TeleBot is always "available" since it polls for messages from the database queue
// No need to check HTTP endpoint availability
return true;
}
private async Task<Order?> GetOrderWithCustomerAsync(Guid orderId)
{
return await _context.Orders
.Include(o => o.Customer)
.FirstOrDefaultAsync(o => o.Id == orderId);
}
private async Task<bool> QueueMessageAsync(Guid customerId, Guid? orderId, MessageType type, string subject, string content)
{
try
{
var createMessageDto = new CreateCustomerMessageDto
{
CustomerId = customerId,
OrderId = orderId,
Type = type,
Subject = subject,
Content = content,
Priority = 5, // Normal priority
IsUrgent = false
};
var result = await _customerMessageService.CreateMessageAsync(createMessageDto);
if (result != null)
{
_logger.LogInformation("Queued message {MessageId} for customer {CustomerId} - {Subject}",
result.Id, customerId, subject);
return true;
}
else
{
_logger.LogWarning("Failed to queue message for customer {CustomerId} - {Subject}",
customerId, subject);
return false;
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error queuing message for customer {CustomerId} - {Subject}",
customerId, subject);
return false;
}
}
}