using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Security.Claims;
using QuantEngine.Web.Services;

namespace QuantEngine.Web.Pages.Account;

[AllowAnonymous]
public class LoginModel : PageModel
{
    private readonly AuthService _authService;
    private readonly IIpLockoutService _lockoutService;
    private readonly ILogger<LoginModel> _logger;

    public string? Username { get; set; }
    public bool RememberUsername { get; set; }
    public string? ErrorMessage { get; set; }

    public LoginModel(AuthService authService, IIpLockoutService lockoutService, ILogger<LoginModel> logger)
    {
        _authService = authService;
        _lockoutService = lockoutService;
        _logger = logger;
    }

    public void OnGet()
    {
        if (Request.Cookies.TryGetValue("quant_admin_username", out var savedUsername))
        {
            Username = savedUsername;
            RememberUsername = true;
        }
    }

    public async Task<IActionResult> OnPostAsync(string username, string password, bool rememberUsername)
    {
        if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
        {
            ErrorMessage = "아이디와 비밀번호를 모두 입력해 주세요.";
            Username = username;
            RememberUsername = rememberUsername;
            return Page();
        }

        var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown";

        var account = await _authService.AuthenticateAsync(username, password, ipAddress);
        if (account is null)
        {
            if (_lockoutService.IsLockedOut(ipAddress))
                ErrorMessage = "로그인 시도 횟수를 초과했습니다. 15분 후에 다시 시도해 주세요.";
            else
                ErrorMessage = "아이디 또는 비밀번호가 올바르지 않습니다.";

            Username = username;
            RememberUsername = rememberUsername;
            return Page();
        }

        var claims = new List<Claim>
        {
            new(ClaimTypes.NameIdentifier, account.Username),
            new(ClaimTypes.Name, account.Username),
            new(ClaimTypes.Role, account.Role ?? "Admin")
        };

        var identity = new ClaimsIdentity(claims, AdminAuthDefaults.Scheme);
        var principal = new ClaimsPrincipal(identity);

        var properties = new Microsoft.AspNetCore.Authentication.AuthenticationProperties
        {
            IsPersistent = true,
            ExpiresUtc = DateTimeOffset.UtcNow.AddHours(12)
        };

        await HttpContext.SignInAsync(AdminAuthDefaults.Scheme, principal, properties);

        if (rememberUsername)
        {
            Response.Cookies.Append(
                "quant_admin_username",
                username,
                new Microsoft.AspNetCore.Http.CookieOptions
                {
                    Expires = DateTimeOffset.UtcNow.AddDays(30),
                    HttpOnly = false,
                    SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict
                }
            );
        }
        else
        {
            Response.Cookies.Delete("quant_admin_username");
        }

        _logger.LogInformation("[Login] User '{Username}' authenticated successfully from {IpAddress}", account.Username, ipAddress);
        return LocalRedirect("/Admin/Dashboard");
    }
}
