using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Telegram.Bot;
using Telegram.Bot.Types;
using TeleBot.Services;
using TeleBot.UI;

namespace TeleBot.Handlers
{
    public interface ICommandHandler
    {
        Task HandleCommandAsync(ITelegramBotClient bot, Message message, string command, string? args);
    }
    
    public class CommandHandler : ICommandHandler
    {
        private readonly ISessionManager _sessionManager;
        private readonly ILittleShopService _shopService;
        private readonly IPrivacyService _privacyService;
        private readonly IProductCarouselService _carouselService;
        private readonly ILogger<CommandHandler> _logger;
        
        public CommandHandler(
            ISessionManager sessionManager,
            ILittleShopService shopService,
            IPrivacyService privacyService,
            IProductCarouselService carouselService,
            ILogger<CommandHandler> logger)
        {
            _sessionManager = sessionManager;
            _shopService = shopService;
            _privacyService = privacyService;
            _carouselService = carouselService;
            _logger = logger;
        }
        
        public async Task HandleCommandAsync(ITelegramBotClient bot, Message message, string command, string? args)
        {
            var session = await _sessionManager.GetOrCreateSessionAsync(message.From!.Id);
            
            try
            {
                switch (command.ToLower())
                {
                    case "/start":
                        await HandleStartCommand(bot, message, session);
                        break;
                        
                    case "/browse":
                        await HandleBrowseCommand(bot, message, session);
                        break;
                        
                    case "/products":
                        await HandleProductsCommand(bot, message, session, args);
                        break;
                        
                    case "/cart":
                        await HandleCartCommand(bot, message, session);
                        break;
                        
                    case "/orders":
                        await HandleOrdersCommand(bot, message, session);
                        break;
                        
                    case "/privacy":
                        await HandlePrivacyCommand(bot, message, session);
                        break;
                        
                    case "/help":
                        await HandleHelpCommand(bot, message);
                        break;
                        
                    case "/delete":
                        await HandleDeleteCommand(bot, message, session);
                        break;
                        
                    case "/ephemeral":
                        await HandleEphemeralCommand(bot, message, session);
                        break;
                        
                    case "/pgpkey":
                        await HandlePGPKeyCommand(bot, message, session, args);
                        break;
                        
                    case "/tor":
                        await HandleTorCommand(bot, message);
                        break;
                        
                    case "/clear":
                        await HandleClearCommand(bot, message, session);
                        break;
                        
                    case "/support":
                        await HandleSupportCommand(bot, message, session);
                        break;
                        
                    case "/cancel":
                        await HandleCancelCommand(bot, message, session);
                        break;
                        
                    case "/review":
                        await HandleReviewCommand(bot, message, session);
                        break;
                        
                    default:
                        await bot.SendTextMessageAsync(
                            message.Chat.Id,
                            "Unknown command. Use /help to see available commands."
                        );
                        break;
                }
                
                await _sessionManager.UpdateSessionAsync(session);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling command {Command}", command);
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "An error occurred processing your request. Please try again."
                );
            }
        }
        
