using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;

namespace WebApp.Authentication
{
    public class AuthController : Controller
    {
        private readonly AuthenticationService _authService;
        private readonly LoginRateLimitService _rateLimitService;
        private readonly ILogger<AuthController> _logger;

        public AuthController(
            AuthenticationService authService,
            LoginRateLimitService rateLimitService,
            ILogger<AuthController> logger)
        {
            _authService = authService;
            _rateLimitService = rateLimitService;
            _logger = logger;
        }

        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> CookieLogin(
            [FromForm] string email,
            [FromForm] string password,
            [FromForm] bool rememberMe = false)
        {
            try
            {
                // Get client IP
                var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";

                // Check rate limiting
                if (_rateLimitService.IsLockedOut(ipAddress))
                {
                    var remaining = _rateLimitService.GetRemainingLockoutTime(ipAddress);
                    _logger.LogWarning(
                        "Login attempt from locked out IP: {IpAddress}. Remaining: {Remaining}",
                        ipAddress, remaining);

                    var errorMsg = Uri.EscapeDataString($"Too many failed attempts. Try again in {remaining?.Minutes ?? 15} minutes.");
                    return Redirect($"/login?error={errorMsg}");
                }

                // Validate credentials
                var result = _authService.ValidateCredentials(email, password);

                if (!result.IsSuccess)
                {
                    // Record failed attempt
                    _rateLimitService.RecordFailedAttempt(ipAddress);

                    _logger.LogWarning(
                        "Failed login attempt for {Email} from {IpAddress}",
                        email, ipAddress);

                    return Redirect("/login?error=Invalid%20email%20or%20password.");
                }

                // Success - clear rate limit tracking
                _rateLimitService.RecordSuccessfulLogin(ipAddress);

                // Create claims
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, result.DisplayName!),
                    new Claim(ClaimTypes.Email, result.Email!),
                    new Claim(ClaimTypes.Role, result.Role!)
                };

                var claimsIdentity = new ClaimsIdentity(claims, "Auth");
                var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

                // Configure auth properties
                var authProperties = new AuthenticationProperties
                {
                    IsPersistent = rememberMe,
                    ExpiresUtc = rememberMe
                        ? DateTimeOffset.UtcNow.AddDays(30)
                        : DateTimeOffset.UtcNow.AddMinutes(20)
                };

                await HttpContext.SignInAsync("Auth", claimsPrincipal, authProperties);

                _logger.LogInformation(
                    "Successful login for {Email} ({Role}) from {IpAddress}",
                    result.Email, result.Role, ipAddress);

                return Redirect("/");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error during login process");
                TempData["LoginError"] = "An error occurred. Please try again.";
                return Redirect("/login");
            }
        }

        [HttpPost]
        [Authorize]
        public async Task<IActionResult> CookieLogout()
        {
            var userEmail = User.FindFirst(ClaimTypes.Email)?.Value;

            await HttpContext.SignOutAsync("Auth");

            _logger.LogInformation("User {Email} logged out", userEmail);

            return Redirect("/login");
        }
    }
}
