using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StorageService.Domain.AggregatesModel.FileAggregate;
using StorageService.Infrastructure.Configuration;

namespace StorageService.Infrastructure.Storage;

/// <summary>
/// EN: Factory to create and select storage providers based on configuration.
/// VI: Factory để tạo và chọn storage provider dựa trên cấu hình.
/// </summary>
public interface IStorageProviderFactory
{
    /// <summary>
    /// EN: Get the currently configured storage provider.
    /// VI: Lấy storage provider đang được cấu hình.
    /// </summary>
    IStorageProvider GetProvider();
    
    /// <summary>
    /// EN: Get a specific storage provider by type.
    /// VI: Lấy storage provider theo loại.
    /// </summary>
    IStorageProvider GetProvider(StorageProvider providerType);
}

/// <summary>
/// EN: Implementation of storage provider factory.
/// VI: Implementation của storage provider factory.
/// </summary>
public class StorageProviderFactory : IStorageProviderFactory
{
    private readonly IServiceProvider _serviceProvider;
    private readonly StorageSettings _settings;
    private readonly ILogger<StorageProviderFactory> _logger;

    public StorageProviderFactory(
        IServiceProvider serviceProvider,
        IOptions<StorageSettings> settings,
        ILogger<StorageProviderFactory> logger)
    {
        _serviceProvider = serviceProvider;
        _settings = settings.Value;
        _logger = logger;
    }

    /// <inheritdoc />
    public IStorageProvider GetProvider()
    {
        var providerType = _settings.Provider.ToLowerInvariant() switch
        {
            "minio" => StorageProvider.MinIO,
            "aliyun" or "aliyunoss" => StorageProvider.AliyunOSS,
            _ => throw new InvalidOperationException($"Unknown storage provider: {_settings.Provider}")
        };

        return GetProvider(providerType);
    }

    /// <inheritdoc />
    public IStorageProvider GetProvider(StorageProvider providerType)
    {
        _logger.LogDebug("Getting storage provider: {ProviderType}", providerType);

        return providerType switch
        {
            StorageProvider.MinIO => 
                (IStorageProvider)_serviceProvider.GetService(typeof(MinioStorageProvider))!,
            StorageProvider.AliyunOSS => 
                (IStorageProvider)_serviceProvider.GetService(typeof(AliyunOssStorageProvider))!,
            _ => throw new InvalidOperationException($"Unsupported storage provider: {providerType}")
        };
    }
}
