using Fengling.AuthService.Data;
using Fengling.AuthService.Models;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using static OpenIddict.Abstractions.OpenIddictConstants;
using System.Linq;

namespace Fengling.AuthService.Controllers;

[ApiController]
[Route("connect")]
public class LogoutController : ControllerBase
{
    private readonly IOpenIddictApplicationManager _applicationManager;
    private readonly IOpenIddictAuthorizationManager _authorizationManager;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly ILogger<LogoutController> _logger;

    public LogoutController(
        IOpenIddictApplicationManager applicationManager,
        IOpenIddictAuthorizationManager authorizationManager,
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        ILogger<LogoutController> logger)
    {
        _applicationManager = applicationManager;
        _authorizationManager = authorizationManager;
        _userManager = userManager;
        _signInManager = signInManager;
        _logger = logger;
    }

    [HttpGet("endsession")]
    [HttpPost("endsession")]
    [IgnoreAntiforgeryToken]
    public async Task<IActionResult> EndSession()
    {
        var request = HttpContext.GetOpenIddictServerRequest() ??
                      throw new InvalidOperationException("OpenIddict request is null");

        // 标准做法：先尝试从 id_token_hint 中提取客户端信息
        string? clientId = request.ClientId;
        
        if (string.IsNullOrEmpty(clientId) && !string.IsNullOrEmpty(request.IdTokenHint))
        {
            try
            {
                // 从 id_token_hint 中提取 client_id (azp claim 或 aud claim)
                var principal = (await HttpContext.AuthenticateAsync(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme)).Principal;
                if (principal != null)
                {
                    // 尝试从 azp (authorized party) claim 获取
                    clientId = principal.GetClaim(Claims.AuthorizedParty);
                    
                    // 如果没有 azp，尝试从 aud (audience) claim 获取
                    if (string.IsNullOrEmpty(clientId))
                    {
                        clientId = principal.GetClaim(Claims.Audience);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to extract client_id from id_token_hint");
            }
        }

        // 执行登出
        var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
        if (result.Succeeded)
        {
            await _signInManager.SignOutAsync();
        }

        // 处理 post_logout_redirect_uri
        if (!string.IsNullOrEmpty(clientId))
        {
            var application = await _applicationManager.FindByClientIdAsync(clientId);
            if (application != null)
            {
                var registeredUris = await _applicationManager.GetPostLogoutRedirectUrisAsync(application);
                
                // 如果提供了 post_logout_redirect_uri，验证它是否在注册的 URI 列表中
                if (!string.IsNullOrEmpty(request.PostLogoutRedirectUri))
                {
                    if (registeredUris.Contains(request.PostLogoutRedirectUri))
                    {
                        // 如果提供了 state，需要附加到重定向 URI
                        var redirectUri = request.PostLogoutRedirectUri;
                        if (!string.IsNullOrEmpty(request.State))
                        {
                            var separator = redirectUri.Contains('?') ? "&" : "?";
                            redirectUri = $"{redirectUri}{separator}state={Uri.EscapeDataString(request.State)}";
                        }
                        
                        return Redirect(redirectUri);
                    }
                    else
                    {
                        _logger.LogWarning(
                            "Post-logout redirect URI {Uri} is not registered for client {ClientId}",
                            request.PostLogoutRedirectUri,
                            clientId);
                    }
                }
                else
                {
                    // 如果没有提供 post_logout_redirect_uri，使用第一个注册的 URI
                    var defaultUri = registeredUris.FirstOrDefault();
                    if (!string.IsNullOrEmpty(defaultUri))
                    {
                        _logger.LogInformation(
                            "Using default post-logout redirect URI for client {ClientId}",
                            clientId);
                        return Redirect(defaultUri);
                    }
                }
            }
        }
        
        // 如果无法确定重定向地址，返回默认页面
        return Redirect("/");
    }
}
