namespace HiVakil.Infrastructure.Services;

public class StorageService : IStorageService
{
    private IAmazonS3? _s3Client;
    private string _bucketName = "vesmeh-content";
    private readonly StorageSetting _storageSettings;

    public StorageService(IOptionsSnapshot<SiteSettings> snapshot)
    {
        _storageSettings = snapshot.Value.StorageSetting;
    }
    private IAmazonS3 GetClientAsync()
    {
        var awsCredentials = new Amazon.Runtime.BasicAWSCredentials(_storageSettings.AccessKey, _storageSettings.SecretKey);
        var config = new AmazonS3Config { ServiceURL = "https://s3.ir-thr-at1.arvanstorage.ir" };
        _s3Client = new AmazonS3Client(awsCredentials, config);
        return _s3Client;
    }

    public async Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, byte[] fileBytes)
    {
        using var memorySteam = new MemoryStream(fileBytes);

        var client = GetClientAsync();

        var fileEx = fileName.Split('.').Last();
        fileName = fileName.Split('.').First();

        fileName = fileName + "_" + StringExtensions.GetId(5) + "_" + DateTime.Today.ToString("yyyy-MM-dd-HH-mm-ss") + "." + fileEx;

        var putRequest = new PutObjectRequest
        {
            BucketName = _bucketName,
            Key = Path.Combine(filePath, fileName),
            ContentType = contentType,
            InputStream = memorySteam,
            CannedACL = S3CannedACL.PublicRead
        };

        putRequest.Metadata.Add("x-amz-meta-title", fileName);

        PutObjectResponse response = await client.PutObjectAsync(putRequest);

        return fileName;
    }

    public async Task<string> UploadObjectFromFileAsync(string fileName, string filePath, string contentType, Stream fileStream , bool fixName = true)
    {

        var client = GetClientAsync();

        if (fixName)
        {
            var fileEx = fileName.Split('.').Last();
            fileName = fileName.Split('.').First();

            fileName = fileName + "_" + StringExtensions.GetId(5) + "_" + DateTimeExtensions.DateTimeToUnixTimeStamp(DateTime.Now) + "." + fileEx;
        }

        var putRequest = new PutObjectRequest
        {
            BucketName = _bucketName,
            Key = Path.Combine(filePath, fileName),
            ContentType = contentType,
            InputStream = fileStream,
            CannedACL = S3CannedACL.PublicRead
        };

        //putRequest.Metadata.Add("x-amz-meta-title", fileName);

        PutObjectResponse response = await client.PutObjectAsync(putRequest);
        return fileName;
    }

    public async Task<List<StorageFileSDto>> GetStorageFiles(StorageFileType fileType)
    {
        var client = GetClientAsync();
        ListObjectsRequest request = new() { BucketName = _bucketName};
        switch (fileType)
        {
            case StorageFileType.Image:
                request.Prefix = "Images/Med";
                break;
            case StorageFileType.Video:
                request.Prefix = "Videos";
                break;
            default:
                break;
        }
        var files = new List<StorageFileSDto>();
        do
        {
            ListObjectsResponse response = await client.ListObjectsAsync(request);

            // Process the response.
            foreach (var s3Object in response.S3Objects.Where(s=>s.Size>0))
            {
                files.Add(new StorageFileSDto
                {
                    FileLocation = s3Object.Key,
                    FileName = s3Object.Key.Split('/').Last()
                });
            }

            // If the response is truncated, set the marker to get the next
            // set of keys.
            if (response.IsTruncated)
            {
                request.Marker = response.NextMarker;
            }
            else
            {
                request = null;
            }
        } while (request != null);

        return files.OrderByDescending(o=>o.CreatedAt).ToList();
    }
}