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

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);
	}

	private static string CreateDefaultJwtToken(this AuthUser authUser)
	{
		var claims = new List<Claim>()
		{
			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 keyCloackResponse = restClient.Post(request);
		if (keyCloackResponse.IsSuccessful && !String.IsNullOrEmpty(keyCloackResponse.Content))
		{
			var token = JsonSerializer.Deserialize<JwtToken>(keyCloackResponse.Content)!;
			return token.AccessToken;
		}

		return String.Empty;
	}
}