        private async Task HandleStartCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            var isReturning = session.CreatedAt < DateTime.UtcNow.AddSeconds(-5);
            var text = MessageFormatter.FormatWelcome(isReturning);
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                text,
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.MainMenu()
            );
            
            session.State = Models.SessionState.MainMenu;
        }
        
        private async Task HandleBrowseCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            var categories = await _shopService.GetCategoriesAsync();
            var text = MessageFormatter.FormatCategories(categories);
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                text,
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.CategoryMenu(categories)
            );
            
            session.State = Models.SessionState.BrowsingCategories;
        }
        
        private async Task HandleProductsCommand(ITelegramBotClient bot, Message message, Models.UserSession session, string? args)
        {
            try
            {
                // Parse category ID from args if provided
                Guid? categoryId = null;
                if (!string.IsNullOrEmpty(args) && Guid.TryParse(args, out var parsedCategoryId))
                {
                    categoryId = parsedCategoryId;
                }

                // Get products
                var products = await _shopService.GetProductsAsync(categoryId, 1);
                
                if (!products.Items.Any())
                {
                    await bot.SendTextMessageAsync(
                        message.Chat.Id,
                        "No products available in this category.",
                        replyMarkup: MenuBuilder.CategoryNavigationMenu(categoryId)
                    );
                    return;
                }

                // Get category name if categoryId is provided
                string? categoryName = null;
                if (categoryId.HasValue)
                {
                    var categories = await _shopService.GetCategoriesAsync();
                    var category = categories.FirstOrDefault(c => c.Id == categoryId.Value);
                    categoryName = category?.Name;
                }

                // Send products as carousel with images
                await _carouselService.SendProductCarouselAsync(bot, message.Chat.Id, products, categoryName, 1);
                
                session.State = Models.SessionState.BrowsingProducts;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling products command");
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "An error occurred while loading products. Please try again.",
                    replyMarkup: MenuBuilder.MainMenu()
                );
            }
        }
        
        private async Task HandleCartCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            var text = MessageFormatter.FormatCart(session.Cart);
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                text,
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.CartMenu(session.Cart)
            );
            
            session.State = Models.SessionState.ViewingCart;
        }
        
        private async Task HandleOrdersCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            // Use new customer-based order lookup
            var orders = await _shopService.GetCustomerOrdersAsync(
                message.From!.Id,
                message.From.Username ?? "",
                $"{message.From.FirstName} {message.From.LastName}".Trim(),
                message.From.FirstName ?? "",
                message.From.LastName ?? ""
            );
            
            if (!orders.Any())
            {
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "You have no orders yet.\n\nStart shopping to place your first order!",
                    replyMarkup: MenuBuilder.MainMenu()
                );
            }
            else
            {
                var text = $"📦 *Your Orders*\n\nFound {orders.Count} order(s):";
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    text,
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                    replyMarkup: MenuBuilder.OrderListMenu(orders)
                );
            }
            
            session.State = Models.SessionState.ViewingOrders;
        }
        
        private async Task HandlePrivacyCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            var text = MessageFormatter.FormatPrivacyPolicy();
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                text,
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.PrivacyMenu(session.Privacy)
            );
            
            session.State = Models.SessionState.PrivacySettings;
        }
        
        private async Task HandleHelpCommand(ITelegramBotClient bot, Message message)
        {
            var text = MessageFormatter.FormatHelp();
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                text,
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.MainMenu()
            );
        }
        
        private async Task HandleDeleteCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            await _sessionManager.DeleteUserDataAsync(message.From!.Id);
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                "✅ *All your data has been deleted*\n\n" +
                "Your shopping cart, order history, and all personal data have been permanently removed.\n\n" +
                "You can start fresh anytime with /start",
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
            );
        }
        
        private async Task HandleEphemeralCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            session.IsEphemeral = !session.IsEphemeral;
            session.Privacy.UseEphemeralMode = session.IsEphemeral;
            
            var status = session.IsEphemeral ? "enabled" : "disabled";
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                $"🔒 Ephemeral mode {status}\n\n" +
                (session.IsEphemeral 
                    ? "Your session data will not be persisted and will be deleted after 30 minutes of inactivity."
                    : "Your session data will be saved for convenience (still encrypted)."),
                replyMarkup: MenuBuilder.MainMenu()
            );
        }
        
        private async Task HandlePGPKeyCommand(ITelegramBotClient bot, Message message, Models.UserSession session, string? pgpKey)
        {
            if (string.IsNullOrWhiteSpace(pgpKey))
            {
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "🔐 *PGP Encryption Setup*\n\n" +
                    "To enable PGP encryption for your shipping information, send your public key:\n\n" +
                    "`/pgpkey YOUR_PUBLIC_KEY_HERE`\n\n" +
                    "Your shipping details will be encrypted before being sent to the server.",
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown
                );
            }
            else
            {
                session.Privacy.PGPPublicKey = pgpKey;
                session.Privacy.RequirePGP = true;
                
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "✅ *PGP key saved successfully*\n\n" +
                    "Your shipping information will now be encrypted with your PGP key before processing.",
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                    replyMarkup: MenuBuilder.MainMenu()
                );
            }
        }
        
        private async Task HandleTorCommand(ITelegramBotClient bot, Message message)
        {
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                "🧅 *Tor Access Information*\n\n" +
                "For maximum privacy, you can access this bot through Tor:\n\n" +
                "1. Install Tor Browser or configure Tor proxy\n" +
                "2. Configure Telegram to use SOCKS5 proxy:\n" +
                "   • Server: 127.0.0.1\n" +
                "   • Port: 9050\n" +
                "   • Type: SOCKS5\n\n" +
                "This routes all your Telegram traffic through the Tor network.\n\n" +
                "_Note: The shop API can also be accessed via Tor if configured._",
                parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                replyMarkup: MenuBuilder.MainMenu()
            );
        }
        
        private async Task HandleClearCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            session.Cart.Clear();
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                "🗑️ Shopping cart cleared successfully!",
                replyMarkup: MenuBuilder.MainMenu()
            );
        }
        
        private async Task HandleSupportCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            session.State = Models.SessionState.CustomerSupport;
            
            // Show conversation history first
            await ShowCustomerConversation(bot, message, session);
        }
        
        private async Task HandleCancelCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            session.State = Models.SessionState.MainMenu;
            
            await bot.SendTextMessageAsync(
                message.Chat.Id,
                "Operation cancelled. How can I help you today?",
                replyMarkup: MenuBuilder.MainMenu()
            );
        }
        
        private async Task ShowCustomerConversation(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            try
            {
                // Get conversation history for this customer
                var messages = await _shopService.GetCustomerConversationAsync(
                    message.From!.Id,
                    message.From.Username ?? "",
                    $"{message.From.FirstName} {message.From.LastName}".Trim(),
                    message.From.FirstName ?? "",
                    message.From.LastName ?? ""
                );

                var conversationText = "💬 *Your Messages*\n\n";
                
                if (messages?.Any() == true)
                {
                    conversationText += "Here's your conversation history:\n\n";
                    
                    foreach (var msg in messages.OrderBy(m => m.CreatedAt).Take(10)) // Show last 10 messages
                    {
                        var isFromBusiness = msg.Direction == 0; // AdminToCustomer
                        var sender = isFromBusiness ? "🏪 Shop" : "👤 You";
                        var time = msg.CreatedAt.ToString("MMM dd, HH:mm");
                        
                        conversationText += $"*{sender}* _{time}_\n{msg.Content}\n\n";
                    }
                }
                else
                {
                    conversationText += "No messages yet. Start a conversation by typing below!\n\n";
                }
                
                conversationText += "_Type your message or use the Exit Chat button to return to shopping._";

                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    conversationText,
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                    replyMarkup: MenuBuilder.ConversationMenu()
                );
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error showing customer conversation");
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "🎧 *Customer Support*\n\nReady to chat with our support team!\n\n_Type your message below._",
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                    replyMarkup: MenuBuilder.ConversationMenu()
                );
            }
        }

        private async Task HandleReviewCommand(ITelegramBotClient bot, Message message, Models.UserSession session)
        {
            try
            {
                // Get customer's shipped orders
                var orders = await _shopService.GetCustomerOrdersAsync(
                    message.From!.Id,
                    message.From.Username ?? "",
                    message.From.FirstName + " " + message.From.LastName,
                    message.From.FirstName ?? "",
                    message.From.LastName ?? ""
                );

                var shippedOrders = orders.Where(o => o.Status == 3).ToList(); // Status 3 = Shipped

                if (!shippedOrders.Any())
                {
                    await bot.SendTextMessageAsync(
                        message.Chat.Id,
                        "⭐ *Product Reviews*\n\n" +
                        "You can only review products from orders that have been shipped.\n\n" +
                        "Once you receive your order, come back here to share your experience!",
                        parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                        replyMarkup: MenuBuilder.MainMenu()
                    );
                    return;
                }

                // Show reviewable products
                var reviewableProducts = new List<dynamic>();
                foreach (var order in shippedOrders)
                {
                    foreach (var item in order.Items)
                    {
                        reviewableProducts.Add(new 
                        { 
                            ProductId = item.ProductId, 
                            ProductName = item.ProductName, 
                            OrderId = order.Id 
                        });
                    }
                }

                if (!reviewableProducts.Any())
                {
                    await bot.SendTextMessageAsync(
                        message.Chat.Id,
                        "⭐ *Product Reviews*\n\n" +
                        "No reviewable products found in your shipped orders.",
                        parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                        replyMarkup: MenuBuilder.MainMenu()
                    );
                    return;
                }

                // Build review selection menu
                var reviewText = "⭐ *Leave a Product Review*\n\n" +
                                "Select a product from your shipped orders to review:\n\n";

                var keyboard = new List<List<Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton>>();

                foreach (var product in reviewableProducts.Take(10)) // Limit to 10 for UI
                {
                    reviewText += $"• {product.ProductName}\n";
                    
                    keyboard.Add(new List<Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton>
                    {
                        Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton.WithCallbackData(
                            $"Review {product.ProductName}", 
                            $"review_{product.ProductId}_{product.OrderId}")
                    });
                }

                keyboard.Add(new List<Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton>
                {
                    Telegram.Bot.Types.ReplyMarkups.InlineKeyboardButton.WithCallbackData("« Back to Menu", "menu_main")
                });

                var replyMarkup = new Telegram.Bot.Types.ReplyMarkups.InlineKeyboardMarkup(keyboard);

                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    reviewText,
                    parseMode: Telegram.Bot.Types.Enums.ParseMode.Markdown,
                    replyMarkup: replyMarkup
                );
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error handling review command");
                await bot.SendTextMessageAsync(
                    message.Chat.Id,
                    "❌ Sorry, there was an error accessing your reviews. Please try again later.",
                    replyMarkup: MenuBuilder.MainMenu()
                );
            }
        }
    }
}