using Microsoft.AspNetCore.Mvc;
using QRRapidoApp.Models.ViewModels;
using QRRapidoApp.Services;
using System.Diagnostics;
using System.Security.Claims;
using System.Text;
using Microsoft.Extensions.Localization;

namespace QRRapidoApp.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class QRController : ControllerBase
    {
        private readonly IQRCodeService _qrService;
        private readonly IUserService _userService;
        private readonly AdDisplayService _adService;
        private readonly ILogger<QRController> _logger;
        private readonly IStringLocalizer<QRRapidoApp.Resources.SharedResource> _localizer;
        private readonly AdDisplayService _adDisplayService;

        public QRController(IQRCodeService qrService, IUserService userService, AdDisplayService adService, ILogger<QRController> logger, IStringLocalizer<QRRapidoApp.Resources.SharedResource> localizer, AdDisplayService adDisplayService)
        {
            _qrService = qrService;
            _userService = userService;
            _adService = adService;
            _logger = logger;
            _localizer = localizer;
            _adDisplayService = adDisplayService;
        }

        [HttpPost("GenerateRapid")]
        public async Task<IActionResult> GenerateRapid([FromBody] QRGenerationRequest request)
        {
            var stopwatch = Stopwatch.StartNew();
            var requestId = Guid.NewGuid().ToString("N")[..8];
            var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var isAuthenticated = User?.Identity?.IsAuthenticated ?? false;

            using (_logger.BeginScope(new Dictionary<string, object>
            {
                ["RequestId"] = requestId,
                ["UserId"] = userId ?? "anonymous",
                ["IsAuthenticated"] = isAuthenticated,
                ["QRType"] = request.Type ?? "unknown",
                ["ContentLength"] = request.Content?.Length ?? 0,
                ["QRGeneration"] = true
            }))
            {
                _logger.LogInformation("QR generation request started - Type: {QRType}, ContentLength: {ContentLength}, User: {UserType}",
                    request.Type, request.Content?.Length ?? 0, isAuthenticated ? "authenticated" : "anonymous");
                
                try
                {
                    // Quick validations
                    if (string.IsNullOrWhiteSpace(request.Content))
                    {
                        _logger.LogWarning("QR generation failed - empty content provided");
                        return BadRequest(new { error = _localizer["RequiredContent"], success = false });
                    }

                    if (request.Content.Length > 4000) // Limit to maintain speed
                    {
                        _logger.LogWarning("QR generation failed - content too long: {ContentLength} characters", request.Content.Length);
                        return BadRequest(new { error = _localizer["ContentTooLong"], success = false });
                    }

                    // Check user status
                    var user = await _userService.GetUserAsync(userId);

                    // Validate premium features
                    if (!string.IsNullOrEmpty(request.CornerStyle) && request.CornerStyle != "square" && user?.IsPremium != true)
                    {
                        _logger.LogWarning("Custom corner style attempted by non-premium user - UserId: {UserId}, CornerStyle: {CornerStyle}", 
                            userId ?? "anonymous", request.CornerStyle);
                        return BadRequest(new 
                        { 
                            error = _localizer["PremiumCornerStyleRequired"],
                            requiresPremium = true,
                            success = false
                        });
                    }

                    // Rate limiting for free users
                    var rateLimitPassed = await CheckRateLimitAsync(userId, user);
                    if (!rateLimitPassed)
                    {
                        _logger.LogWarning("QR generation rate limited - User: {UserId}, IsPremium: {IsPremium}", 
                            userId ?? "anonymous", user?.IsPremium ?? false);
                        return StatusCode(429, new
                        {
                            error = _localizer["RateLimitReached"],
                            upgradeUrl = "/Pagamento/SelecaoPlano",
                            success = false
                        });
                    }

                    // Configure optimizations based on user
                    request.IsPremium = user?.IsPremium == true;
                    request.OptimizeForSpeed = true;

                    _logger.LogDebug("Generating QR code - IsPremium: {IsPremium}, OptimizeForSpeed: {OptimizeForSpeed}", 
                        request.IsPremium, request.OptimizeForSpeed);

                    // Generate QR code
                    var generationStopwatch = Stopwatch.StartNew();
                    var result = await _qrService.GenerateRapidAsync(request);
                    generationStopwatch.Stop();

                    if (!result.Success)
                    {
                        _logger.LogError("QR generation failed - Error: {ErrorMessage}, GenerationTime: {GenerationTimeMs}ms", 
                            result.ErrorMessage, generationStopwatch.ElapsedMilliseconds);
                        return StatusCode(500, new { error = result.ErrorMessage, success = false });
                    }

                    _logger.LogInformation("QR code generated successfully - GenerationTime: {GenerationTimeMs}ms, FromCache: {FromCache}, Size: {Size}px",
                        generationStopwatch.ElapsedMilliseconds, result.FromCache, request.Size);

                    // Update counter for all logged users
                    if (userId != null)
                    {
                        if (request.IsPremium)
                        {
                            result.RemainingQRs = int.MaxValue; // Premium users have unlimited
                            // Still increment the count for statistics
                            await _userService.IncrementDailyQRCountAsync(userId);
                        }
                        else
                        {
                            var remaining = await _userService.IncrementDailyQRCountAsync(userId);
                            result.RemainingQRs = remaining;
                            _logger.LogDebug("Updated QR count for free user - Remaining: {RemainingQRs}", remaining);
                        }
                    }

                    // Save to history if user is logged in (fire and forget)
                    if (userId != null)
                    {
                        _ = Task.Run(async () =>
                        {
                            try
                            {
                                await _userService.SaveQRToHistoryAsync(userId, result);
                                _logger.LogDebug("QR code saved to history successfully for user {UserId}", userId);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "Error saving QR to history for user {UserId}", userId);
                            }
                        });
                    }

                    stopwatch.Stop();
                    var totalTimeMs = stopwatch.ElapsedMilliseconds;

                    // Performance logging with structured data
                    using (_logger.BeginScope(new Dictionary<string, object>
                    {
                        ["TotalRequestTimeMs"] = totalTimeMs,
                        ["QRGenerationTimeMs"] = generationStopwatch.ElapsedMilliseconds,
                        ["ServiceGenerationTimeMs"] = result.GenerationTimeMs,
                        ["FromCache"] = result.FromCache,
                        ["UserType"] = request.IsPremium ? "premium" : "free",
                        ["QRSize"] = request.Size,
                        ["Success"] = true
                    }))
                    {
                        var performanceStatus = totalTimeMs switch
                        {
                            < 500 => "excellent",
                            < 1000 => "good",
                            < 2000 => "acceptable", 
                            _ => "slow"
                        };

                        _logger.LogInformation("QR generation completed - TotalTime: {TotalTimeMs}ms, ServiceTime: {ServiceTimeMs}ms, Performance: {PerformanceStatus}, Cache: {FromCache}",
                            totalTimeMs, result.GenerationTimeMs, performanceStatus, result.FromCache);
                    }

                    return Ok(result);
                }
                catch (Exception ex)
                {
                    stopwatch.Stop();
                    _logger.LogError(ex, "QR generation failed with exception - RequestTime: {RequestTimeMs}ms, UserId: {UserId}", 
                        stopwatch.ElapsedMilliseconds, userId ?? "anonymous");
                    return StatusCode(500, new { error = "Erro interno do servidor", success = false });
                }
            }
        }

        [HttpGet("Download/{qrId}")]
        public async Task<IActionResult> Download(string qrId, string format = "png")
        {
            var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var stopwatch = Stopwatch.StartNew();
            
            using (_logger.BeginScope(new Dictionary<string, object>
            {
                ["QRId"] = qrId,
                ["Format"] = format.ToLower(),
                ["UserId"] = userId ?? "anonymous",
                ["QRDownload"] = true
            }))
            {
                _logger.LogInformation("QR download requested - QRId: {QRId}, Format: {Format}", qrId, format);
                
                try
                {
                    var qrData = await _userService.GetQRDataAsync(qrId);
                    if (qrData == null)
                    {
                        _logger.LogWarning("QR download failed - QR code not found: {QRId}", qrId);
                        return NotFound();
                    }

                    var contentType = format.ToLower() switch
                    {
                        "svg" => "image/svg+xml",
                        "pdf" => "application/pdf", 
                        _ => "image/png"
                    };

                    var fileName = $"qrrapido-{DateTime.Now:yyyyMMdd-HHmmss}.{format}";

                    _logger.LogDebug("Converting QR to format - QRId: {QRId}, Format: {Format}, Size: {Size}", 
                        qrId, format, qrData.Size);

                    byte[] fileContent;
                    if (format.ToLower() == "svg")
                    {
                        fileContent = await _qrService.ConvertToSvgAsync(qrData.QRCodeBase64);
                    }
                    else if (format.ToLower() == "pdf")
                    {
                        fileContent = await _qrService.ConvertToPdfAsync(qrData.QRCodeBase64, qrData.Size);
                    }
                    else
                    {
                        fileContent = Convert.FromBase64String(qrData.QRCodeBase64);
                    }

                    stopwatch.Stop();
                    _logger.LogInformation("QR download completed - QRId: {QRId}, Format: {Format}, Size: {FileSize} bytes, ProcessingTime: {ProcessingTimeMs}ms",
                        qrId, format, fileContent.Length, stopwatch.ElapsedMilliseconds);

                    return File(fileContent, contentType, fileName);
                }
                catch (Exception ex)
                {
                    stopwatch.Stop();
                    _logger.LogError(ex, "QR download failed - QRId: {QRId}, Format: {Format}, ProcessingTime: {ProcessingTimeMs}ms", 
                        qrId, format, stopwatch.ElapsedMilliseconds);
                    return StatusCode(500);
                }
            }
        }

        [HttpPost("SaveToHistory")]
        public async Task<IActionResult> SaveToHistory([FromBody] SaveToHistoryRequest request)
        {
            var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            
            using (_logger.BeginScope(new Dictionary<string, object>
            {
                ["QRId"] = request.QrId,
                ["UserId"] = userId ?? "anonymous",
                ["SaveToHistory"] = true
            }))
            {
                _logger.LogInformation("Save to history requested - QRId: {QRId}", request.QrId);
                
                try
                {
                    if (string.IsNullOrEmpty(userId))
                    {
                        _logger.LogWarning("Save to history failed - user not authenticated");
                        return Unauthorized();
                    }

                    var qrData = await _userService.GetQRDataAsync(request.QrId);
                    if (qrData == null)
                    {
                        _logger.LogWarning("Save to history failed - QR code not found: {QRId}", request.QrId);
                        return NotFound();
                    }

                    // QR is already saved when generated, just return success
                    _logger.LogInformation("QR code already saved in history - QRId: {QRId}", request.QrId);
                    return Ok(new { success = true, message = "QR Code salvo no histórico!" });
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Save to history failed - QRId: {QRId}", request.QrId);
                    return StatusCode(500, new { error = "Erro ao salvar no histórico." });
                }
            }
        }

        [HttpPost("GenerateRapidWithLogo")]
        public async Task<IActionResult> GenerateRapidWithLogo([FromForm] QRGenerationRequest request, IFormFile? logo)
        {
            var stopwatch = Stopwatch.StartNew();
            var requestId = Guid.NewGuid().ToString("N")[..8];
            var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var isAuthenticated = User?.Identity?.IsAuthenticated ?? false;

            // DEBUG: Log detalhado dos parâmetros recebidos
            _logger.LogInformation("🔍 [DEBUG] GenerateRapidWithLogo called - RequestId: {RequestId}, ApplyLogoColorization: {ApplyLogoColorization}, LogoSizePercent: {LogoSizePercent}, HasLogo: {HasLogo}", 
                requestId, request.ApplyLogoColorization, request.LogoSizePercent, request.HasLogo);
            
            using (_logger.BeginScope(new Dictionary<string, object>
            {
                ["RequestId"] = requestId,
                ["UserId"] = userId ?? "anonymous",
                ["IsAuthenticated"] = isAuthenticated,
                ["QRType"] = request.Type ?? "unknown",
                ["ContentLength"] = request.Content?.Length ?? 0,
                ["QRGeneration"] = true,
                ["HasLogo"] = logo != null
            }))
            {
                _logger.LogInformation("QR generation with logo request started - Type: {QRType}, ContentLength: {ContentLength}, HasLogo: {HasLogo}",
                    request.Type, request.Content?.Length ?? 0, logo != null);
                
                try
                {
                    // Quick validations
                    if (string.IsNullOrWhiteSpace(request.Content))
                    {
                        _logger.LogWarning("QR generation failed - empty content provided");
                        return BadRequest(new { error = _localizer["RequiredContent"], success = false });
                    }

                    if (request.Content.Length > 4000)
                    {
                        _logger.LogWarning("QR generation failed - content too long: {ContentLength} characters", request.Content.Length);
                        return BadRequest(new { error = _localizer["ContentTooLong"], success = false });
                    }

                    // Check user status
                    var user = await _userService.GetUserAsync(userId);

                    // Validate premium status for logo feature
                    if (user?.IsPremium != true)
                    {
                        _logger.LogWarning("Logo upload attempted by non-premium user - UserId: {UserId}", userId ?? "anonymous");
                        return BadRequest(new 
                        { 
                            error = _localizer["PremiumLogoRequired"],
                            requiresPremium = true,
                            success = false
                        });
                    }

                    // Validate premium corner styles
                    if (!string.IsNullOrEmpty(request.CornerStyle) && request.CornerStyle != "square")
                    {
                        _logger.LogInformation("Premium user using custom corner style - UserId: {UserId}, CornerStyle: {CornerStyle}", 
                            userId, request.CornerStyle);
                    }

                    // Process logo upload if provided
                    if (logo != null && logo.Length > 0)
                    {
                        // Validate file size (2MB max)
                        if (logo.Length > 2 * 1024 * 1024)
                        {
                            _logger.LogWarning("Logo upload failed - file too large: {FileSize} bytes", logo.Length);
                            return BadRequest(new { error = _localizer["LogoTooLarge"], success = false });
                        }

                        // Validate file format
                        var allowedTypes = new[] { "image/png", "image/jpeg", "image/jpg" };
                        if (!allowedTypes.Contains(logo.ContentType?.ToLower()))
                        {
                            _logger.LogWarning("Logo upload failed - invalid format: {ContentType}", logo.ContentType);
                            return BadRequest(new { error = _localizer["InvalidLogoFormat"], success = false });
                        }

                        try
                        {
                            // Convert file to byte array
                            using var memoryStream = new MemoryStream();
                            await logo.CopyToAsync(memoryStream);
                            request.Logo = memoryStream.ToArray();
                            request.HasLogo = true;

                            _logger.LogInformation("Logo processed successfully - Size: {LogoSize} bytes, Format: {ContentType}, SizePercent: {SizePercent}%, Colorized: {Colorized}", 
                                logo.Length, logo.ContentType, request.LogoSizePercent ?? 20, request.ApplyLogoColorization);
                        }
                        catch (Exception ex)
                        {
                            _logger.LogError(ex, "Error processing logo file");
                            return BadRequest(new { error = _localizer["ErrorProcessingLogo"], success = false });
                        }
                    }

                    // Rate limiting for free users (premium users get unlimited)
                    var rateLimitPassed = await CheckRateLimitAsync(userId, user);
                    if (!rateLimitPassed)
                    {
                        _logger.LogWarning("QR generation rate limited - User: {UserId}, IsPremium: {IsPremium}", 
                            userId ?? "anonymous", user?.IsPremium ?? false);
                        return StatusCode(429, new
                        {
                            error = _localizer["RateLimitReached"],
                            upgradeUrl = "/Pagamento/SelecaoPlano",
                            success = false
                        });
                    }

                    // Configure optimizations based on user
                    request.IsPremium = user?.IsPremium == true;
                    request.OptimizeForSpeed = true;

                    _logger.LogDebug("Generating QR code with logo - IsPremium: {IsPremium}, HasLogo: {HasLogo}, LogoSize: {LogoSize}%, Colorized: {Colorized}", 
                        request.IsPremium, request.HasLogo, request.LogoSizePercent ?? 20, request.ApplyLogoColorization);

                    // Generate QR code
                    var generationStopwatch = Stopwatch.StartNew();
                    var result = await _qrService.GenerateRapidAsync(request);
                    generationStopwatch.Stop();

                    if (!result.Success)
                    {
                        _logger.LogError("QR generation failed - Error: {ErrorMessage}, GenerationTime: {GenerationTimeMs}ms", 
                            result.ErrorMessage, generationStopwatch.ElapsedMilliseconds);
                        return StatusCode(500, new { error = result.ErrorMessage, success = false });
                    }

                    _logger.LogInformation("QR code with logo generated successfully - GenerationTime: {GenerationTimeMs}ms, FromCache: {FromCache}, HasLogo: {HasLogo}, Base64Length: {Base64Length}",
                        generationStopwatch.ElapsedMilliseconds, result.FromCache, request.HasLogo, result.QRCodeBase64?.Length ?? 0);

                    // Save to history if user is logged in (fire and forget)
                    if (userId != null)
                    {
                        _ = Task.Run(async () =>
                        {
                            try
                            {
                                await _userService.SaveQRToHistoryAsync(userId, result);
                                _logger.LogDebug("QR code saved to history successfully for user {UserId}", userId);
                            }
                            catch (Exception ex)
                            {
                                _logger.LogError(ex, "Error saving QR to history for user {UserId}", userId);
                            }
                        });
                    }

                    stopwatch.Stop();
                    
                    return Ok(result);
                }
                catch (Exception ex)
                {
                    stopwatch.Stop();
                    _logger.LogError(ex, "QR generation with logo failed with exception - RequestTime: {RequestTimeMs}ms, UserId: {UserId}", 
                        stopwatch.ElapsedMilliseconds, userId ?? "anonymous");
                    return StatusCode(500, new { error = "Erro interno do servidor", success = false });
                }
            }
        }

        [HttpGet("History")]
        public async Task<IActionResult> GetHistory(int limit = 20)
        {
            try
            {
                var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                if (string.IsNullOrEmpty(userId))
                {
                    return Unauthorized();
                }

                var history = await _userService.GetUserQRHistoryAsync(userId, limit);
                return Ok(history);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting QR history");
                return StatusCode(500);
            }
        }

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

                var user = await _userService.GetUserAsync(userId);
                var isPremium = user?.IsPremium ?? false;
                
                // For logged users (premium or not), return -1 to indicate unlimited
                // For consistency with the frontend logic
                var remainingCount = -1; // Unlimited for all logged users
                
                return Ok(new 
                { 
                    remainingCount = remainingCount,
                    isPremium = isPremium,
                    isUnlimited = true
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting user stats");
                return StatusCode(500);
            }
        }

        [HttpDelete("History/{qrId}")]
        public async Task<IActionResult> DeleteFromHistory(string qrId)
        {
            try
            {
                var userId = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
                if (string.IsNullOrEmpty(userId))
                {
                    return Unauthorized();
                }

                var success = await _userService.DeleteQRFromHistoryAsync(userId, qrId);
                
                if (success)
                {
                    _logger.LogInformation("QR code deleted from history - QRId: {QRId}, UserId: {UserId}", qrId, userId);
                    return Ok(new { success = true, message = _localizer["QRCodeDeleted"].Value });
                }
                else
                {
                    return NotFound(new { success = false, message = _localizer["ErrorDeletingQR"].Value });
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error deleting QR from history - QRId: {QRId}", qrId);
                return StatusCode(500, new { success = false, message = _localizer["ErrorDeletingQR"].Value });
            }
        }

        private async Task<bool> CheckRateLimitAsync(string? userId, Models.User? user)
        {
            // Premium users have unlimited QR codes
            if (user?.IsPremium == true) return true;
            
            // Logged users (non-premium) have unlimited QR codes
            if (userId != null) return true;

            // Anonymous users have 3 QR codes per day
            var dailyLimit = 3;
            var currentCount = await _userService.GetDailyQRCountAsync(userId);

            return currentCount < dailyLimit;
        }
    }

    public class SaveToHistoryRequest
    {
        public string QrId { get; set; } = string.Empty;
    }
}