using DomainResults.Common;

using DataProviders;
using DataProviders.Buckets;

using FileSecurityService;
using Core.Abstractions;

namespace WeatherForecast.Services {

  /// <summary>
  /// 
  /// </summary>
  public interface IFilesService {

    /// <summary>
    /// 
    /// </summary>
    /// <param name="siteId"></param>
    /// <param name="userId"></param>
    /// <param name="files"></param>
    /// <returns></returns>
    (List<Guid>?, IDomainResult) Post(Guid siteId, Guid userId, List<IFormFile> files);

    /// <summary>
    /// 
    /// </summary>
    /// <param name="siteId"></param>
    /// <param name="userId"></param>
    /// <returns></returns>
    IDomainResult Delete(Guid siteId, Guid userId);
  }

  /// <summary>
  /// 
  /// </summary>
  public class FilesService : ServiceBase<FilesService>, IFilesService {

    private readonly IFileSecurityService _fileSecurityService;
    private readonly IImageBucketDataProvider _imageBucketDataProvider;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="logger"></param>
    /// <param name="imageBucketDataProvider"></param>
    public FilesService(
      ILogger<FilesService> logger,
      IFileSecurityService fileSecurityService,
      IImageBucketDataProvider imageBucketDataProvider
    ) : base(logger) {
      _fileSecurityService = fileSecurityService;
      _imageBucketDataProvider = imageBucketDataProvider;
    }

    /// <summary>
    /// Process uploaded files
    /// </summary>
    /// <param name="siteId"></param>
    /// <param name="userId"></param>
    /// <param name="files"></param>
    /// <returns></returns>
    public (List<Guid>?, IDomainResult) Post(Guid siteId, Guid userId, List<IFormFile> files) {
      try {
        // Don't rely on or trust the FileName property without validation.

        if(files.Any(x => !(x.Length > 0)))
          return IDomainResult.Failed<List<Guid>?>();

        var newFiles = new List<BucketFile>();
        foreach (var formFile in files) {
          using var ms = new MemoryStream();
          formFile.CopyTo(ms);
          var bytes = ms.ToArray();

          var (fileCategory, signatureResult) = _fileSecurityService.CheckFileSignature(formFile.FileName, bytes, formFile.ContentType);
          if (!signatureResult.IsSuccess || fileCategory == null)
            return IDomainResult.Failed<List<Guid>?>();

          var bucketFile = new BucketFile(formFile.FileName, bytes, formFile.ContentType);

          newFiles.Add(bucketFile);
        }

        var (list, result) = _imageBucketDataProvider.UploadMany(siteId, userId, newFiles);

        if (!result.IsSuccess || list == null)
          return IDomainResult.Failed<List<Guid>?>();

        return IDomainResult.Success(list);
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed<List<Guid>?> (ex.Message);
      }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="siteId"></param>
    /// <param name="userId"></param>
    /// <returns></returns>
    public IDomainResult Delete(Guid siteId, Guid userId) {
      try {
        return _imageBucketDataProvider.DeletMany(siteId, userId);
      }
      catch (Exception ex) {
        _logger.LogError(ex, "Unhandled exception");
        return IDomainResult.Failed(ex.Message);
      }
    }
  }
}
