using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace TeleBot.Services
{
    public class BotManagerService : IHostedService, IDisposable
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<BotManagerService> _logger;
        private readonly HttpClient _httpClient;
        private readonly SessionManager _sessionManager;
        private Timer? _heartbeatTimer;
        private Timer? _metricsTimer;
        private string? _botKey;
        private Guid? _botId;
        private readonly Dictionary<string, decimal> _metricsBuffer;

        public BotManagerService(
            IConfiguration configuration,
            ILogger<BotManagerService> logger,
            HttpClient httpClient,
            SessionManager sessionManager)
        {
            _configuration = configuration;
            _logger = logger;
            _httpClient = httpClient;
            _sessionManager = sessionManager;
            _metricsBuffer = new Dictionary<string, decimal>();
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            try
            {
                // Check if bot key exists in configuration
                _botKey = _configuration["BotManager:ApiKey"];
                
                if (string.IsNullOrEmpty(_botKey))
                {
                    // Register new bot
                    await RegisterBotAsync();
                }
                else
                {
                    // Authenticate existing bot
                    await AuthenticateBotAsync();
                }

                // Sync settings from server
                await SyncSettingsAsync();

                // Start heartbeat timer (every 30 seconds)
                _heartbeatTimer = new Timer(SendHeartbeat, null, TimeSpan.Zero, TimeSpan.FromSeconds(30));

                // Start metrics timer (every 60 seconds)
                _metricsTimer = new Timer(SendMetrics, null, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(60));

                _logger.LogInformation("Bot manager service started successfully");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to start bot manager service");
            }
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _heartbeatTimer?.Change(Timeout.Infinite, 0);
            _metricsTimer?.Change(Timeout.Infinite, 0);
            
            // Send final metrics before stopping
            SendMetrics(null);
            
            _logger.LogInformation("Bot manager service stopped");
            return Task.CompletedTask;
        }

        private async Task RegisterBotAsync()
        {
            var apiUrl = _configuration["LittleShop:ApiUrl"];
            var registrationData = new
            {
                Name = _configuration["BotInfo:Name"] ?? "TeleBot",
                Description = _configuration["BotInfo:Description"] ?? "Telegram E-commerce Bot",
                Type = 0, // Telegram
                Version = _configuration["BotInfo:Version"] ?? "1.0.0",
                InitialSettings = new Dictionary<string, object>
                {
                    ["telegram"] = new
                    {
                        botToken = _configuration["Telegram:BotToken"],
                        webhookUrl = _configuration["Telegram:WebhookUrl"]
                    },
                    ["privacy"] = new
                    {
                        mode = _configuration["Privacy:Mode"],
                        enableTor = _configuration.GetValue<bool>("Privacy:EnableTor")
                    }
                }
            };

            var json = JsonSerializer.Serialize(registrationData);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync($"{apiUrl}/api/bots/register", content);
            
            if (response.IsSuccessStatusCode)
            {
                var responseJson = await response.Content.ReadAsStringAsync();
                var result = JsonSerializer.Deserialize<BotRegistrationResponse>(responseJson);
                
                _botKey = result?.BotKey;
                _botId = result?.BotId;
                
                _logger.LogInformation("Bot registered successfully. Bot ID: {BotId}", _botId);
                _logger.LogWarning("IMPORTANT: Save this bot key securely: {BotKey}", _botKey);
                
                // Save bot key to configuration or secure storage
                // In production, this should be saved securely
            }
            else
            {
                _logger.LogError("Failed to register bot: {StatusCode}", response.StatusCode);
            }
        }

        private async Task AuthenticateBotAsync()
        {
            var apiUrl = _configuration["LittleShop:ApiUrl"];
            var authData = new { BotKey = _botKey };
            
            var json = JsonSerializer.Serialize(authData);
            var content = new StringContent(json, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync($"{apiUrl}/api/bots/authenticate", content);
            
            if (response.IsSuccessStatusCode)
            {
                var responseJson = await response.Content.ReadAsStringAsync();
                var result = JsonSerializer.Deserialize<BotDto>(responseJson);
                
                _botId = result?.Id;
                _logger.LogInformation("Bot authenticated successfully. Bot ID: {BotId}", _botId);
            }
            else
            {
                _logger.LogError("Failed to authenticate bot: {StatusCode}", response.StatusCode);
            }
        }

        private async Task SyncSettingsAsync()
        {
            if (string.IsNullOrEmpty(_botKey)) return;

            var apiUrl = _configuration["LittleShop:ApiUrl"];
            _httpClient.DefaultRequestHeaders.Clear();
            _httpClient.DefaultRequestHeaders.Add("X-Bot-Key", _botKey);

            var response = await _httpClient.GetAsync($"{apiUrl}/api/bots/settings");
            
            if (response.IsSuccessStatusCode)
            {
                var settingsJson = await response.Content.ReadAsStringAsync();
                var settings = JsonSerializer.Deserialize<Dictionary<string, object>>(settingsJson);
                
                // Apply settings to configuration
                // This would update the running configuration with server settings
                _logger.LogInformation("Settings synced from server");
            }
        }

        private async void SendHeartbeat(object? state)
        {
            if (string.IsNullOrEmpty(_botKey)) return;

            try
            {
                var apiUrl = _configuration["LittleShop:ApiUrl"];
                var activeSessions = _sessionManager.GetActiveSessions().Count();
                
                var heartbeatData = new
                {
                    Version = _configuration["BotInfo:Version"] ?? "1.0.0",
                    IpAddress = "127.0.0.1", // In production, get actual IP
                    ActiveSessions = activeSessions,
                    Status = new Dictionary<string, object>
                    {
                        ["healthy"] = true,
                        ["uptime"] = DateTime.UtcNow.Subtract(AppDomain.CurrentDomain.BaseDirectory != null 
                            ? new System.IO.DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory).CreationTimeUtc 
                            : DateTime.UtcNow).TotalSeconds
                    }
                };

                var json = JsonSerializer.Serialize(heartbeatData);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                _httpClient.DefaultRequestHeaders.Clear();
                _httpClient.DefaultRequestHeaders.Add("X-Bot-Key", _botKey);

                await _httpClient.PostAsync($"{apiUrl}/api/bots/heartbeat", content);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to send heartbeat");
            }
        }

        private async void SendMetrics(object? state)
        {
            if (string.IsNullOrEmpty(_botKey)) return;

            try
            {
                var apiUrl = _configuration["LittleShop:ApiUrl"];
                var metrics = new List<object>();

                // Collect metrics from buffer
                lock (_metricsBuffer)
                {
                    foreach (var metric in _metricsBuffer)
                    {
                        metrics.Add(new
                        {
                            MetricType = GetMetricType(metric.Key),
                            Value = metric.Value,
                            Category = "Bot",
                            Description = metric.Key
                        });
                    }
                    _metricsBuffer.Clear();
                }

                if (!metrics.Any()) return;

                var metricsData = new { Metrics = metrics };
                var json = JsonSerializer.Serialize(metricsData);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                _httpClient.DefaultRequestHeaders.Clear();
                _httpClient.DefaultRequestHeaders.Add("X-Bot-Key", _botKey);

                await _httpClient.PostAsync($"{apiUrl}/api/bots/metrics/batch", content);
                
                _logger.LogDebug("Sent {Count} metrics to server", metrics.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to send metrics");
            }
        }

        public void RecordMetric(string name, decimal value)
        {
            lock (_metricsBuffer)
            {
                if (_metricsBuffer.ContainsKey(name))
                    _metricsBuffer[name] += value;
                else
                    _metricsBuffer[name] = value;
            }
        }

        public async Task<Guid?> StartSessionAsync(string sessionIdentifier, string platform = "Telegram")
        {
            if (string.IsNullOrEmpty(_botKey)) return null;

            try
            {
                var apiUrl = _configuration["LittleShop:ApiUrl"];
                var sessionData = new
                {
                    SessionIdentifier = sessionIdentifier,
                    Platform = platform,
                    Language = "en",
                    Country = "",
                    IsAnonymous = true,
                    Metadata = new Dictionary<string, object>()
                };

                var json = JsonSerializer.Serialize(sessionData);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                _httpClient.DefaultRequestHeaders.Clear();
                _httpClient.DefaultRequestHeaders.Add("X-Bot-Key", _botKey);

                var response = await _httpClient.PostAsync($"{apiUrl}/api/bots/sessions/start", content);
                
                if (response.IsSuccessStatusCode)
                {
                    var responseJson = await response.Content.ReadAsStringAsync();
                    var result = JsonSerializer.Deserialize<SessionDto>(responseJson);
                    return result?.Id;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to start session");
            }

            return null;
        }

        public async Task UpdateSessionAsync(Guid sessionId, int? orderCount = null, int? messageCount = null, decimal? totalSpent = null)
        {
            if (string.IsNullOrEmpty(_botKey)) return;

            try
            {
                var apiUrl = _configuration["LittleShop:ApiUrl"];
                var updateData = new
                {
                    OrderCount = orderCount,
                    MessageCount = messageCount,
                    TotalSpent = totalSpent
                };

                var json = JsonSerializer.Serialize(updateData);
                var content = new StringContent(json, Encoding.UTF8, "application/json");
                
                _httpClient.DefaultRequestHeaders.Clear();
                _httpClient.DefaultRequestHeaders.Add("X-Bot-Key", _botKey);

                await _httpClient.PutAsync($"{apiUrl}/api/bots/sessions/{sessionId}", content);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Failed to update session");
            }
        }

        private int GetMetricType(string metricName)
        {
            return metricName.ToLower() switch
            {
                "message" => 4,
                "order" => 2,
                "error" => 6,
                "command" => 5,
                _ => 7 // ApiCall
            };
        }

        public void Dispose()
        {
            _heartbeatTimer?.Dispose();
            _metricsTimer?.Dispose();
        }

        // DTOs for API responses
        private class BotRegistrationResponse
        {
            public Guid BotId { get; set; }
            public string BotKey { get; set; } = string.Empty;
            public string Name { get; set; } = string.Empty;
        }

        private class BotDto
        {
            public Guid Id { get; set; }
            public string Name { get; set; } = string.Empty;
        }

        private class SessionDto
        {
            public Guid Id { get; set; }
        }
    }
}