namespace Fast.Shared.Logic.FileService;

/// Facade that provides a unified entry point for all file operations.
/// Delegates to the appropriate implementation (local or SharePoint) based on configuration.
/// This is the single entry point for all file operations throughout the codebase.
public class FileService : IFileService
{
    private readonly IFileService _implementation;
    private readonly FileServiceConfig _config;

    public FileService(FileServiceConfig config)
    {
        _config = config ?? throw new ArgumentNullException(nameof(config));

        if (Main.UseLocalFiles)
            _implementation = new LocalFileService(config);
        else
            _implementation = new SharePointFileService(config);
    }

    public Task<bool> FileExistsAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.FileExistsAsync(folderName, fileName, useSharding);

    public bool FileExists(string folderName, string fileName, bool useSharding = true)
        => _implementation.FileExists(folderName, fileName, useSharding);

    public Task<byte[]> ReadAllBytesAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.ReadAllBytesAsync(folderName, fileName, useSharding);

    public byte[] ReadAllBytes(string folderName, string fileName, bool useSharding = true)
        => _implementation.ReadAllBytes(folderName, fileName, useSharding);

    public Task<string> WriteAllBytesAsync(string folderName, string fileName, byte[] content, bool useSharding = true)
        => _implementation.WriteAllBytesAsync(folderName, fileName, content, useSharding);

    public string WriteAllBytes(string folderName, string fileName, byte[] content, bool useSharding = true)
        => _implementation.WriteAllBytes(folderName, fileName, content, useSharding);

    public Task<bool> DeleteFileAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.DeleteFileAsync(folderName, fileName, useSharding);

    public bool DeleteFile(string folderName, string fileName, bool useSharding = true)
        => _implementation.DeleteFile(folderName, fileName, useSharding);

    public Task CopyFileAsync(string sourceFolderName, string sourceFileName, string destFolderName, string destFileName, bool useSharding = true, bool overwrite = false)
        => _implementation.CopyFileAsync(sourceFolderName, sourceFileName, destFolderName, destFileName, useSharding, overwrite);

    public Task MoveFileAsync(string sourceFolderName, string sourceFileName, string destFolderName, string destFileName, bool useSharding = true, bool overwrite = false)
        => _implementation.MoveFileAsync(sourceFolderName, sourceFileName, destFolderName, destFileName, useSharding, overwrite);

    public Task<Stream> OpenReadAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.OpenReadAsync(folderName, fileName, useSharding);

    public Task<string> WriteStreamAsync(string folderName, string fileName, Stream content, bool useSharding = true)
        => _implementation.WriteStreamAsync(folderName, fileName, content, useSharding);

    public Task<string?> UploadFileAsync(string folderName, string fileName, IFormFile file, bool useSharding = true)
        => _implementation.UploadFileAsync(folderName, fileName, file, useSharding);

    public Task<FileDownloadResult> DownloadFileAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.DownloadFileAsync(folderName, fileName, useSharding);

    public Task<bool> DirectoryExistsAsync(string folderName, string? subFolder = null)
        => _implementation.DirectoryExistsAsync(folderName, subFolder);

    public bool DirectoryExists(string folderName, string? subFolder = null)
        => _implementation.DirectoryExists(folderName, subFolder);

    public Task<bool> CreateDirectoryAsync(string folderName, string? subFolder = null)
        => _implementation.CreateDirectoryAsync(folderName, subFolder);

    public bool CreateDirectory(string folderName, string? subFolder = null)
        => _implementation.CreateDirectory(folderName, subFolder);

    public Task<bool> DeleteDirectoryAsync(string folderName, string? subFolder = null, bool recursive = false)
        => _implementation.DeleteDirectoryAsync(folderName, subFolder, recursive);

    public bool DeleteDirectory(string folderName, string? subFolder = null, bool recursive = false)
        => _implementation.DeleteDirectory(folderName, subFolder, recursive);

    public Task<IReadOnlyList<string>> GetFilesAsync(string folderName, string? subFolder = null, string searchPattern = "*", bool recursive = false)
        => _implementation.GetFilesAsync(folderName, subFolder, searchPattern, recursive);

    public Task<IReadOnlyList<FileItemInfo>> GetFilesWithInfoAsync(string folderName, string? subFolder = null, string searchPattern = "*", bool recursive = false)
        => _implementation.GetFilesWithInfoAsync(folderName, subFolder, searchPattern, recursive);

    public Task<IReadOnlyList<string>> GetDirectoriesAsync(string folderName, string? subFolder = null)
        => _implementation.GetDirectoriesAsync(folderName, subFolder);

    public Task<IReadOnlyList<BatchOperationResult>> WriteAllFilesBatchedAsync(IEnumerable<(string folderName, string fileName, byte[] content)> files, bool useSharding = true, int maxDegreeOfParallelism = 4)
        => _implementation.WriteAllFilesBatchedAsync(files, useSharding, maxDegreeOfParallelism);

    public Task<IReadOnlyList<BatchOperationResult>> DeleteFilesBatchedAsync(IEnumerable<(string folderName, string fileName)> files, bool useSharding = true, int maxDegreeOfParallelism = 4)
        => _implementation.DeleteFilesBatchedAsync(files, useSharding, maxDegreeOfParallelism);

    public Task<FileItemInfo?> GetFileInfoAsync(string folderName, string fileName, bool useSharding = true)
        => _implementation.GetFileInfoAsync(folderName, fileName, useSharding);

    public string GetShardFolderName(string fileName)
        => _implementation.GetShardFolderName(fileName);

    public string ResolvePath(string folderName, string fileName, bool useSharding = true)
        => _implementation.ResolvePath(folderName, fileName, useSharding);
}
