using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Bogus; using LittleShop.Client; using LittleShop.Client.Models; using Microsoft.Extensions.Logging; namespace TeleBotClient { public class BotSimulator { private readonly ILittleShopClient _client; private readonly ILogger _logger; private readonly Random _random; private readonly Faker _faker; private List _categories = new(); private List _products = new(); public BotSimulator(ILittleShopClient client, ILogger logger) { _client = client; _logger = logger; _random = new Random(); _faker = new Faker(); } public async Task SimulateUserSession() { var result = new SimulationResult { SessionId = Guid.NewGuid().ToString(), StartTime = DateTime.UtcNow }; try { _logger.LogInformation("🤖 Starting bot simulation session {SessionId}", result.SessionId); // Step 1: Authenticate _logger.LogInformation("📝 Authenticating with API..."); if (!await Authenticate()) { result.Success = false; result.ErrorMessage = "Authentication failed"; return result; } result.Steps.Add("✅ Authentication successful"); // Step 2: Browse categories _logger.LogInformation("📁 Browsing categories..."); await BrowseCategories(); result.Steps.Add($"✅ Found {_categories.Count} categories"); // Step 3: Select random category and browse products if (_categories.Any()) { var selectedCategory = _categories[_random.Next(_categories.Count)]; _logger.LogInformation("🔍 Selected category: {Category}", selectedCategory.Name); result.Steps.Add($"✅ Selected category: {selectedCategory.Name}"); await BrowseProducts(selectedCategory.Id); result.Steps.Add($"✅ Found {_products.Count} products in category"); } else { // Browse all products if no categories await BrowseProducts(null); result.Steps.Add($"✅ Found {_products.Count} total products"); } // Step 4: Build shopping cart _logger.LogInformation("🛒 Building shopping cart..."); var cart = BuildRandomCart(); result.Cart = cart; result.Steps.Add($"✅ Added {cart.Items.Count} items to cart (Total: ${cart.TotalAmount:F2})"); // Step 5: Generate shipping information _logger.LogInformation("📦 Generating shipping information..."); var shippingInfo = GenerateShippingInfo(); result.ShippingInfo = shippingInfo; result.Steps.Add($"✅ Generated shipping to {shippingInfo.City}, {shippingInfo.Country}"); // Step 6: Create order _logger.LogInformation("📝 Creating order..."); var order = await CreateOrder(cart, shippingInfo); if (order != null) { result.OrderId = order.Id; result.OrderTotal = order.TotalAmount; result.Steps.Add($"✅ Order created: {order.Id}"); // Step 7: Select payment method var currency = SelectRandomCurrency(); _logger.LogInformation("💰 Selected payment method: {Currency}", currency); result.PaymentCurrency = currency; result.Steps.Add($"✅ Selected payment: {currency}"); // Step 8: Create payment var payment = await CreatePayment(order.Id, currency); if (payment != null) { result.PaymentId = payment.Id; result.PaymentAddress = payment.WalletAddress; result.PaymentAmount = payment.RequiredAmount; result.Steps.Add($"✅ Payment created: {payment.RequiredAmount} {currency}"); } } result.Success = true; result.EndTime = DateTime.UtcNow; result.Duration = result.EndTime - result.StartTime; _logger.LogInformation("✅ Simulation completed successfully in {Duration}", result.Duration); } catch (Exception ex) { _logger.LogError(ex, "❌ Simulation failed"); result.Success = false; result.ErrorMessage = ex.Message; result.EndTime = DateTime.UtcNow; result.Duration = result.EndTime - result.StartTime; } return result; } private async Task Authenticate() { var result = await _client.Authentication.LoginAsync("admin", "admin"); if (result.IsSuccess && result.Data != null && !string.IsNullOrEmpty(result.Data.Token)) { _client.Authentication.SetToken(result.Data.Token); return true; } return false; } private async Task BrowseCategories() { var result = await _client.Catalog.GetCategoriesAsync(); if (result.IsSuccess && result.Data != null) { _categories = result.Data; } } private async Task BrowseProducts(Guid? categoryId) { var result = await _client.Catalog.GetProductsAsync( pageNumber: 1, pageSize: 50, categoryId: categoryId ); if (result.IsSuccess && result.Data != null) { _products = result.Data.Items; } } private ShoppingCart BuildRandomCart() { var cart = new ShoppingCart(); if (!_products.Any()) return cart; // Random number of items (1-5) var itemCount = _random.Next(1, Math.Min(6, _products.Count + 1)); var selectedProducts = _products.OrderBy(x => _random.Next()).Take(itemCount).ToList(); foreach (var product in selectedProducts) { var quantity = _random.Next(1, 4); // 1-3 items cart.AddItem(product.Id, product.Name, product.Price, quantity); _logger.LogDebug("Added {Quantity}x {Product} @ ${Price}", quantity, product.Name, product.Price); } return cart; } private ShippingInfo GenerateShippingInfo() { return new ShippingInfo { IdentityReference = $"SIM-{Guid.NewGuid().ToString().Substring(0, 8).ToUpper()}", Name = _faker.Name.FullName(), Address = _faker.Address.StreetAddress(), City = _faker.Address.City(), PostCode = _faker.Address.ZipCode(), Country = _faker.PickRandom(new[] { "United Kingdom", "Ireland", "France", "Germany", "Netherlands" }), Notes = _faker.Lorem.Sentence() }; } private async Task CreateOrder(ShoppingCart cart, ShippingInfo shipping) { var request = new CreateOrderRequest { IdentityReference = shipping.IdentityReference, ShippingName = shipping.Name, ShippingAddress = shipping.Address, ShippingCity = shipping.City, ShippingPostCode = shipping.PostCode, ShippingCountry = shipping.Country, Notes = shipping.Notes, Items = cart.Items.Select(i => new CreateOrderItem { ProductId = i.ProductId, Quantity = i.Quantity }).ToList() }; var result = await _client.Orders.CreateOrderAsync(request); return result.IsSuccess ? result.Data : null; } private string SelectRandomCurrency() { var currencies = new[] { "BTC", "XMR", "USDT", "LTC", "ETH", "ZEC", "DASH", "DOGE" }; // Weight towards BTC and XMR var weights = new[] { 30, 25, 15, 10, 10, 5, 3, 2 }; var totalWeight = weights.Sum(); var randomValue = _random.Next(totalWeight); var currentWeight = 0; for (int i = 0; i < currencies.Length; i++) { currentWeight += weights[i]; if (randomValue < currentWeight) return currencies[i]; } return "BTC"; } private async Task CreatePayment(Guid orderId, string currency) { var currencyInt = ConvertCurrencyToEnum(currency); var result = await _client.Orders.CreatePaymentAsync(orderId, currencyInt); return result.IsSuccess ? result.Data : null; } private static int ConvertCurrencyToEnum(string currency) { return currency.ToUpper() switch { "BTC" => 0, "XMR" => 1, "USDT" => 2, "LTC" => 3, "ETH" => 4, "ZEC" => 5, "DASH" => 6, "DOGE" => 7, _ => 0 // Default to BTC }; } } public class SimulationResult { public string SessionId { get; set; } = string.Empty; public bool Success { get; set; } public string? ErrorMessage { get; set; } public DateTime StartTime { get; set; } public DateTime EndTime { get; set; } public TimeSpan Duration { get; set; } public List Steps { get; set; } = new(); // Order details public Guid? OrderId { get; set; } public decimal OrderTotal { get; set; } public ShoppingCart? Cart { get; set; } public ShippingInfo? ShippingInfo { get; set; } // Payment details public Guid? PaymentId { get; set; } public string? PaymentCurrency { get; set; } public string? PaymentAddress { get; set; } public decimal PaymentAmount { get; set; } } public class ShoppingCart { public List Items { get; set; } = new(); public decimal TotalAmount => Items.Sum(i => i.TotalPrice); public void AddItem(Guid productId, string name, decimal price, int quantity) { Items.Add(new CartItem { ProductId = productId, ProductName = name, UnitPrice = price, Quantity = quantity, TotalPrice = price * quantity }); } } public class CartItem { public Guid ProductId { get; set; } public string ProductName { get; set; } = string.Empty; public decimal UnitPrice { get; set; } public int Quantity { get; set; } public decimal TotalPrice { get; set; } } public class ShippingInfo { public string IdentityReference { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Address { get; set; } = string.Empty; public string City { get; set; } = string.Empty; public string PostCode { get; set; } = string.Empty; public string Country { get; set; } = string.Empty; public string? Notes { get; set; } } }