using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LittleShop.Client;
using LittleShop.Client.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using TeleBot.Models;

namespace TeleBot.Services
{
    public interface ILittleShopService
    {
        Task<bool> AuthenticateAsync();
        Task<List<Category>> GetCategoriesAsync();
        Task<PagedResult<Product>> GetProductsAsync(Guid? categoryId = null, int page = 1);
        Task<Product?> GetProductAsync(Guid productId);
        Task<Order?> CreateOrderAsync(UserSession session, long telegramUserId = 0, string telegramUsername = "", string telegramDisplayName = "", string telegramFirstName = "", string telegramLastName = "");
        Task<List<Order>> GetOrdersAsync(string identityReference);
        Task<List<Order>> GetCustomerOrdersAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName);
        Task<Order?> GetOrderAsync(Guid orderId);
        Task<Order?> GetCustomerOrderAsync(Guid orderId, long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName);
        Task<CryptoPayment?> CreatePaymentAsync(Guid orderId, string currency);
        Task<List<CustomerMessage>?> GetPendingMessagesAsync();
        Task<bool> MarkMessageAsSentAsync(Guid messageId, string? platformMessageId = null);
        Task<bool> MarkMessageAsFailedAsync(Guid messageId, string reason);
        Task<bool> SendCustomerMessageAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName, string subject, string content);
        Task<List<CustomerMessage>?> GetCustomerConversationAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName);
    }
    
    public class LittleShopService : ILittleShopService
    {
        private readonly ILittleShopClient _client;
        private readonly IConfiguration _configuration;
        private readonly ILogger<LittleShopService> _logger;
        private readonly IPrivacyService _privacyService;
        private bool _isAuthenticated = false;
        
        public LittleShopService(
            ILittleShopClient client,
            IConfiguration configuration,
            ILogger<LittleShopService> logger,
            IPrivacyService privacyService)
        {
            _client = client;
            _configuration = configuration;
            _logger = logger;
            _privacyService = privacyService;
        }
        
        public async Task<bool> AuthenticateAsync()
        {
            if (_isAuthenticated)
                return true;
            
            try
            {
                var username = _configuration["LittleShop:Username"] ?? "bot-user";
                var password = _configuration["LittleShop:Password"] ?? "bot-password";
                
                var result = await _client.Authentication.LoginAsync(username, password);
                
                if (result.IsSuccess && result.Data != null && !string.IsNullOrEmpty(result.Data.Token))
                {
                    _client.Authentication.SetToken(result.Data.Token);
                    _isAuthenticated = true;
                    _logger.LogInformation("Successfully authenticated with LittleShop API");
                    return true;
                }
                
                _logger.LogWarning("Failed to authenticate with LittleShop API");
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error authenticating with LittleShop API");
                return false;
            }
        }
        
        public async Task<List<Category>> GetCategoriesAsync()
        {
            try
            {
                if (!await AuthenticateAsync())
                    return new List<Category>();
                
                var result = await _client.Catalog.GetCategoriesAsync();
                
                if (result.IsSuccess && result.Data != null)
                {
                    return result.Data.Where(c => c.IsActive).ToList();
                }
                
                return new List<Category>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching categories");
                return new List<Category>();
            }
        }
        
        public async Task<PagedResult<Product>> GetProductsAsync(Guid? categoryId = null, int page = 1)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return new PagedResult<Product> { Items = new List<Product>() };
                
                var result = await _client.Catalog.GetProductsAsync(
                    pageNumber: page,
                    pageSize: 10,
                    categoryId: categoryId
                );
                
                if (result.IsSuccess && result.Data != null)
                {
                    // Filter to active products only
                    result.Data.Items = result.Data.Items.Where(p => p.IsActive).ToList();
                    return result.Data;
                }
                
                return new PagedResult<Product> { Items = new List<Product>() };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching products");
                return new PagedResult<Product> { Items = new List<Product>() };
            }
        }
        
        public async Task<Product?> GetProductAsync(Guid productId)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;
                
                var result = await _client.Catalog.GetProductByIdAsync(productId);
                
                if (result.IsSuccess && result.Data != null && result.Data.IsActive)
                {
                    return result.Data;
                }
                
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching product {ProductId}", productId);
                return null;
            }
        }
        
        public async Task<Order?> CreateOrderAsync(UserSession session, long telegramUserId = 0, string telegramUsername = "", string telegramDisplayName = "", string telegramFirstName = "", string telegramLastName = "")
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;
                
                if (session.Cart.IsEmpty() || session.OrderFlow == null)
                    return null;
                
                // Create or get customer instead of using anonymous reference
                string? identityReference = null;
                CreateCustomerRequest? customerInfo = null;
                
                if (telegramUserId > 0)
                {
                    // Create customer info for order creation
                    customerInfo = new CreateCustomerRequest
                    {
                        TelegramUserId = telegramUserId,
                        TelegramUsername = telegramUsername,
                        TelegramDisplayName = string.IsNullOrEmpty(telegramDisplayName) ? $"{telegramFirstName} {telegramLastName}".Trim() : telegramDisplayName,
                        TelegramFirstName = telegramFirstName,
                        TelegramLastName = telegramLastName,
                        AllowOrderUpdates = true,
                        AllowMarketing = false
                    };
                    
                    _logger.LogInformation("Creating order for Telegram user {UserId} ({DisplayName})", 
                        telegramUserId, customerInfo.TelegramDisplayName);
                }
                else
                {
                    // Fallback to anonymous reference for legacy support
                    if (string.IsNullOrEmpty(session.OrderFlow.IdentityReference))
                    {
                        session.OrderFlow.IdentityReference = _privacyService.GenerateAnonymousReference();
                    }
                    identityReference = session.OrderFlow.IdentityReference;
                    
                    _logger.LogInformation("Creating anonymous order with identity {Identity}", identityReference);
                }
                
                // Encrypt shipping info if PGP is enabled
                string shippingData = $"{session.OrderFlow.ShippingName}\n" +
                                    $"{session.OrderFlow.ShippingAddress}\n" +
                                    $"{session.OrderFlow.ShippingCity}\n" +
                                    $"{session.OrderFlow.ShippingPostCode}\n" +
                                    $"{session.OrderFlow.ShippingCountry}";
                
                if (session.Privacy.RequirePGP && !string.IsNullOrEmpty(session.Privacy.PGPPublicKey))
                {
                    var encrypted = await _privacyService.EncryptWithPGP(shippingData, session.Privacy.PGPPublicKey);
                    if (encrypted != null)
                    {
                        // Store encrypted data in notes field
                        session.OrderFlow.Notes = $"PGP_ENCRYPTED_SHIPPING:\n{encrypted}";
                        session.OrderFlow.ShippingName = "PGP_ENCRYPTED";
                        session.OrderFlow.ShippingAddress = "PGP_ENCRYPTED";
                        session.OrderFlow.ShippingCity = "PGP_ENCRYPTED";
                        session.OrderFlow.ShippingPostCode = "PGP_ENCRYPTED";
                    }
                }
                
                var request = new CreateOrderRequest
                {
                    // Use customer info if available, otherwise fallback to identity reference
                    CustomerInfo = customerInfo,
                    IdentityReference = identityReference,
                    ShippingName = session.OrderFlow.ShippingName ?? "",
                    ShippingAddress = session.OrderFlow.ShippingAddress ?? "",
                    ShippingCity = session.OrderFlow.ShippingCity ?? "",
                    ShippingPostCode = session.OrderFlow.ShippingPostCode ?? "",
                    ShippingCountry = session.OrderFlow.ShippingCountry ?? "United Kingdom",
                    Notes = session.OrderFlow.Notes,
                    Items = session.Cart.Items.Select(i => new CreateOrderItem
                    {
                        ProductId = i.ProductId,
                        Quantity = i.Quantity
                    }).ToList()
                };
                
                var result = await _client.Orders.CreateOrderAsync(request);
                
                if (result.IsSuccess && result.Data != null)
                {
                    _logger.LogInformation("Order created successfully");
                    return result.Data;
                }
                
                _logger.LogWarning("Failed to create order: {Error}", result.ErrorMessage);
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating order");
                return null;
            }
        }
        
        public async Task<List<Order>> GetOrdersAsync(string identityReference)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return new List<Order>();
                
                var result = await _client.Orders.GetOrdersByIdentityAsync(identityReference);
                
                if (result.IsSuccess && result.Data != null)
                {
                    return result.Data;
                }
                
                return new List<Order>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching orders");
                return new List<Order>();
            }
        }
        
        public async Task<Order?> GetOrderAsync(Guid orderId)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;
                
                var result = await _client.Orders.GetOrderByIdAsync(orderId);
                
                if (result.IsSuccess && result.Data != null)
                {
                    return result.Data;
                }
                
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching order {OrderId}", orderId);
                return null;
            }
        }

        public async Task<Order?> GetCustomerOrderAsync(Guid orderId, long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;

                // Get or create the customer to get customer ID
                var customer = await _client.Customers.GetOrCreateCustomerAsync(new CreateCustomerRequest
                {
                    TelegramUserId = telegramUserId,
                    TelegramUsername = telegramUsername,
                    TelegramDisplayName = displayName,
                    TelegramFirstName = firstName,
                    TelegramLastName = lastName,
                    AllowOrderUpdates = true,
                    AllowMarketing = false
                });

                if (!customer.IsSuccess || customer.Data == null)
                {
                    return null;
                }

                // Get the specific order using customer validation
                var result = await _client.Orders.GetOrderByCustomerIdAsync(customer.Data.Id, orderId);
                
                if (result.IsSuccess && result.Data != null)
                {
                    return result.Data;
                }
                
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching customer order {OrderId}", orderId);
                return null;
            }
        }
        
        public async Task<CryptoPayment?> CreatePaymentAsync(Guid orderId, string currency)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;
                
                // Convert string currency to enum integer
                var currencyInt = ConvertCurrencyToEnum(currency);
                var result = await _client.Orders.CreatePaymentAsync(orderId, currencyInt);
                
                if (result.IsSuccess && result.Data != null)
                {
                    _logger.LogInformation("Payment created for order {OrderId} with currency {Currency}", 
                        orderId, currency);
                    return result.Data;
                }
                
                _logger.LogWarning("Failed to create payment: {Error}", result.ErrorMessage);
                return null;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating payment for order {OrderId}", orderId);
                return null;
            }
        }

        public async Task<List<CustomerMessage>?> GetPendingMessagesAsync()
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;

                // Use the client messages service
                var messages = await _client.Messages.GetPendingMessagesAsync("Telegram");
                
                // Convert to TeleBot CustomerMessage format
                return messages.Select(m => new CustomerMessage
                {
                    Id = m.Id,
                    CustomerId = m.CustomerId,
                    TelegramUserId = m.TelegramUserId,
                    Subject = m.Subject,
                    Content = m.Content,
                    Type = (MessageType)m.Type,
                    IsUrgent = m.IsUrgent,
                    OrderReference = m.OrderReference,
                    CreatedAt = m.CreatedAt
                }).ToList();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting pending messages");
                return null;
            }
        }

        public async Task<bool> MarkMessageAsSentAsync(Guid messageId, string? platformMessageId = null)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return false;

                return await _client.Messages.MarkMessageAsSentAsync(messageId, platformMessageId);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error marking message {MessageId} as sent", messageId);
                return false;
            }
        }

        public async Task<bool> MarkMessageAsFailedAsync(Guid messageId, string reason)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return false;

                return await _client.Messages.MarkMessageAsFailedAsync(messageId, reason);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error marking message {MessageId} as failed", messageId);
                return false;
            }
        }
        
        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 async Task<bool> SendCustomerMessageAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName, string subject, string content)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return false;

                // First, get or create the customer
                var customer = await _client.Customers.GetOrCreateCustomerAsync(new CreateCustomerRequest
                {
                    TelegramUserId = telegramUserId,
                    TelegramUsername = telegramUsername,
                    TelegramDisplayName = displayName,
                    TelegramFirstName = firstName,
                    TelegramLastName = lastName,
                    AllowOrderUpdates = true,
                    AllowMarketing = false
                });

                if (!customer.IsSuccess || customer.Data == null)
                {
                    _logger.LogError("Failed to get or create customer for support message");
                    return false;
                }

                // Create the customer message
                var messageData = new
                {
                    CustomerId = customer.Data.Id,
                    Type = 3, // CustomerService
                    Subject = subject,
                    Content = content,
                    Direction = 1, // CustomerToAdmin
                    Priority = 5,
                    IsUrgent = false
                };

                var response = await _client.Messages.CreateCustomerMessageAsync(messageData);
                return response;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error sending customer message");
                return false;
            }
        }

        public async Task<List<Order>> GetCustomerOrdersAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return new List<Order>();

                // Get or create the customer
                var customer = await _client.Customers.GetOrCreateCustomerAsync(new CreateCustomerRequest
                {
                    TelegramUserId = telegramUserId,
                    TelegramUsername = telegramUsername,
                    TelegramDisplayName = displayName,
                    TelegramFirstName = firstName,
                    TelegramLastName = lastName,
                    AllowOrderUpdates = true,
                    AllowMarketing = false
                });

                if (!customer.IsSuccess || customer.Data == null)
                {
                    return new List<Order>();
                }

                // Get customer orders using the new endpoint
                var ordersResult = await _client.Orders.GetOrdersByCustomerIdAsync(customer.Data.Id);
                
                if (ordersResult.IsSuccess && ordersResult.Data != null)
                {
                    return ordersResult.Data;
                }

                return new List<Order>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error fetching customer orders");
                return new List<Order>();
            }
        }

        public async Task<List<CustomerMessage>?> GetCustomerConversationAsync(long telegramUserId, string telegramUsername, string displayName, string firstName, string lastName)
        {
            try
            {
                if (!await AuthenticateAsync())
                    return null;

                // First, get or create the customer
                var customer = await _client.Customers.GetOrCreateCustomerAsync(new CreateCustomerRequest
                {
                    TelegramUserId = telegramUserId,
                    TelegramUsername = telegramUsername,
                    TelegramDisplayName = displayName,
                    TelegramFirstName = firstName,
                    TelegramLastName = lastName,
                    AllowOrderUpdates = true,
                    AllowMarketing = false
                });

                if (!customer.IsSuccess || customer.Data == null)
                {
                    return new List<CustomerMessage>();
                }

                // Get all messages for this customer (conversation history)
                var clientMessages = await _client.Messages.GetCustomerMessagesAsync(customer.Data.Id);
                
                // Convert to TeleBot CustomerMessage format
                return clientMessages?.Select(m => new CustomerMessage
                {
                    Id = m.Id,
                    CustomerId = m.CustomerId,
                    TelegramUserId = m.TelegramUserId,
                    Subject = m.Subject,
                    Content = m.Content,
                    Type = (MessageType)m.Type,
                    IsUrgent = m.IsUrgent,
                    OrderReference = m.OrderReference,
                    CreatedAt = m.CreatedAt,
                    Direction = m.Direction
                }).ToList() ?? new List<CustomerMessage>();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting customer conversation");
                return null;
            }
        }
    }
}