using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using QRRapidoApp.Models;
using QRRapidoApp.Services;
using System.Security.Claims;

namespace QRRapidoApp.Controllers
{
    [Authorize]
    [Route("Developer")]
    [Route("es/Developer")]
    [Route("en/Developer")]
    public class DeveloperController : Controller
    {
        private readonly IUserService _userService;
        private readonly StripeService _stripeService;
        private readonly ILogger<DeveloperController> _logger;
        private readonly IDistributedCache _cache;
        private readonly IWebHostEnvironment _env;

        public DeveloperController(
            IUserService userService,
            StripeService stripeService,
            ILogger<DeveloperController> logger,
            IDistributedCache cache,
            IWebHostEnvironment env)
        {
            _userService   = userService;
            _stripeService = stripeService;
            _logger        = logger;
            _cache         = cache;
            _env           = env;
        }

        [HttpGet("")]
        public async Task<IActionResult> Index()
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (string.IsNullOrEmpty(userId)) return Unauthorized();

            var user = await _userService.GetUserAsync(userId);
            if (user == null) return NotFound();

            ViewBag.Culture = GetCulture();
            return View(user);
        }

        [HttpPost("GenerateKey")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> GenerateKey(string keyName)
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (string.IsNullOrEmpty(userId)) return Unauthorized();

            if (string.IsNullOrWhiteSpace(keyName) || keyName.Length > 50)
            {
                TempData["Error"] = "Nome da chave inválido (máx. 50 caracteres).";
                return Redirect(GetDevUrl());
            }

            var user = await _userService.GetUserAsync(userId);
            if (user == null) return NotFound();

            if (user.ApiKeys.Count(k => k.IsActive) >= 5)
            {
                TempData["Error"] = "Limite de 5 chaves ativas atingido. Revogue uma antes de criar outra.";
                return Redirect(GetDevUrl());
            }

            var (rawKey, prefix) = await _userService.GenerateApiKeyAsync(userId, keyName.Trim());

            _logger.LogInformation("API key '{Prefix}' generated for user {UserId}", prefix, userId);

            TempData["NewKey"] = rawKey;
            TempData["NewKeyName"] = keyName.Trim();
            return RedirectToAction(nameof(Index));
        }

        [HttpGet("Pricing")]
        public async Task<IActionResult> Pricing()
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            User? user = null;
            if (!string.IsNullOrEmpty(userId))
                user = await _userService.GetUserAsync(userId);

            ViewBag.CurrentTier = user?.ApiSubscription?.EffectiveTier ?? ApiPlanTier.Free;
            ViewBag.Culture = GetCulture();
            return View();
        }

        [HttpPost("SubscribeApi")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> SubscribeApi(string planTier)
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (string.IsNullOrEmpty(userId)) return Unauthorized();

            if (!Enum.TryParse<ApiPlanTier>(planTier, out var tier) ||
                tier == ApiPlanTier.Free ||
                tier == ApiPlanTier.Enterprise)
            {
                TempData["Error"] = "Plano inválido selecionado.";
                return Redirect(GetDevUrl("Pricing"));
            }

            try
            {
                var baseUrl = $"{Request.Scheme}://{Request.Host}";
                var checkoutUrl = await _stripeService.CreateApiSubscriptionCheckoutAsync(userId, tier, baseUrl);
                return Redirect(checkoutUrl);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating API subscription checkout for user {UserId}", userId);
                TempData["Error"] = "Erro ao criar sessão de pagamento. Tente novamente.";
                return Redirect(GetDevUrl("Pricing"));
            }
        }

        [HttpGet("Mcp")]
        public async Task<IActionResult> Mcp()
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (string.IsNullOrEmpty(userId)) return Unauthorized();

            var user = await _userService.GetUserAsync(userId);
            if (user == null) return NotFound();

            ViewBag.Culture = GetCulture();
            return View(user);
        }

        [HttpPost("RevokeKey")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> RevokeKey(string prefix)
        {
            var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (string.IsNullOrEmpty(userId)) return Unauthorized();

            if (string.IsNullOrWhiteSpace(prefix))
            {
                TempData["Error"] = "Chave inválida.";
                return Redirect(GetDevUrl());
            }

            var revoked = await _userService.RevokeApiKeyAsync(userId, prefix);

            if (revoked)
            {
                _logger.LogInformation("API key '{Prefix}' revoked by user {UserId}", prefix, userId);
                TempData["Success"] = "Chave revogada com sucesso.";
            }
            else
            {
                TempData["Error"] = "Chave não encontrada ou já inativa.";
            }

            return RedirectToAction(nameof(Index));
        }
        [HttpPost("ResetRateLimit")]
        public async Task<IActionResult> ResetRateLimit(string prefix)
        {
            if (!_env.IsDevelopment())
                return Forbid();

            if (string.IsNullOrWhiteSpace(prefix))
                return BadRequest("prefix required");

            var now = DateTime.UtcNow;
            var monthKey  = $"rl:mo:{prefix}:{now:yyyyMM}";
            var minuteKey = $"rl:min:{prefix}:{now:yyyyMMddHHmm}";

            await Task.WhenAll(
                _cache.RemoveAsync(monthKey),
                _cache.RemoveAsync(minuteKey)
            );

            _logger.LogWarning("Rate limit reset for prefix {Prefix} (dev only)", prefix);
            TempData["Success"] = $"Rate limit resetado para '{prefix}'.";
            return RedirectToAction(nameof(Index));
        }

        private string GetCulture()
        {
            var path = Request.Path.Value ?? "";
            if (path.StartsWith("/es/", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(path, "/es", StringComparison.OrdinalIgnoreCase)) return "es";
            if (path.StartsWith("/en/", StringComparison.OrdinalIgnoreCase) ||
                string.Equals(path, "/en", StringComparison.OrdinalIgnoreCase)) return "en";
            return "pt-BR";
        }

        private string GetDevUrl(string action = "")
        {
            var base_ = GetCulture() switch {
                "es"    => "/es/Developer",
                "en"    => "/en/Developer",
                _       => "/Developer"
            };
            return string.IsNullOrEmpty(action) ? base_ : $"{base_}/{action}";
        }
    }
}
