using Azure.Cosmos;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.Models;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.Services.Common;
using static TEAMModelOS.Services.Common.BlobService;

namespace TEAMModelOS.Controllers.Client
{
    [Route("hita")]
    [ApiController]
    public class HiTAControlller : ControllerBase
    {
        private readonly AzureStorageFactory _azureStorage;
        private readonly AzureRedisFactory _azureRedis;
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly DingDing _dingDing;
        private readonly Option _option;
        private readonly SnowflakeId _snowflakeId;

        public HiTAControlller(
            AzureStorageFactory azureStorage,
            AzureRedisFactory azureRedis,
            AzureCosmosFactory azureCosmos,
            DingDing dingDing,
            SnowflakeId snowflakeId,
            IOptionsSnapshot<Option> option)
        {
            _azureStorage = azureStorage;
            _azureRedis = azureRedis;
            _azureCosmos = azureCosmos;
            _dingDing = dingDing;
            _snowflakeId = snowflakeId;
            _option = option?.Value;
        }

        //[Authorize(Roles = "HiTA")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(StatusCodes.Status400BadRequest)]
        [ProducesDefaultResponseType]
        [HttpPost("get-teacher-info")]
        public async Task<IActionResult> GetTeacherInfo()
        {
            try
            {
                string id_token = HttpContext.GetXAuth("IdToken");
                if (string.IsNullOrEmpty(id_token)) return BadRequest();
                var jwt = new JwtSecurityToken(id_token);
                if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
                var id = jwt.Payload.Sub;

                
                var clientc = _azureCosmos.GetCosmosClient();
                var clientr = _azureRedis.GetRedisClient(8);
                var response = await clientc.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(id, new PartitionKey("Base"));
                if (response.Status == 200)
                {
                    var jsonsc = await JsonDocument.ParseAsync(response.ContentStream);
                    //學校資訊
                    List<dynamic> schools = new List<dynamic>();
                    if (jsonsc.RootElement.TryGetProperty("schools", out JsonElement value))
                    {
                        foreach (var obj in value.EnumerateArray())
                        {
                            string schoolCodeNow = $"{obj.GetProperty("schoolId")}";
                            var clientss = _azureStorage.GetBlobContainerClient(schoolCodeNow);
                            //Blob使用狀況
                            UsedBlob schoolUsedBlob = await BlobService.GetBlobUsed(clientc, clientss, clientr, "school", schoolCodeNow);
                            //管理者名單
                            List<Dictionary<string, string>> adminList = new List<Dictionary<string, string>>();
                            string querySchool = $"SELECT c.id, c.name FROM c WHERE ARRAY_CONTAINS(c.roles, 'admin', true)";
                            await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(querySchool, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{schoolCodeNow}") }))
                            {
                                using var json = await JsonDocument.ParseAsync(item.ContentStream);
                                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                                {
                                    foreach (var objadmin in json.RootElement.GetProperty("Documents").EnumerateArray())
                                    {
                                        Dictionary<string, string> adminRow = new Dictionary<string, string>();
                                        adminRow.Add("id", objadmin.GetProperty("id").GetString());
                                        adminRow.Add("name", objadmin.GetProperty("name").GetString());
                                        adminList.Add(adminRow);
                                    }
                                }
                            }
                            //老師在此學校的課程
                            List<dynamic> coursesch = new List<dynamic>();
                            var query = $"SELECT c.id, c.name, c.no FROM c JOIN schedule IN c.schedule WHERE schedule.teacherId = '{id}'";
                            await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{schoolCodeNow}") }))
                            {
                                var jsoncs = await JsonDocument.ParseAsync(item.ContentStream);
                                if (jsoncs.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                                {
                                    foreach (var obj2 in jsoncs.RootElement.GetProperty("Documents").EnumerateArray())
                                    {
                                        dynamic courseExtobj = new ExpandoObject();
                                        courseExtobj.id = obj2.GetProperty("id");
                                        courseExtobj.name = obj2.GetProperty("name");
                                        courseExtobj.no = obj2.GetProperty("no");
                                        coursesch.Add(courseExtobj);
                                    }
                                }
                            }
                           
                            //學校資料生成
                            dynamic schoolExtobj = new ExpandoObject();
                            var schoolJson = await clientc.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{obj.GetProperty("schoolId")}", new PartitionKey("Base"));
                            var school = await JsonDocument.ParseAsync(schoolJson.ContentStream);
                            schoolExtobj.schoolId = obj.GetProperty("schoolId");
                            schoolExtobj.name = school.RootElement.GetProperty("name");
                            schoolExtobj.status = obj.GetProperty("status");
                            schoolExtobj.picture = school.RootElement.GetProperty("picture");
                            schoolExtobj.size = new ExpandoObject();
                            schoolExtobj.size.used = schoolUsedBlob.size + schoolUsedBlob.teach * 1073741824;
                            long ssize = (school.RootElement.TryGetProperty("size", out JsonElement ssizeJson)) ? ssizeJson.GetInt32() : 0;
                            schoolExtobj.size.total = ssize * 1073741824;
                            schoolExtobj.size.avaliable = schoolExtobj.size.total - schoolExtobj.size.used;
                            schoolExtobj.admin = adminList;
                            schoolExtobj.courses = coursesch;

                            schools.Add(schoolExtobj);
                        }
                    }
                    //預設學校
                    string defaultschool = null;
                    if(jsonsc.RootElement.TryGetProperty("defaultSchool", out JsonElement defaultSchoolJson) && !defaultSchoolJson.ValueKind.Equals(JsonValueKind.Null))
                    {
                        defaultschool = defaultSchoolJson.GetString();
                    }
                    //老師個人課程
                    List<dynamic> courses = new List<dynamic>();
                    await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name, c.no FROM c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Course-{id}") }))
                    {
                        var jsontcs = await JsonDocument.ParseAsync(item.ContentStream);
                        if (jsontcs.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                        {
                            foreach (var obj in jsontcs.RootElement.GetProperty("Documents").EnumerateArray())
                            {
                                dynamic courseExtobj = new ExpandoObject();
                                courseExtobj.id = obj.GetProperty("id");
                                courseExtobj.name = obj.GetProperty("name");
                                courseExtobj.no = obj.GetProperty("no");
                                courses.Add(courseExtobj);
                            }
                        }
                    }
                    //老師個人空間  ※老師可用的空間 = (Teacher)Base.size + (School)各校的Teacher-{schoolCode}
                    dynamic size = new ExpandoObject();
                    size.resource = 0;
                    size.records = 0;
                    size.used = 0;
                    size.total = 0;
                    var clientst = _azureStorage.GetBlobContainerClient(id);
                    ////個人可用空間
                    if (jsonsc.RootElement.TryGetProperty("size", out JsonElement teaSizeTotalJson) && teaSizeTotalJson.ValueKind.Equals(JsonValueKind.Number))
                    {
                        size.total += teaSizeTotalJson.GetInt32();
                    }
                    ////學校分派給老師的空間
                    int GsizeFromSchool = 0;
                    string querySizeFromSchool = $"SELECT sum(c.size) as size FROM c WHERE c.pk = 'Teacher' AND c.id = {id}";
                    await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(querySizeFromSchool, requestOptions: new QueryRequestOptions() { }))
                    {
                        var json = await JsonDocument.ParseAsync(item.ContentStream);
                        foreach (var elmt in json.RootElement.GetProperty("Documents").EnumerateArray())
                        {
                            if (elmt.TryGetProperty("size", out JsonElement sizeJson) && sizeJson.ValueKind.Equals(JsonValueKind.Number))
                            {
                                GsizeFromSchool = sizeJson.GetInt32();
                                break;
                            }
                        }
                    }
                    size.total += GsizeFromSchool;
                    size.total = Convert.ToInt64(size.total) * 1073741824;

                    ////個人空間使用狀況
                    UsedBlob teacherUsedBlob = await BlobService.GetBlobUsed(clientc, clientst, clientr, "private", id);
                    size.used = teacherUsedBlob.size;
                    foreach (KeyValuePair<string, double?> blobCatalog in teacherUsedBlob.catalog)
                    {
                        if(blobCatalog.Key.Equals("records"))
                        {
                            size.records = blobCatalog.Value;
                        }
                        else
                        {
                            size.resource += blobCatalog.Value;
                        }
                    }
                    

                    //資源數
                    int resCount = 0; //教材數
                    int itemCount = 0; //題目數
                    int paperCount = 0; //試卷數
                    List<BlobCount> blogCountList = await BloblogCount(clientc, "private", id, "", "");
                    foreach(BlobCount blobCountRow in blogCountList)
                    {
                        switch (blobCountRow.type)
                        {
                            case "item":
                                itemCount += blobCountRow.count;
                                break;
                            case "paper":
                                paperCount += blobCountRow.count;
                                break;
                            case "doc":
                            case "image":
                            case "res":
                            case "video":
                            case "audio":
                            case "other":
                                resCount += blobCountRow.count;
                                break;
                        }
                    }

                    //進行中的活動數
                    int activityCount = 0;
                    List<string> examIdList = new List<string>();
                    await foreach (var actitem in clientc.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT COUNT(1) AS count FROM c WHERE c.progress = 'going'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{id}") }))
                    {
                        using var json = await JsonDocument.ParseAsync(actitem.ContentStream);
                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                        {
                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                            {
                                activityCount += obj.GetProperty("count").GetInt32();
                            }
                        }
                    }
                    await foreach (var actitem in clientc.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT COUNT(1) AS count FROM c WHERE c.progress = 'going'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{id}") }))
                    {
                        using var json = await JsonDocument.ParseAsync(actitem.ContentStream);
                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                        {
                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                            {
                                activityCount += obj.GetProperty("count").GetInt32();
                            }
                        }
                    }
                    await foreach (var actitem in clientc.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT COUNT(1) AS count FROM c WHERE c.progress = 'going'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{id}") }))
                    {
                        using var json = await JsonDocument.ParseAsync(actitem.ContentStream);
                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                        {
                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                            {
                                activityCount += obj.GetProperty("count").GetInt32();
                            }
                        }
                    }
                    await foreach (var actitem in clientc.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: $"SELECT COUNT(1) AS count FROM c WHERE c.progress = 'going'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{id}") }))
                    {
                        using var json = await JsonDocument.ParseAsync(actitem.ContentStream);
                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                        {
                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                            {
                                activityCount += obj.GetProperty("count").GetInt32();
                            }
                        }
                    }

                    return Ok(new { schools, defaultschool, courses, size, resCount, itemCount, paperCount, activityCount });
                }
                else //無此老師
                {
                    return BadRequest();
                }
            }
            catch (Exception ex)
            {
                //await _dingDing.SendBotMsg($"CoreAPI2，{_option.Location}，Channel/Create()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }
        }
    }
}
