using DomainObjects;
using DataProviders.Collections;
using DomainObjects.Documents;
using ExtensionMethods;
using Extensions;
using Microsoft.AspNetCore.Authorization;
using WeatherForecast.Services;

namespace WeatherForecast.Policies.Abstractions;

/// <summary>
/// 
/// </summary>
/// <typeparam name="TRequirement"></typeparam>
public abstract class AuthorizationHandlerBase<TRequirement> : AuthorizationHandler<TRequirement> where TRequirement : IAuthorizationRequirement {

  private readonly IHttpContextAccessor _contextAccessor;
  private readonly IUserDataProvider _userDataProvider;
  private readonly IAccountPolicyService _accountService;

  /// <summary>
  /// 
  /// </summary>
  /// <param name="contextAccessor"></param>
  /// <param name="userDataProvider"></param>
  /// <param name="accountService"></param>
  public AuthorizationHandlerBase(
    IHttpContextAccessor contextAccessor,
    IUserDataProvider userDataProvider,
    IAccountPolicyService accountService
  ) {
    _contextAccessor = contextAccessor;
    _userDataProvider = userDataProvider;
    _accountService = accountService;
  }

  /// <summary>
  /// 
  /// </summary>
  /// <param name="context"></param>
  /// <returns></returns>
  protected UserDocument? GetUser(AuthorizationHandlerContext context) {

    if (context == null)
      return null;

    var userId = context.User?.Identity?.Name?.ToNullableGuid();
    var bearerToken = _contextAccessor.HttpContext?.Request?.GeBearerToken();

    if (userId == null || bearerToken == null)
      return null;

    var (user, getUserResult) = _userDataProvider.Get(userId.Value);
    if (!getUserResult.IsSuccess || user == null)
      return null;

    if (!_accountService.Authenticate(user, bearerToken).IsSuccess)
      return null;

    return user;
  }
}

/// <summary>
/// 
/// </summary>
/// <typeparam name="TRequirement"></typeparam>
/// <typeparam name="TResource"></typeparam>
public abstract class AuthorizationHandlerBase<TRequirement, TResource> : AuthorizationHandler<TRequirement, TResource> where TRequirement : IAuthorizationRequirement {

  private readonly IHttpContextAccessor _contextAccessor;
  private readonly IUserDataProvider _userDataProvider;
  private readonly IAccountPolicyService _accountService;

  /// <summary>
  /// 
  /// </summary>
  /// <param name="contextAccessor"></param>
  /// <param name="userDataProvider"></param>
  /// <param name="accountService"></param>
  public AuthorizationHandlerBase(
    IHttpContextAccessor contextAccessor,
    IUserDataProvider userDataProvider,
    IAccountPolicyService accountService
  ) {
    _contextAccessor = contextAccessor;
    _userDataProvider = userDataProvider;
    _accountService = accountService;
  }

  /// <summary>
  ///                        
  /// </summary>
  /// <param name="context"></param>
  /// <returns></returns>
  protected UserDocument? GetUser(AuthorizationHandlerContext context) {

    if (context == null)
      return null;

    var userId = context.User?.Identity?.Name?.ToNullableGuid();
    var bearerToken = _contextAccessor.HttpContext?.Request?.GeBearerToken();

    if (userId == null || bearerToken == null)
      return null;

    var (user, getUserResult) = _userDataProvider.Get(userId.Value);
    if (!getUserResult.IsSuccess || user == null)
      return null;

    if (!_accountService.Authenticate(user, bearerToken).IsSuccess)
      return null;

    return user;
  }
}
