using Azure;
using Azure.Cosmos;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK;
using HTEXLib.COMM.Helpers;
using TEAMModelOS.SDK.Models.Cosmos.Common;

namespace TEAMModelOS.SDK.Models.Service
{
    public static class FixDataService
    {
        /// <summary>
        /// 修复学生数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="_dingDing"></param>
        /// <param name="_azureStorage"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static async Task<List<Student>> FixStudentInfo(CosmosClient client, DingDing _dingDing, AzureStorageFactory _azureStorage, JsonElement data)
        {
            var code = data.GetProperty("code").GetString();
            var ids = data.GetProperty("ids").ToObject<List<string>>();
            var dict = data.GetProperty("dict").ToObject<Dictionary<string, object>>();
            string queryText = $"SELECT VALUE c FROM c WHERE c.id IN ({string.Join(",", ids.Select(o => $"'{o}'"))})";
            List<Student> students = new List<Student>();
            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student")
                            .GetItemQueryIterator<Student>(
                                queryText: queryText,
                                requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{code}") }))
            {
                foreach (var key in dict.Keys)
                {
                    switch (key)
                    {
                        case "classId":
                            item.classId = $"{ dict[key]}";
                            break;
                        case "periodId":
                            item.periodId = $"{ dict[key]}";
                            break;
                        case "schoolId":
                            item.schoolId = $"{ dict[key]}";
                            break;
                        case "year":
                            int year = DateTime.Now.Year;
                            int.TryParse($"dict[key]", out year);
                            item.year = year;
                            break;
                        default:
                            break;
                    }
                    await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<Student>(item, item.id, new PartitionKey(item.code));
                    students.Add(item);
                }
            }
            return students;
        }
        /// <summary>
        /// 修复内容模块数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="_dingDing"></param>
        /// <param name="_azureStorage"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public static async Task FixBlobContent(CosmosClient client, DingDing _dingDing, AzureStorageFactory _azureStorage, JsonElement data)
        {
            if (data.TryGetProperty("doPrivate", out JsonElement _doPrivate) && $"{_doPrivate}".Equals("yes", StringComparison.OrdinalIgnoreCase))
            {
                foreach (var cnt in _azureStorage.GetBlobServiceClient().GetBlobContainers())
                {
                    if (cnt.Name.Length == 10 && int.TryParse(cnt.Name, out _))
                    {
                        await doFixBlob(client, _azureStorage, cnt.Name, "private");
                    }
                }
            }
            List<School> schools = new List<School>();
            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: "select value(c) from c", requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
            {
                schools.Add(item);
            }
            foreach (var school in schools)
            {
                await doFixBlob(client, _azureStorage, school.id, "school");
            }
        }
        private static async Task doFixBlob(CosmosClient client, AzureStorageFactory _azureStorage, string name, string scope)
        {
            List<string> prefixs = new List<string>() { "audio", "doc", "image", "other", "res", "video" };
            var ContainerClient = _azureStorage.GetBlobContainerClient($"{name}");
            var tb = "Teacher";
            if (scope != "private")
            {
                tb = "School";
            }
            List<string> ids = new List<string>();
            await foreach (var item in client.GetContainer(Constant.TEAMModelOS, tb).GetItemQueryIterator<Bloblog>(queryDefinition: new QueryDefinition("select c.id from c "), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
            {
                ids.Add(item.id);
            }
            await client.GetContainer(Constant.TEAMModelOS, tb).DeleteItemsStreamAsync(ids, $"Bloblog-{name}");
            long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            foreach (var prefix in prefixs)
            {
                if (prefix.Equals("res"))
                {
                    List<string> itemres = await ContainerClient.List(prefix);
                    if (itemres.IsNotEmpty())
                    {
                        HashSet<string> set = new HashSet<string>();
                        itemres.ForEach(x =>
                        {
                            var uri = x.Split("/");
                            set.Add($"res/{uri[1]}");
                        });
                        foreach (var item in set)
                        {
                            var urlsSize = await ContainerClient.GetBlobsSize(item);
                            var url = item;
                            if (!item.EndsWith(".hte", StringComparison.OrdinalIgnoreCase) && !item.EndsWith(".HTEX", StringComparison.OrdinalIgnoreCase))
                            {
                                url += ".HTEX";
                            }
                            Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = url, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
                            await client.GetContainer(Constant.TEAMModelOS, tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
                        }
                    }
                }
                else
                {
                    List<string> items = await ContainerClient.List(prefix);
                    if (items.IsNotEmpty())
                    {
                        foreach (var item in items)
                        {
                            var urlsSize = await ContainerClient.GetBlobsSize(item);
                            Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = item, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
                            await client.GetContainer(Constant.TEAMModelOS, tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 修復學校基本資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixSchoolPeriodId(CosmosClient client, string schoolCode)
        {
            List<string> periodIdList = new List<string>();
            await foreach (School schinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: $"SELECT value(c) FROM c WHERE c.id = '{schoolCode}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
            {
                int periodIndex = 0;
                foreach (Period periodNow in schinfo.period)
                {
                    if (periodNow.id.Equals("上學期") || periodNow.id.Equals("上学期") || periodNow.id.Equals("First semester"))
                    {
                        string periodId = Guid.NewGuid().ToString();
                        schinfo.period[periodIndex].id = periodId;
                        periodIdList.Add(periodId);
                    }
                    periodIndex++;
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(schinfo, schinfo.id, new PartitionKey("Base"));
            }
            return periodIdList;
        }

        /// <summary>
        /// 修復學校班級資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixClassInfo(CosmosClient client, string schoolCode, Dictionary<string,string> dataDic)
        {
            List<string> classIdList = new List<string>();
            await foreach (Class classinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Class>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            classinfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Class>(classinfo, classinfo.id, new PartitionKey($"Class-{schoolCode}"));
                classIdList.Add(classinfo.id);
            }
            return classIdList;
        }

        /// <summary>
        /// 修復學校課程資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixCourseInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> courseIdList = new List<string>();
            await foreach (Course courseinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Course>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            courseinfo.period.id = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Course>(courseinfo, courseinfo.id, new PartitionKey($"Course-{schoolCode}"));
                courseIdList.Add(courseinfo.id);
            }
            return courseIdList;
        }

        /// <summary>
        /// 修復學校知識點資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixKnowledgeInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> knowledgeIdList = new List<string>();
            await foreach (Knowledge knowledgeinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Knowledge>(queryText: $"SELECT value(c) FROM c WHERE c.pk = 'Knowledge' AND c.owner = '{schoolCode}'", requestOptions: new QueryRequestOptions() {}))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            knowledgeinfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Knowledge>(knowledgeinfo, knowledgeinfo.id, new PartitionKey($"{knowledgeinfo.code}"));
                knowledgeIdList.Add(knowledgeinfo.id);
            }
            return knowledgeIdList;
        }

        /// <summary>
        /// 修復學校試卷資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixPaperInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> paperIdList = new List<string>();
            await foreach (Paper paperinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            paperinfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Paper>(paperinfo, paperinfo.id, new PartitionKey($"Paper-{schoolCode}"));
                paperIdList.Add(paperinfo.id);
            }
            return paperIdList;
        }

        /// <summary>
        /// 修復學校課綱資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixVolumeInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> volumeIdList = new List<string>();
            await foreach (Volume volumeinfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Volume>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Volume-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            volumeinfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Volume>(volumeinfo, volumeinfo.id, new PartitionKey($"Volume-{schoolCode}"));
                volumeIdList.Add(volumeinfo.id);
            }
            return volumeIdList;
        }

        /// <summary>
        /// 修復學校試題資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixItemInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> itemIdList = new List<string>();
            await foreach (ItemInfo iteminfo in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ItemInfo>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            iteminfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<ItemInfo>(iteminfo, iteminfo.id, new PartitionKey($"Item-{schoolCode}"));
                itemIdList.Add(iteminfo.id);
            }
            return itemIdList;
        }

        /// <summary>
        /// 修復學校評測資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixExamInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> examIdList = new List<string>();
            await foreach (ExamInfo examinfo in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            examinfo.period.id = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync<ExamInfo>(examinfo, examinfo.id, new PartitionKey($"Exam-{schoolCode}"));
                examIdList.Add(examinfo.id);
            }
            return examIdList;
        }

        /// <summary>
        /// 修復學生資料
        /// </summary>
        /// <param name="client"></param>
        /// <param name="schoolCode"></param>
        /// <param name="dataDic"></param>
        /// <returns></returns>
        public static async Task<List<string>> FixStudentInfo(CosmosClient client, string schoolCode, Dictionary<string, string> dataDic)
        {
            List<string> studentIdList = new List<string>();
            await foreach (Student studentinfo in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<Student>(queryText: $"SELECT value(c) FROM c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-{schoolCode}") }))
            {
                foreach (KeyValuePair<string, string> item in dataDic)
                {
                    switch (item.Key)
                    {
                        case "periodId":
                            studentinfo.periodId = item.Value;
                            break;
                    }
                }
                await client.GetContainer(Constant.TEAMModelOS, "Student").ReplaceItemAsync<Student>(studentinfo, studentinfo.id, new PartitionKey($"Base-{schoolCode}"));
                studentIdList.Add(studentinfo.id);
            }
            return studentIdList;
        }

    }
}
