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

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

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

    public override string AuthenticationSchemeName => GiteeAuthenticationDefaults.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("code", code)
        };
        var tokenModel =
            await SendHttpRequestAsync<GiteeAuthticationcationTokenResponse>(GiteeAuthenticationDefaults.TokenEndpoint,
                tokenQueryKv, HttpMethod.Post);

        // 获取 userInfo
        var userInfoQueryKv = new List<KeyValuePair<string, string?>>
        {
            new("access_token", tokenModel.access_token),
        };

        var userInfoModel =
            await SendHttpRequestAsync<GiteeAuthticationcationUserInfoResponse>(
                GiteeAuthenticationDefaults.UserInformationEndpoint, userInfoQueryKv);

        List<Claim> claims =
        [
            new(Claims.AvatarUrl, userInfoModel.avatar_url),
            new(Claims.Url, userInfoModel.url),

            new(AuthenticationConstants.OpenId, userInfoModel.id.ToString()),
            new(AuthenticationConstants.Name, userInfoModel.name),
            new(AuthenticationConstants.AccessToken, tokenModel.access_token)
        ];
        return claims;
    }
}