using Microsoft.AspNetCore.Mvc;
using OnlyOneAccessTemplate.Services;
using OnlyOneAccessTemplate.Models;
using System.Security.Cryptography;
using System.Text;
using Microsoft.AspNetCore.Http.Extensions;

namespace OnlyOneAccessTemplate.Controllers
{
    [Route("api/module-management")]
    [ApiController]
    public class ModuleManagementController : ControllerBase
    {
        private readonly IModuleService _moduleService;
        private readonly ILogger<ModuleManagementController> _logger;
        private readonly IConfiguration _configuration;

        public ModuleManagementController(
            IModuleService moduleService,
            ILogger<ModuleManagementController> logger,
            IConfiguration configuration)
        {
            _moduleService = moduleService;
            _logger = logger;
            _configuration = configuration;
        }

        [HttpPost("register")]
        public async Task<IActionResult> RegisterModule([FromBody] ModuleRegistrationRequest request)
        {
            try
            {
                _logger.LogInformation("Registrando novo módulo: {ModuleId}", request.ModuleId);

                // Verificar se módulo já existe
                var existing = await _moduleService.GetModuleConfigAsync(request.ModuleId);
                if (existing != null)
                {
                    return BadRequest(new { success = false, message = "Módulo já existe" });
                }

                // Testar conectividade com o módulo
                var healthUrl = $"{request.BaseUrl.TrimEnd('/')}/{request.HealthEndpoint?.TrimStart('/') ?? "api/converter/health"}";
                var isHealthy = await TestModuleHealth(healthUrl);

                // Gerar API Key
                var apiKey = GenerateApiKey();

                // Criar configuração
                var moduleConfig = new ModuleConfig
                {
                    ModuleId = request.ModuleId,
                    Name = request.Name,
                    Url = $"{request.BaseUrl.TrimEnd('/')}/modules/{request.ModuleId}",
                    RequestBy = request.ModuleId,
                    IsActive = request.AutoActivate.HasValue && request.AutoActivate.Value && isHealthy,
                    CacheMinutes = request.CacheMinutes ?? 5,

                    // Proxy Configuration
                    UseProxy = true,
                    ProxyEndpoint = $"/api/modules/{request.ModuleId}",
                    ProxyMappings = new Dictionary<string, string>
                    {
                        ["convert"] = $"{request.BaseUrl}/api/converter/convert",
                        ["config"] = $"{request.BaseUrl}/api/converter/config",
                        ["health"] = $"{request.BaseUrl}/api/converter/health"
                    },

                    // Security
                    ApiKey = apiKey,
                    AllowedOrigins = request.AllowedOrigins ?? new List<string> { Request.GetDisplayUrl() },
                    RateLimitPerMinute = request.RateLimitPerMinute ?? 60,

                    // Menu
                    MenuTitle = request.MenuTitle ?? request.Name,
                    MenuDescription = request.MenuDescription,
                    MenuIcon = request.MenuIcon ?? "fas fa-exchange-alt",
                    MenuCategory = request.MenuCategory ?? "Conversores",
                    MenuOrder = request.MenuOrder ?? 0,
                    ShowInMenu = request.ShowInMenu ?? true,

                    // SEO
                    SeoTitles = request.SeoTitles ?? new Dictionary<string, string>(),
                    SeoDescriptions = request.SeoDescriptions ?? new Dictionary<string, string>(),
                    SeoKeywords = request.SeoKeywords ?? new Dictionary<string, string>(),

                    // Technical
                    HealthEndpoint = request.HealthEndpoint ?? "/api/converter/health",
                    HealthCheckIntervalMinutes = request.HealthCheckIntervalMinutes ?? 5,
                    AutoStart = request.AutoActivate ?? true,
                    Version = request.Version ?? "1.0.0",
                    IsHealthy = isHealthy,
                    LastHealthCheck = DateTime.UtcNow,

                    // Developer
                    DeveloperName = request.DeveloperName,
                    DeveloperEmail = request.DeveloperEmail,
                    Repository = request.Repository,
                    Documentation = request.Documentation,

                    // Headers
                    Headers = new Dictionary<string, string>
                    {
                        ["X-API-Key"] = apiKey,
                        ["User-Agent"] = "ConvertIt-MainApp/1.0"
                    }
                };

                await _moduleService.SaveModuleConfigAsync(moduleConfig);

                _logger.LogInformation("Módulo {ModuleId} registrado com sucesso", request.ModuleId);

                return Ok(new
                {
                    success = true,
                    message = "Módulo registrado com sucesso",
                    moduleId = request.ModuleId,
                    apiKey = apiKey,
                    proxyEndpoint = moduleConfig.ProxyEndpoint,
                    isHealthy = isHealthy,
                    isActive = moduleConfig.IsActive
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao registrar módulo {ModuleId}", request.ModuleId);
                return StatusCode(500, new { success = false, message = ex.Message });
            }
        }

        [HttpGet("modules")]
        public async Task<IActionResult> ListModules()
        {
            try
            {
                var modules = await _moduleService.GetAllActiveModulesAsync();

                var result = modules.Select(m => new
                {
                    moduleId = m.ModuleId,
                    name = m.Name,
                    isActive = m.IsActive,
                    isHealthy = m.IsHealthy,
                    lastHealthCheck = m.LastHealthCheck,
                    version = m.Version,
                    menuTitle = m.MenuTitle,
                    menuCategory = m.MenuCategory,
                    showInMenu = m.ShowInMenu,
                    developerName = m.DeveloperName,
                    proxyEndpoint = m.ProxyEndpoint
                });

                return Ok(new { success = true, modules = result });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao listar módulos");
                return StatusCode(500, new { success = false, message = ex.Message });
            }
        }

        [HttpPost("modules/{moduleId}/toggle")]
        public async Task<IActionResult> ToggleModule(string moduleId)
        {
            try
            {
                var module = await _moduleService.GetModuleConfigAsync(moduleId);
                if (module == null)
                {
                    return NotFound(new { success = false, message = "Módulo não encontrado" });
                }

                module.IsActive = !module.IsActive;
                module.UpdatedAt = DateTime.UtcNow;

                await _moduleService.SaveModuleConfigAsync(module);

                _logger.LogInformation("Módulo {ModuleId} {Status}", moduleId,
                    module.IsActive ? "ativado" : "desativado");

                return Ok(new
                {
                    success = true,
                    moduleId = moduleId,
                    isActive = module.IsActive,
                    message = $"Módulo {(module.IsActive ? "ativado" : "desativado")} com sucesso"
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao alternar módulo {ModuleId}", moduleId);
                return StatusCode(500, new { success = false, message = ex.Message });
            }
        }

        [HttpPost("modules/{moduleId}/health-check")]
        public async Task<IActionResult> CheckModuleHealth(string moduleId)
        {
            try
            {
                var module = await _moduleService.GetModuleConfigAsync(moduleId);
                if (module == null)
                {
                    return NotFound(new { success = false, message = "Módulo não encontrado" });
                }

                var healthUrl = $"{GetBaseUrl(module.Url)}{module.HealthEndpoint}";
                var isHealthy = await TestModuleHealth(healthUrl);

                module.IsHealthy = isHealthy;
                module.LastHealthCheck = DateTime.UtcNow;
                await _moduleService.SaveModuleConfigAsync(module);

                return Ok(new
                {
                    success = true,
                    moduleId = moduleId,
                    isHealthy = isHealthy,
                    lastCheck = module.LastHealthCheck,
                    healthUrl = healthUrl
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao verificar saúde do módulo {ModuleId}", moduleId);
                return StatusCode(500, new { success = false, message = ex.Message });
            }
        }

        [HttpDelete("modules/{moduleId}")]
        public async Task<IActionResult> UnregisterModule(string moduleId)
        {
            try
            {
                var module = await _moduleService.GetModuleConfigAsync(moduleId);
                if (module == null)
                {
                    return NotFound(new { success = false, message = "Módulo não encontrado" });
                }

                // Aqui você implementaria a remoção (dependendo de como está armazenado)
                // Por enquanto, vamos apenas desativar
                module.IsActive = false;
                module.UpdatedAt = DateTime.UtcNow;
                await _moduleService.SaveModuleConfigAsync(module);

                _logger.LogInformation("Módulo {ModuleId} desregistrado", moduleId);

                return Ok(new
                {
                    success = true,
                    message = "Módulo desregistrado com sucesso"
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao desregistrar módulo {ModuleId}", moduleId);
                return StatusCode(500, new { success = false, message = ex.Message });
            }
        }

        private async Task<bool> TestModuleHealth(string healthUrl)
        {
            try
            {
                using var client = new HttpClient();
                client.Timeout = TimeSpan.FromSeconds(10);
                var response = await client.GetAsync(healthUrl);
                return response.IsSuccessStatusCode;
            }
            catch
            {
                return false;
            }
        }

        private string GenerateApiKey()
        {
            using var rng = RandomNumberGenerator.Create();
            var bytes = new byte[32];
            rng.GetBytes(bytes);
            return Convert.ToBase64String(bytes);
        }

        private string GetBaseUrl(string fullUrl)
        {
            var uri = new Uri(fullUrl);
            return $"{uri.Scheme}://{uri.Host}:{uri.Port}";
        }
    }

    public class ModuleRegistrationRequest
    {
        public string ModuleId { get; set; } = "";
        public string Name { get; set; } = "";
        public string BaseUrl { get; set; } = "";
        public bool? AutoActivate { get; set; } = true;
        public int? CacheMinutes { get; set; } = 5;
        public List<string>? AllowedOrigins { get; set; }
        public int? RateLimitPerMinute { get; set; } = 60;

        // Menu
        public string? MenuTitle { get; set; }
        public string? MenuDescription { get; set; }
        public string? MenuIcon { get; set; }
        public string? MenuCategory { get; set; }
        public int? MenuOrder { get; set; }
        public bool? ShowInMenu { get; set; } = true;

        // SEO
        public Dictionary<string, string>? SeoTitles { get; set; }
        public Dictionary<string, string>? SeoDescriptions { get; set; }
        public Dictionary<string, string>? SeoKeywords { get; set; }

        // Technical
        public string? HealthEndpoint { get; set; }
        public int? HealthCheckIntervalMinutes { get; set; }
        public string? Version { get; set; }

        // Developer
        public string? DeveloperName { get; set; }
        public string? DeveloperEmail { get; set; }
        public string? Repository { get; set; }
        public string? Documentation { get; set; }
    }
}