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<BotSimulator> _logger;
        private readonly Random _random;
        private readonly Faker _faker;
        private List<Category> _categories = new();
        private List<Product> _products = new();

        public BotSimulator(ILittleShopClient client, ILogger<BotSimulator> logger)
        {
            _client = client;
            _logger = logger;
            _random = new Random();
            _faker = new Faker();
        }

        public async Task<SimulationResult> 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<bool> 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<Order?> 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<CryptoPayment?> 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<string> 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<CartItem> 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; }
    }
}