using System.Security.Claims;
using System.Text.Encodings.Web;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using static NPin.Framework.AspNetCore.Authentication.OAuth.QQ.QQAuthenticationConstants;

namespace NPin.Framework.AspNetCore.Authentication.OAuth.QQ;

public class QQAuthenticationHandler : OAuthAuthenticationHandler<QQAuthenticationOptions>
{
    public QQAuthenticationHandler(IOptionsMonitor<QQAuthenticationOptions> options, ILoggerFactory logger,
        UrlEncoder encoder, IHttpClientFactory httpClientFactory) :
        base(options, logger, encoder, httpClientFactory)
    {
    }

    public override string AuthenticationSchemeName => QQAuthenticationDefaults.AuthenticationScheme;

    protected override async Task<List<Claim>> GetAuthTicketAsync(string code)
    {
        // 获取 AccessToken
        var tokenQueryKv = new List<KeyValuePair<string, string?>>
        {
            new("grant_type", "authorization_code"),
            new("client_id", Options.ClientId),
            new("client_secret", Options.ClientSecret),
            new("redirect_uri", Options.RedirectUri),
            new("fmt", "json"),
            new("need_openid", "1"),
            new("code", code)
        };
        var tokenModel =
            await SendHttpRequestAsync<QQAuthticationcationTokenResponse>(QQAuthenticationDefaults.TokenEndpoint,
                tokenQueryKv);

        // 获取 userinfo
        var userInfoQueryKv = new List<KeyValuePair<string, string?>>
        {
            new("access_token", tokenModel.access_token),
            new("oauth_consumer_key", Options.ClientId),
            new("openid", tokenModel.openid),
        };

        var userInfoModel =
            await SendHttpRequestAsync<QQAuthticationcationUserInfoResponse>(
                QQAuthenticationDefaults.UserInformationEndpoint, userInfoQueryKv);

        // 组装 claims
        var claims = new List<Claim>
        {
            new(Claims.AvatarFullUrl, userInfoModel.figureurl_qq_2),
            new(Claims.AvatarUrl, userInfoModel.figureurl_qq_1),
            new(Claims.PictureFullUrl, userInfoModel.figureurl_2),
            new(Claims.PictureMediumUrl, userInfoModel.figureurl_qq_1),
            new(Claims.PictureUrl, userInfoModel.figureurl),

            new(AuthenticationConstants.OpenId, tokenModel.openid),
            new(AuthenticationConstants.Name, userInfoModel.nickname),
            new(AuthenticationConstants.AccessToken, tokenModel.access_token),
        };

        return claims;
    }
}