
using Microsoft.Azure.Cosmos.Table;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Blobs.Specialized;
using Azure.Storage.Sas;
using Azure.Storage;
using TEAMModelOS.SDK.Extension;
using Azure.Storage.Queues;
using TEAMModelOS.SDK.Context.Attributes.Azure;
using System.Threading.Tasks;
using TEAMModelOS.SDK.Module.AzureBlob.Configuration;

namespace TEAMModelOS.SDK.DI
{
    public class AzureStorageFactory
    {
        private readonly IServiceProvider _services;
        private readonly IOptionsMonitor<AzureStorageFactoryOptions> _optionsMonitor;
        private readonly ILogger _logger;
        public AzureStorageFactory(IServiceProvider services, IOptionsMonitor<AzureStorageFactoryOptions> optionsMonitor, ILogger<AzureStorageFactory> logger)
        {
            if (services == null) throw new ArgumentNullException(nameof(services));
            if (optionsMonitor == null) throw new ArgumentNullException(nameof(optionsMonitor));

            _services = services;
            _optionsMonitor = optionsMonitor;
            _logger = logger;
        }

        public BlobServiceClient GetBlobServiceClient(string name = "Default")
        {
            try
            {
                var options = _optionsMonitor.Get(name);
                return new BlobServiceClient(options.StorageAccountConnectionString);
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }

        }

