using Core.Enumerations;
using DataProviders;
using DataProviders.Collections;
using DomainObjects.Enumerations;
using FileSecurityService;
using Microsoft.AspNetCore.Authorization;
using WeatherForecast.Policies.Abstractions;
using WeatherForecast.Services;

namespace WeatherForecast.Policies;

/// <summary>
/// 
/// </summary>
public class FileAuthorisationHandler : AuthorizationHandlerBase<FileAuthorisationRequirement, List<BucketFile>> {


  private readonly IFileSecurityService _fileSecurityService;

  /// <summary>
  /// 
  /// </summary>
  /// <param name="contextAccessor"></param>
  /// <param name="userDataProvider"></param>
  /// <param name="accountService"></param>
  /// <param name="fileSecurityService"></param>
  public FileAuthorisationHandler(
    IHttpContextAccessor contextAccessor,
    IUserDataProvider userDataProvider,
    IAccountPolicyService accountService,
    IFileSecurityService fileSecurityService
  ) : base(contextAccessor, userDataProvider, accountService) {
    _fileSecurityService = fileSecurityService;
  }

  /// <summary>
  /// 
  /// </summary>
  /// <param name="context"></param>
  /// <param name="requirement"></param>
  /// <param name="resource"></param>
  /// <returns></returns>
  /// <exception cref="NotImplementedException"></exception>
  protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FileAuthorisationRequirement requirement, List<BucketFile> resource) {

    var user = GetUser(context);
    if (user == null)
      return Task.CompletedTask;

    if (resource.Any(x => {
      var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(x.Name, x.Bytes, x.ContentType);
      return !signatureResult.IsSuccess || fileCategory == null;
    }))
      return Task.CompletedTask;

    // Can Admin, Editor, Author, Contributor, Shop manager
    if (requirement.Action == CrudActions.Create
    && user.Role != Roles.Admin
    && user.Role != Roles.Editor
    && user.Role != Roles.Author
    && user.Role != Roles.Contributor
    && user.Role != Roles.ShopManager)
      return Task.CompletedTask;


    // Can Admin, Editor, Author (own), Contributor (own), Shop manager
    if (requirement.Action == CrudActions.Read
    && (user.Role != Roles.Admin
    && user.Role != Roles.Editor
    && user.Role != Roles.Author
    && user.Role != Roles.Contributor
    && user.Role != Roles.ShopManager
    && ((user.Role == Roles.Author || user.Role == Roles.Contributor) && resource.Any(x => x.UserId != user.Id))))
      return Task.CompletedTask;

    // Can Admin, Editor, Author (own), Contributor (own, not yet pubblished), Shop manager
    if ((requirement.Action == CrudActions.Update || requirement.Action == CrudActions.Delete)
    && (user.Role != Roles.Admin
    && user.Role != Roles.Editor
    && user.Role != Roles.Author
    && user.Role != Roles.Contributor
    && user.Role != Roles.ShopManager
    && ((user.Role == Roles.Author || user.Role == Roles.Contributor) && resource.Any(x => x.UserId != user.Id))
    && (user.Role == Roles.Contributor && resource.Any(x => x.Published != null))))
      return Task.CompletedTask;

    context.Succeed(requirement);

    return Task.CompletedTask;
  }
}

/// <summary>
/// 
/// </summary>
public class FileAuthorisationRequirement : AuthorizationRequirementBase { }

