using Blazored.LocalStorage;
using decePubClient.Models;
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Text.Json;

namespace decePubClient.Services
{
	public class TokenAuthStateProvider : AuthenticationStateProvider
	{
		readonly ILocalStorageService Storage;
		readonly IStorage DbStorage;
		readonly ILogger<TokenAuthStateProvider> Logger;
		AuthData AuthData { get; set; }

		public TokenAuthStateProvider(ILocalStorageService storage,
			IStorage dbStorage,
			ILogger<TokenAuthStateProvider> logger)
		{
			Storage = storage;
			DbStorage = dbStorage;
			Logger = logger;
		}

		public void SetToken(/*string token, long expirationTicks = default*/)
		{
			//AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
			//if (string.IsNullOrEmpty(token))
			//{
			//	Logger.LogInformation($"set null({nameof(SetToken)})");
			//	AuthData.Token = null;
			//	AuthData.TokenExpiration = null;
			//}
			//else
			//{
			//	AuthData.Token = token;
			//	AuthData.TokenExpiration = expirationTicks;
			//}
			//await Storage.SetItemAsync(nameof(AuthData), AuthData);

			NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
		}

		public async ValueTask<bool> IsAuthenticatedAsync()
		{
			AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
			if (AuthData is null)
			{
				AuthData = new();
				await Storage.SetItemAsync(nameof(AuthData), AuthData);
			}
			return AuthData.Token != null &&
				AuthData.TokenExpiration.HasValue &&
				AuthData.TokenExpiration.Value > DateTime.UtcNow.Ticks;
		}

		public async Task LogoutAsync(bool deleteDb = false)
		{
			Logger.LogInformation($"set null({nameof(LogoutAsync)})");
			//await Storage.RemoveItemAsync(nameof(PrivateCacheData));
			await Storage.RemoveItemAsync(nameof(AuthData));
			if (deleteDb)
				await DbStorage.RemoveAll(includeClientLogs: true);

			NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
		}

		public override async Task<AuthenticationState> GetAuthenticationStateAsync()
		{
			AuthData = await Storage.GetItemAsync<AuthData>(nameof(AuthData));
			if (string.IsNullOrEmpty(AuthData?.Token))
			{
				Logger.LogInformation($"set null({nameof(GetAuthenticationStateAsync)})");
				return new(new());
			}
			var claims = new List<Claim>
			{
				new(ClaimTypes.UserData, JsonSerializer.Serialize(AuthData.User))
			};

			//claims.Add(new(Policies.IsUser, (AuthData.User.Policies.Contains(Policies.IsUser)).ToString().ToLower()));
			//claims.Add(new(Policies.UserPlus, (AuthData.User.Policies.Contains(Policies.UserPlus)).ToString().ToLower()));
			//claims.Add(new(Policies.IsAdmin, (AuthData.User.Policies.Contains(Policies.IsAdmin)).ToString().ToLower()));

			var identity = new ClaimsIdentity(claims, "jwt");
			return new(new(identity));
		}
	}
}
