using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Tokens;
using Persistence.Models.Configurations;
using RestSharp;
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Json;

namespace Persistence.Client.Helpers;
public static class ApiTokenHelper
{
    public static void Authorize(this HttpClient httpClient, IConfiguration configuration)
    {
        var authUser = configuration
            .GetSection(nameof(AuthUser))
            .Get<AuthUser>()!;
        var needUseKeyCloak = configuration
            .GetSection("NeedUseKeyCloak")
            .Get<bool>()!;
        var keycloakGetTokenUrl = configuration.GetSection("KeycloakGetTokenUrl").Get<string>() ?? string.Empty;

        var jwtToken = needUseKeyCloak
            ? authUser.CreateKeyCloakJwtToken(keycloakGetTokenUrl)
            : authUser.CreateDefaultJwtToken();

        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
    }

	public static void Authorize(this HttpClient httpClient, string jwtToken)
	{
		httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
	}

	private static string CreateDefaultJwtToken(this AuthUser authUser)
	{
		var nameIdetifier = Guid.NewGuid().ToString();
		var claims = new List<Claim>()
		{
			new(ClaimTypes.NameIdentifier, nameIdetifier),
			new("client_id", authUser.ClientId),
			new("username", authUser.Username),
			new("password", authUser.Password),
			new("grant_type", authUser.GrantType),
			new(ClaimTypes.NameIdentifier.ToString(), Guid.NewGuid().ToString())
		};

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Issuer = JwtParams.Issuer,
            Audience = JwtParams.Audience,
            Subject = new ClaimsIdentity(claims),
            Expires = DateTime.UtcNow.AddHours(1),
            SigningCredentials = new SigningCredentials(JwtParams.SecurityKey, SecurityAlgorithms.HmacSha256Signature)
        };
        var tokenHandler = new JwtSecurityTokenHandler();
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }

    private static string CreateKeyCloakJwtToken(this AuthUser authUser, string keycloakGetTokenUrl)
    {
        var restClient = new RestClient();

        var request = new RestRequest(keycloakGetTokenUrl, Method.Post);
        request.AddParameter("username", authUser.Username);
        request.AddParameter("password", authUser.Password);
        request.AddParameter("client_id", authUser.ClientId);
        request.AddParameter("grant_type", authUser.GrantType);

        var keycloakResponse = restClient.Post(request);
        if (keycloakResponse.IsSuccessful && !String.IsNullOrEmpty(keycloakResponse.Content))
        {
            var token = JsonSerializer.Deserialize<JwtToken>(keycloakResponse.Content)!;
            return token.AccessToken;
        }

        return String.Empty;
    }
}