        public BlobContainerClient GetBlobContainerClient(string containerName, string name = "Default")
        {
            try
            {
                var options = _optionsMonitor.Get(name);
                return new BlobContainerClient(options.StorageAccountConnectionString, containerName);
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }

        public BlobBatchClient GetBlobBatchClient(string name = "Default")
        {
            try
            {
                var options = _optionsMonitor.Get(name);
                BlobServiceClient blobServiceClient = new BlobServiceClient(options.StorageAccountConnectionString);
                return blobServiceClient.GetBlobBatchClient();
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }

        /// <summary>
        /// 取得Blob Container SAS (有效期預設一天)
        /// </summary>
        /// <param name="containerName">容器名稱</param>        
        /// <param name="blobContainerSasPermissions">權限(可多選)Flags</param>
        /// <param name="name"></param>
        /// <returns></returns>
        public (string uri, string sas) GetBlobContainerSAS(string containerName, BlobContainerSasPermissions blobContainerSasPermissions, string name = "Default")
        {
            try
            {
                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
                var accountname = keys["AccountName"];
                var accountkey = keys["AccountKey"];
                var endpoint = keys["EndpointSuffix"];

                var blobSasBuilder = new BlobSasBuilder
                {
                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                    ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
                    BlobContainerName = containerName
                };

                blobSasBuilder.SetPermissions(blobContainerSasPermissions);
                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
                UriBuilder fullUri = new UriBuilder()
                {
                    Scheme = "https",
                    Host = $"{accountname}.blob.{endpoint}",
                    Path = containerName
                    //Query = sasQueryParameters.ToString()
                };

                return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
            }
            catch
            {
                return (null, null);
            }
        }

        /// <summary>
        /// 取得Blob Container SAS (有效期預設一天)
        /// </summary>
        /// <param name="containerName">容器名稱</param>
        /// <param name="blobName"></param>
        /// <param name="blobContainerSasPermissions"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public BlobAuth GetContainerSasUri(BlobSas blobSas, bool isRead, string name = "Default")
        {
            try
            {
                string containerName = null;
                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
                var accountname = keys["AccountName"];
                var accountkey = keys["AccountKey"];
                var endpoint = keys["EndpointSuffix"];
                if (blobSas.role == "system")
                {
                    containerName = "teammodelos";
                }
                else
                {
                    containerName = blobSas.name.ToLower().Replace("#", "");
                }
                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0));
                long time = dateTime.ToUnixTimeMilliseconds();
                var blobSasBuilder = new BlobSasBuilder
                {
                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                    ExpiresOn = dateTime,
                    BlobContainerName = containerName
                };
                BlobContainerSasPermissions blobContainerSasPermissions = BlobContainerSasPermissions.Read;
                if (isRead)
                {
                    blobContainerSasPermissions = BlobContainerSasPermissions.Read;
                }
                else
                {
                    blobContainerSasPermissions = BlobContainerSasPermissions.Delete | BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Create | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List;
                }
                blobSasBuilder.SetPermissions(blobContainerSasPermissions);
                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
                UriBuilder fullUri = new UriBuilder()
                {
                    Scheme = "https",
                    Host = $"{accountname}.blob.{endpoint}",
                    Path = containerName
                    //Query = sasQueryParameters.ToString()
                };
                return new BlobAuth { url = fullUri.Uri.ToString().Replace(fullUri.Uri.LocalPath, ""), sas = sasQueryParameters.ToString(), timeout = time, name = containerName };
                // return (fullUri.Uri.ToString(), sasQueryParameters.ToString());
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 取得Blob SAS (有效期預設一天)
        /// </summary>
        /// <param name="containerName">容器名稱</param>
        /// <param name="blobName"></param>
        /// <param name="blobSasPermissions">權限(可多選)Flags</param>
        /// <param name="name"></param>
        /// <returns></returns>
        public string GetBlobSAS(string containerName, string blobName, BlobSasPermissions blobSasPermissions, string name = "Default")
        {
            try
            {
                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
                var accountname = keys["AccountName"];
                var accountkey = keys["AccountKey"];
                var endpoint = keys["EndpointSuffix"];

                var blobSasBuilder = new BlobSasBuilder
                {
                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                    ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
                    BlobContainerName = containerName,
                    BlobName = blobName
                };

                blobSasBuilder.SetPermissions(blobSasPermissions);
                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
                UriBuilder fullUri = new UriBuilder()
                {
                    Scheme = "https",
                    Host = $"{accountname}.blob.{endpoint}",
                    Path = $"{containerName}/{blobName}",
                    Query = sasQueryParameters.ToString()
                };

                return fullUri.Uri.ToString();
            }
            catch
            {
                return null;
            }
        }


        /// <summary>
        /// 取得Blob SAS (有效期預設一天)
        /// </summary>
        /// <param name="containerName">容器名稱</param>
        /// <param name="blobName"></param>
        /// <param name="blobSasPermissions"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public BlobAuth GetBlobSasUriRead(string containerName, string blobName, string name = "Default")
        {
            try
            {
                var keys = Utils.ParseConnectionString(_optionsMonitor.Get(name).StorageAccountConnectionString);
                var accountname = keys["AccountName"];
                var accountkey = keys["AccountKey"];
                var endpoint = keys["EndpointSuffix"];
                DateTimeOffset dateTime = DateTimeOffset.UtcNow.Add(new TimeSpan(365 * 99, 0, 15, 0));
                long time = dateTime.ToUnixTimeMilliseconds();
                var blobSasBuilder = new BlobSasBuilder
                {
                    StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                    ExpiresOn = dateTime,
                    BlobContainerName = containerName,
                    BlobName = blobName
                };

                blobSasBuilder.SetPermissions(BlobSasPermissions.Read);
                var sskc = new StorageSharedKeyCredential(accountname, accountkey);
                BlobSasQueryParameters sasQueryParameters = blobSasBuilder.ToSasQueryParameters(sskc);
                UriBuilder fullUri = new UriBuilder()
                {
                    Scheme = "https",
                    Host = $"{accountname}.blob.{endpoint}",
                    Path = $"{containerName}/{blobName}",
                    Query = sasQueryParameters.ToString()
                };
                return new BlobAuth { url = fullUri.Uri.ToString(), sas = sasQueryParameters.ToString(), timeout = time };
                // return fullUri.Uri.ToString();
            }
            catch
            {
                return null;
            }
        }

        public CloudTableClient GetCloudTableClient(string name = "Default")
        {
            try
            {
                var options = _optionsMonitor.Get(name);
                CloudStorageAccount storageAccount = CloudStorageAccount.Parse(options.StorageAccountConnectionString);
                return storageAccount.CreateCloudTableClient();
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }



        /// <summary>
        /// 可讓您管理儲存體帳戶中的所有佇列
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public QueueServiceClient GetQueueServiceClient(string name = "Default")
        {
            try
            {
                var options = _optionsMonitor.Get(name);
                return new QueueServiceClient(options.StorageAccountConnectionString);
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }

        /// <summary>
        /// 可讓您管理和操作個別佇列及其訊息
        /// </summary>
        /// <param name="name"></param>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public QueueClient GetQueueClient(string queueName, string name = "Default")
        {
            if (name == null) throw new ArgumentNullException(nameof(name));
            try
            {
                var options = _optionsMonitor.Get(name);
                return new QueueClient(options.StorageAccountConnectionString, queueName);
            }
            catch (OptionsValidationException e)
            {
                _logger?.LogWarning(e, e.Message);
                return null;
            }
        }
        public async Task<CloudTable> InitializeTable<T>()
        {
            string TableName = GetTableSpace<T>();
            CloudTable cloudTable = GetCloudTableClient().GetTableReference(TableName);
            await cloudTable.CreateIfNotExistsAsync();
            return cloudTable;
        }
        private string GetTableSpace<T>()
        {
            Type type = typeof(T);
            string Name = type.Name;
            object[] attributes = type.GetCustomAttributes(true);
            foreach (object attribute in attributes) //2.通过映射，找到成员属性上关联的特性类实例，
            {
                if (attribute is TableNameAttribute tableSpace)
                {
                    Name = tableSpace.Name;
                }
            }
            return Name;
        }
    }
}
