using System.Threading.Tasks;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
using TEAMModelOS.SDK.Module.AzureBlob.Container;
using TEAMModelOS.SDK.Context.Constant;
using TEAMModelOS.SDK.Helper.Security.ShaHash;
using System;
using System.IO;
using Azure.Storage.Blobs.Specialized;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Azure.Core;

namespace TEAMModelOS.SDK.DI
{
    public static class AzureStorageBlobExtensions
    {
        /// <summary>
        /// 取得指定前置詞的 Blob 名稱的總大小(Bytes)，例如指定目錄名稱為前置詞
        /// </summary>      
        /// <param name="prefix">篩選開頭名稱，Null代表容器總大小</param>
        /// <returns>總大小(Bytes)，如果為Null代表查無前置詞或者發生錯誤</returns>
        public static async Task<long?> GetBlobsSize(this BlobContainerClient client, string prefix = null)
        {
            long? size = 0;
            try
            {
               
                await foreach (BlobItem item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
                {
                    size += item.Properties.ContentLength;
                };
                return size;
            }
            catch
            {
                return size;
            }
        }

        public static async Task<List<string>> List(this BlobContainerClient client, string prefix = null) {
            try
            {
                List<string> items = new List<string>();
                await foreach (BlobItem item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix)) {
                    items.Add(item.Name);
                }
                return items;
            }
            catch
            {
                return null;
            }

        }

