using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;

namespace Fast.Shared.Controllers;

[ApiController]
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
    [HttpGet("Login")]
    [AllowAnonymous]
    public IActionResult Login(string? returnUrl = "/")
    {
        if (!ProgramShared.IsAuthenticationEnabled)
            return Redirect(returnUrl ?? "/");

        if (string.IsNullOrEmpty(returnUrl))
            returnUrl = "/";

        var properties = new AuthenticationProperties
        {
            RedirectUri = returnUrl,
            IsPersistent = true,
            ExpiresUtc = DateTime.UtcNow.AddDays(ProgramShared.AuthExpirationDays)
        };

        var loginHint = Request.Cookies[ProgramShared.LoginHintCookieName];
        if (!string.IsNullOrEmpty(loginHint))
        {
            properties.Items["login_hint"] = loginHint;
        }

        return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme);
    }

    [HttpGet("CheckCookieStatus")]
    [AllowAnonymous]  // Changed from [Authorize] to allow unauthenticated requests to get a proper response
    public IActionResult CheckCookieStatus()
    {
        // Return 200 OK with authentication status instead of 401 for unauthenticated users
        // This prevents the Angular app from treating "not logged in" as an error
        if (!ProgramShared.IsAuthenticationEnabled)
        {
            return Ok(new
            {
                message = "Cookie is valid.",
                userName = "System",
                isAuthenticated = true
            });
        }

        var isAuthenticated = User.Identity?.IsAuthenticated ?? false;
        return Ok(new
        {
            message = isAuthenticated ? "Cookie is valid." : "Not authenticated.",
            userName = isAuthenticated ? User.Identity?.Name : null,
            isAuthenticated = isAuthenticated
        });
    }

    [HttpGet("Logout")]
    [AllowAnonymous]
    public async Task<IActionResult> Logout(string? redirectUri = null)
    {
        DeleteCookies();

        var appUser = await UserSynchronizationService.FindAppUserByEntraEmailsAsync(User);
        ProgramShared.WriteMessage($"User '{appUser?.Email ?? string.Empty}' cookies cleared and initiating OIDC signout.");

        var postLogoutRedirectUri = string.IsNullOrEmpty(redirectUri) ? "/" : redirectUri;

        var idToken = User.FindFirst("id_token")?.Value;

        var db = Main.CreateContext();
        var appSettings = db.AppSettings.AsNoTracking().ToList();
        string? GetValue(string name) => appSettings.FirstOrDefault(x => x.Name == name)?.Value;

        var tenantId = GetValue("AzureAd-TenantId") ?? GetValue("Graph-TenantID");

        var aadLogoutUrl = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/logout";

        var aadLogoutUrlWithParams = $"{aadLogoutUrl}" +
                                     $"?post_logout_redirect_uri={Uri.EscapeDataString(postLogoutRedirectUri)}";

        if (!string.IsNullOrEmpty(idToken))
        {
            aadLogoutUrlWithParams += $"&id_token_hint={Uri.EscapeDataString(idToken)}";
        }

        if (!string.IsNullOrEmpty(idToken))
        {
            var loginLiveLogoutUrl = $"https://login.live.com/logout.srf?id=12&ru={Uri.EscapeDataString(aadLogoutUrlWithParams)}";
            return Redirect(loginLiveLogoutUrl);
        }

        // Fallback if no ID token found
        return Redirect(aadLogoutUrlWithParams);
    }

    private void DeleteCookies()
    {
        var rootDomain = ProgramShared.GetRootDomain(HttpContext.Request.Host);
        var cookieOptions = new CookieOptions
        {
            HttpOnly = true,
            Secure = true,
            SameSite = SameSiteMode.Lax,
            Domain = rootDomain
        };

        var cookieNames = new[] {
            ProgramShared.FastAppBffCookieName,
            ProgramShared.FastAppBffCookieName + "C1",
            ProgramShared.FastAppBffCookieName + "C2",
            ProgramShared.FastAppBffCookieName + "C3"
        };
        foreach (var cookieName in cookieNames)
        {
            Response.Cookies.Delete(cookieName, cookieOptions);
        }
    }
}
