using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;
using TEAMModelOS.SDK;

using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK;
using System;
using TEAMModelOS.SDK.Helper.Common.JsonHelper;
using System.Linq;
using TEAMModelOS.Models;
using System.Text.Json;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models;
using Microsoft.AspNetCore.Http;
using TEAMModelOS.SDK.Models.Cosmos.Common;
using Azure.Cosmos;
using TEAMModelOS.Services.Common;
using Microsoft.Extensions.Options;
using System.Text;
using HTEXLib.COMM.Helpers;

namespace TEAMModelOS.Controllers
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")]
    [Route("common/syllabus")]
    [ApiController]
    //[Authorize]
    public class SyllabusController : ControllerBase
    {
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly Option _option;
        private readonly DingDing _dingDing;
        public SyllabusController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option)
        {
            _azureCosmos = azureCosmos;
            _dingDing = dingDing;
            _option = option?.Value;
        }

        /// <summary>
        /// 检查资源链接是否被其他结构关联
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("check-link")]
        public async Task<IActionResult> CheckLink(JsonElement request) {
            if (!request.TryGetProperty("links", out JsonElement _links)) return BadRequest();
            if (!request.TryGetProperty("code", out JsonElement _code)) return BadRequest();
            if (!request.TryGetProperty("scope", out JsonElement _scope)) return BadRequest();
            if (_code.ValueKind.Equals(JsonValueKind.String) && _links.ValueKind.Equals(JsonValueKind.Array))
            {
                List<LinkDto> links = new List<LinkDto>();
                List<string>list=  _links.ToObject<List<string>>();
                var client = _azureCosmos.GetCosmosClient();
                list= list.Select(x => $"'{x}'").ToList();
                string lks= string.Join(",", list);
                StringBuilder queryText = new StringBuilder($"SELECT  c.id as syllabusId,c.volumeId,rnodes.link ,children.id as treeid  FROM c join children  in  c.children join rnodes in children.rnodes    where rnodes.link in ({lks}) ");
                if (_scope.ValueKind.Equals(JsonValueKind.String) && _scope.GetString() .Equals("school"))
                {
                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LinkDto>(queryText: queryText.ToString(),
                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{_code}") }))
                    {
                        links.Add(item);
                    }
                }
                else if (_scope.ValueKind.Equals(JsonValueKind.String) && _scope.GetString() .Equals("private")) {
                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<LinkDto>(queryText: queryText.ToString(),
                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{_code}") }))
                    {
                        links.Add(item);
                    }
                }
               var count= links.GroupBy(x => x.link).Select(y=>new { key= y.Key,count=y.ToList().Count});
                return Ok(new { count , links });
            }
            else {
                return BadRequest();
            }
           
        }
        public class LinkDto{ 
            public string syllabusId { get; set; }
            public string volumeId { get; set; }
            public string link { get; set; }
            public string treeid { get; set; }
        }

        /*
         [
            {
                "id": "章节id",
                "volumeId": "册别id",
                "scope": "school",
                "trees": [
                    {
                        "id": "b2b15c99-83cc-eca7-5b4b-e58d2a457c8e",
                        "pid": "0baf00db-0768-4b62-a8f7-280f6bcebf71",
                        "title": "第一单元",
                        "type": 1,
                        "children": []
                    }
                ]
            }
        ]
         */
        /// <summary>
        /// 批量保存或更新课纲
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("upsert-tree")]
        public async Task<IActionResult> SaveOrUpdateAsTree(List<SyllabusTreeNode> request)
        {
            long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            foreach (SyllabusTreeNode syllabusTree in request) {
              
                if (!string.IsNullOrEmpty(syllabusTree.id))
                {
                    Syllabus syllabus = null;
                    if (syllabusTree.scope .Equals("school"))
                    {
                        try
                        {
                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }
                        catch
                        {
                        }
                        if (syllabus == null)
                        {
                            if (syllabusTree.trees.IsNotEmpty())
                            {
                                syllabusTree.trees.ForEach(x => x.id = syllabusTree.id);
                            }
                            List<Tnode> nodes = new List<Tnode>();
                            SyllabusService.TreeToList(syllabusTree.trees, nodes, now);
                            syllabus = new Syllabus();
                            syllabus.id = syllabusTree.id;
                            syllabus.children = nodes;
                            syllabus.code = $"Syllabus-{syllabusTree.codeval}";
                            syllabus.pk = "Syllabus";
                            syllabus.ttl = -1;
                            syllabus.volumeId = syllabusTree.volumeId;
                            syllabus.scope = syllabusTree.scope;
                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }
                        else
                        {
                            if (syllabusTree.trees.IsNotEmpty())
                            {
                                syllabusTree.trees.ForEach(x => x.id = syllabusTree.id);
                            }
                            List<Tnode> nodes = new List<Tnode>();
                            SyllabusService.TreeToList(syllabusTree.trees, nodes, now);
                            syllabus.children = nodes;
                            syllabusTree.auth = syllabus.auth;
                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Syllabus>(syllabus,syllabus.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }

                    }
                    else {
                        try
                        {
                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }
                        catch
                        {
                        }
                        if (syllabus == null)
                        {
                            if (syllabusTree.trees.IsNotEmpty()) {
                                syllabusTree.trees.ForEach(x => x.id = syllabusTree.id);
                            }
                            List<Tnode> nodes = new List<Tnode>();
                            SyllabusService.TreeToList(syllabusTree.trees, nodes, now);
                            syllabus = new Syllabus();
                            syllabus.id = syllabusTree.id;
                            syllabus.children = nodes;
                            syllabus.code = $"Syllabus-{syllabusTree.codeval}";
                            syllabus.pk = "Syllabus";
                            syllabus.ttl = -1;
                            syllabus.volumeId = syllabusTree.volumeId;
                            syllabus.scope = syllabusTree.scope;
                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }
                        else
                        {
                            if (syllabusTree.trees.IsNotEmpty())
                            {
                                syllabusTree.trees.ForEach(x => x.id = syllabusTree.id);
                            }
                            List<Tnode> nodes = new List<Tnode>();
                            SyllabusService.TreeToList(syllabusTree.trees, nodes, now);
                            syllabus.children = nodes;
                            syllabusTree.auth = syllabus.auth;
                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                        }
                    }
                }
                else {
                    string id = Guid.NewGuid().ToString();
                    syllabusTree.id = id;
                    if (syllabusTree.trees.IsNotEmpty())
                    {
                        syllabusTree.trees.ForEach(x => x.id = syllabusTree.id);
                    }
                    List<Tnode> nodes = new List<Tnode>();
                    SyllabusService.TreeToList(syllabusTree.trees, nodes, now);
                    Syllabus syllabus = new Syllabus {
                        id = id,
                        code = $"Syllabus-{syllabusTree.codeval}",
                        pk = "Syllabus",
                        ttl = -1,
                        volumeId=syllabusTree.volumeId,
                        children=nodes,
                        scope = syllabusTree.scope
                    };
                    if (syllabusTree.scope .Equals("school")) {
                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                    } else {
                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                    }
                }
            }
            return Ok(request);
        }

        /*
            {"volumeId":"册别id：0baf00db-0768-4b62-a8f7-280f6bcebf71","scope":"school","volumeCode":"册别分区键"}
         */
        /// <summary>
        /// 查找课纲 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("find-id")]
        public async Task<IActionResult> Find(JsonElement request)
        {
            var client = _azureCosmos.GetCosmosClient();
            if (!request.TryGetProperty("volumeId", out JsonElement volumeId)) return BadRequest();
            if (!request.TryGetProperty("volumeCode", out JsonElement volumeCode)) return BadRequest();
            if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
            Volume volume = null;
            List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
            List<SyllabusTreeNode> redt = new List<SyllabusTreeNode>();
            try {
                if (scope.ToString().Equals("school"))
                {
                      volume = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Volume>($"{volumeId}", new PartitionKey($"{volumeCode}"));
                      await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c where c.volumeId='{volumeId}'",

                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volume.school}") }))
                    {
                        List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope =item.scope, trees = trees ,volumeId=item.volumeId,auth=item.auth,codeval=volume.school};
                        treeNodes.Add(tree);
                    }
                }
                else
                {
                    volume = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Volume>($"{volumeId}", new PartitionKey($"{volumeCode}"));
                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c where c.volumeId='{volumeId}'",
                     requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volume.creatorId}") }))
                    {
                        List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth,codeval=volume.creatorId };
                        treeNodes.Add(tree);
                    }
                }
                //对课纲树形结构排序
                if (volume.syllabusIds.IsNotEmpty())
                {
                    volume.syllabusIds.ForEach(x =>
                    {
                        for (int index = 0; index < treeNodes.Count; index++)
                        {
                            if (treeNodes[index].id == x)
                            {
                                redt.Add(treeNodes[index]);
                                treeNodes.RemoveAt(index);
                            }
                        }
                    });
                    redt.AddRange(treeNodes);
                    return Ok(new { tree = redt });
                }
                else {
                    return Ok(new { tree = treeNodes });
                }
               
            } catch (Exception ex) {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，common/syllabus/find-id\n{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
                return Ok(new { tree= treeNodes });
            }
        }

        /*
            {"id":"章节id","code":"学校编码/醍摩豆id","scope":"school/private"}
         */

        /// <summary>
        /// 删除章节
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("delete")]
        public async Task<IActionResult> Delete(JsonElement request)
        {
            try
            {
                if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                if (scope.ToString().Equals("school"))
                {
                    Syllabus syllabus = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Syllabus>(id.ToString(), new PartitionKey($"Syllabus-{code}"));
                    if (syllabus.auth.IsNotEmpty()) {
                        foreach (var a in syllabus.auth)
                        {
                            try
                            {
                                Share share = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Share>(syllabus.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
                                share.agree = -1;
                                await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Share>(share, syllabus.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
                            }
                            catch (Exception ex)
                            {
                                ///仅用于处理查不到该数据的问题
                            }
                        }
                    }
                    var response = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Syllabus-{code}"));
                    return Ok(new { code = response.Status });
                }
                else
                {
                    Syllabus syllabus = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Syllabus>(id.ToString(), new PartitionKey($"Syllabus-{code}"));
                    if (syllabus.auth.IsNotEmpty())
                    {
                        foreach (var a in syllabus.auth)
                        {
                            try
                            {
                                Share share = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Share>(syllabus.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
                                share.agree = -1;
                                await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Share>(share, syllabus.id, new PartitionKey($"Share-{a.type}-{a.tmdid}"));
                            }
                            catch (Exception ex)
                            {
                                ///仅用于处理查不到该数据的问题
                            }
                        }
                    }
                    var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Syllabus-{code}"));
                    return Ok(new { code = response.Status });
                }
            }
            catch {
                return Ok(new { code = 404});
            }
        }
    }
}