        /// <summary>
        /// 取得指定前置詞的 Blob 名稱的總大小(Bytes)，例如指定目錄名稱為前置詞
        /// </summary>      
        /// <param name="prefix">篩選開頭名稱，Null代表容器總大小</param>
        /// <returns>總大小(Bytes)，如果為Null代表查無前置詞或者發生錯誤</returns>
        public static async Task<(long?, Dictionary<string, double?>)> GetBlobsCatalogSize(this BlobContainerClient client, string prefix = null)
        {
            long? size = 0;
            Dictionary<string, double?> dict = new Dictionary<string, double?>();
            try
            {
                List<KeyValuePair<string, double?>> foderSize = new List<KeyValuePair<string, double?>>();
                await foreach (BlobItem item in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
                {
                    var len = item.Properties.ContentLength;
                    foderSize.Add(new KeyValuePair<string, double?>(item.Name.Split("/")[0], len));
                    size += item.Properties.ContentLength;
                };
                foderSize.Select(x => new { x.Key, x.Value }).GroupBy(y=>y.Key).ToList().ForEach(g=> {
                    var gpsize = g.Select(m => m.Value).Sum();
                    dict[g.Key] = gpsize;
                });
                return (size, dict);
            }
            catch
            {
                return (size, dict);
            }
        }

        public class OptUrl
        {
            public string url { get; set; }
            public long size { get; set; }
        }
        /// <summary>
        /// 取得指定前置詞的 Blob 名稱的總大小(Bytes)，例如指定目錄名稱為前置詞
        /// </summary>      
        /// <param name="urls">多个文件的连接/param>
        /// <returns>總大小(Bytes)，如果為Null代表查無前置詞或者發生錯誤</returns>
        public static async Task<List<OptUrl>> GetBlobsSize(this BlobContainerClient client, List<string> urls)
        {
            List<OptUrl> optUrls = new List<OptUrl>();
            try
            {
                if (urls != null) {
                    foreach (var url in urls)
                    {
                        OptUrl optUrl = new OptUrl { url = url, size = 0 };
                        var eurl = System.Web.HttpUtility.UrlDecode(url, Encoding.UTF8);
                        var blob = client.GetBlobClient(eurl);
                        if (blob.Exists())
                        {
                            var props = await blob.GetPropertiesAsync();
                            var size = props.Value.ContentLength;
                            optUrl.size = size;
                        }
                        optUrls.Add(optUrl);
                    }
                }
                
                return optUrls;
            }
            catch
            {
                return optUrls;
            }
        }
        /// <summary>        
        /// 批量刪除Blobs
        /// </summary>      
        /// <param name="prefix">篩選開頭名稱，Null代表容器</param>        
        public static async Task<bool> DelectBlobs(this BlobServiceClient client, string blobContainerName, List<Uri> blobs = null)
        {
            
            try
            {
                BlobContainerClient bcc = client.GetBlobContainerClient(blobContainerName);
                BlobBatchClient bbc = client.GetBlobBatchClient();
                if (blobs.Count <= 256)
                {
                    await bbc.DeleteBlobsAsync(blobs);
                    return true;
                }
                else
                {
                    int pages = (blobs.Count + 255) / 256; //256是批量操作最大值，pages = (total + max -1) / max;
                    for (int i = 0; i < pages; i++)
                    {
                        List<Uri> lists = blobs.Skip((i) * 256).Take(256).ToList();
                        await bbc.DeleteBlobsAsync(lists);
                    }
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }
        /// <summary>        
        /// 批量刪除Blobs
        /// </summary>      
        /// <param name="prefix">篩選開頭名稱，Null代表容器</param>        
        public static async Task<bool> DelectBlobs(this BlobServiceClient client, string blobContainerName, string prefix = null)
        {
            if (string.IsNullOrWhiteSpace(prefix)) return false;
            try
            {
                BlobContainerClient bcc = client.GetBlobContainerClient(blobContainerName);
                BlobBatchClient bbc = client.GetBlobBatchClient();
                
                List<Uri> blobs = new List<Uri>();
                await foreach (var item in bcc.GetBlobsAsync(BlobTraits.None, BlobStates.None, prefix))
                {
                    var urib = new UriBuilder(bcc.Uri);
                    urib.Path += "/" + item.Name;
                    blobs.Add(urib.Uri);
                };
                if (blobs.Count <= 256)
                {
                    await bbc.DeleteBlobsAsync(blobs);
                    return true;
                }
                else
                {
                    int pages = (blobs.Count + 255) / 256; //256是批量操作最大值，pages = (total + max -1) / max;
                    for (int i = 0; i < pages; i++)
                    {
                        List<Uri> lists = blobs.Skip((i) * 256).Take(256).ToList();
                        await bbc.DeleteBlobsAsync(lists);
                    }
                    return true;
                }
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 系统管理员 资源，题目关联，htex关联，学习活动学生上传文件关联，基本信息关联，教室平面图关联，评测冷数据关联
        /// "system": [ "res", "item", "htex", "task", "info", "room", "exam" ],
        /// 资源，题目关联，htex关联，学习活动学生上传文件关联，基本信息关联，教室平面图关联，评测冷数据关联
        /// "school": [ "res", "item", "htex", "task", "info", "room", "exam" ],
        /// 资源，题目关联，htex关联，学习活动关联，教师基本信息关联
        /// "teacher": [ "res", "item", "htex", "task", "info" ],
        /// 答案及学习活动上传的文件，学生基本信息关联
        ///"student": [ "stu/{studentId}/ans", "stu/{studentId}/task" ]
        /// </summary>
        /// <param name="name">容器名称</param>
        /// <param name="json">文件内容的流</param>
        /// <param name="folder">业务文件夹</param>
        /// <param name="fileName">文件名</param>
        /// <param name="contentTypeDefault">是否存放文件后缀对应的contentType</param>
        /// <returns></returns>
        public static async Task<string> UploadFileByContainer(this AzureStorageFactory azureStorage, string name, string json, string root , string blobpath, bool contentTypeDefault = true)
        {

            // string groupName =folder;

            BlobContainerClient blobContainer = azureStorage.GetBlobContainerClient(name.ToLower().Replace("#", "")); //blobClient.GetContainerReference(groupName);            

            var blockBlob = blobContainer.GetBlobClient($"{root}/{blobpath}");
            string content_type = "application/octet-stream";
            if (!contentTypeDefault)
            {
                string fileext = blobpath.Substring(blobpath.LastIndexOf(".") > 0 ? blobpath.LastIndexOf(".") : 0);
                ContentTypeDict.dict.TryGetValue(fileext, out string contenttype);
                if (!string.IsNullOrEmpty(contenttype))
                {
                    content_type = contenttype;
                }
            }
            byte[] bytes = System.Text.Encoding.Default.GetBytes(json);
            Stream streamBlob = new MemoryStream(bytes);
            await blockBlob.UploadAsync(streamBlob, true);
            blockBlob.SetHttpHeaders(new BlobHttpHeaders { ContentType = content_type });
            
            return  blockBlob.Uri.ToString();
        }

        /// <summary>
        /// 系统管理员 资源，题目关联，htex关联，学习活动学生上传文件关联，基本信息关联，教室平面图关联，评测冷数据关联
        /// "system": [ "res", "item", "htex", "task", "info", "room", "exam" ],
        /// 资源，题目关联，htex关联，学习活动学生上传文件关联，基本信息关联，教室平面图关联，评测冷数据关联
        /// "school": [ "res", "item", "htex", "task", "info", "room", "exam" ],
        /// 资源，题目关联，htex关联，学习活动关联，教师基本信息关联
        /// "teacher": [ "res", "item", "htex", "task", "info" ],
        /// 答案及学习活动上传的文件，学生基本信息关联
        ///"student": [ "stu/{studentId}/ans", "stu/{studentId}/task" ]
        /// </summary>
        /// <param name="name">容器名称</param>
        /// <param name="stream">文件内容的流</param>
        /// <param name="folder">业务文件夹</param>
        /// <param name="fileName">文件名</param>
        /// <param name="contentTypeDefault">是否存放文件后缀对应的contentType</param>
        /// <returns></returns>
        public static async Task<string> UploadFileByContainer(this AzureStorageFactory azureStorage, string name, Stream stream, string root, string blobpath, bool contentTypeDefault = true)
        {
            BlobContainerClient blobContainer = azureStorage.GetBlobContainerClient(name.ToLower().Replace("#", "")); //blobClient.GetContainerReference(groupName); 
            Uri url = blobContainer.Uri;
            var blockBlob = blobContainer.GetBlobClient($"{root}/{blobpath}");
            string content_type = "application/octet-stream";
            if (!contentTypeDefault)
            {
                string fileext = blobpath.Substring(blobpath.LastIndexOf(".") > 0 ? blobpath.LastIndexOf(".") : 0);
                ContentTypeDict.dict.TryGetValue(fileext, out string contenttype);
                if (!string.IsNullOrEmpty(contenttype))
                {
                    content_type = contenttype;
                }
            }
            await blockBlob.UploadAsync(stream, true);
            blockBlob.SetHttpHeaders(new BlobHttpHeaders { ContentType = content_type });
            return blockBlob.Uri.ToString();
        }
    }
}
