using System.Security.Claims;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Nalu.Web.Services;

namespace Nalu.Web.Pages.Auth;

public class CallbackModel(UserService userService, ILogger<CallbackModel> logger) : PageModel
{
    public async Task<IActionResult> OnGetAsync(string? returnUrl = null)
    {
        var result = await HttpContext.AuthenticateAsync("ExternalCookie");
        if (!result.Succeeded)
        {
            logger.LogWarning("External auth failed: {Error}", result.Failure?.Message);
            return RedirectToPage("/Login");
        }

        var principal = result.Principal!;
        var provider = result.Properties?.Items[".AuthScheme"] ?? "unknown";

        var providerId = principal.FindFirstValue(ClaimTypes.NameIdentifier)
                         ?? principal.FindFirstValue("sub")
                         ?? throw new InvalidOperationException("No provider ID in claims");

        var email = principal.FindFirstValue(ClaimTypes.Email)
                    ?? principal.FindFirstValue("email")
                    ?? $"{providerId}@{provider}.oauth";

        var name = principal.FindFirstValue(ClaimTypes.Name)
                   ?? principal.FindFirstValue("name");

        var picture = principal.FindFirstValue("picture")
                      ?? principal.FindFirstValue("urn:github:avatar");

        var loginResult = await userService.LoginOrCreateAsync(
            provider.ToLowerInvariant(), providerId, email, name, picture);

        // Issue site cookie
        var claims = new List<Claim>
        {
            new(ClaimTypes.NameIdentifier, loginResult.User.Id),
            new(ClaimTypes.Email, email),
            new(ClaimTypes.Name, name ?? email),
            new("plan", loginResult.User.Plan),
            new("picture", picture ?? ""),
        };

        var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
        var cookiePrincipal = new ClaimsPrincipal(identity);

        await HttpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            cookiePrincipal,
            new AuthenticationProperties
            {
                IsPersistent = true,
                ExpiresUtc = DateTimeOffset.UtcNow.AddDays(30),
            });

        // Delete external cookie
        await HttpContext.SignOutAsync("ExternalCookie");

        // Show API key once for new users
        if (loginResult.IsNew)
            TempData["NewApiKey"] = loginResult.ApiKey.Key;

        var safeReturn = IsLocalUrl(returnUrl) ? returnUrl : "/painel";
        return Redirect(safeReturn!);
    }

    private bool IsLocalUrl(string? url) =>
        !string.IsNullOrEmpty(url) && url.StartsWith('/') && !url.StartsWith("//");
}
