using Azure.Cosmos;
using HTEXLib.COMM.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.Filter;
using TEAMModelOS.Models;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models;
using TEAMModelOS.SDK.Models.Cosmos;
using TEAMModelOS.SDK.Models.Cosmos.Common;
using TEAMModelOS.SDK.Models.Service;
using TEAMModelOS.Services.Common;

namespace TEAMModelOS.Controllers
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")]
    [Route("teacher/share")]
    [ApiController]
    public class ShareController : ControllerBase
    {
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly SnowflakeId _snowflakeId;
        private readonly DingDing _dingDing;
        private readonly Option _option;
        private readonly IConfiguration _configuration;
        private readonly NotificationService _notificationService;
        public ShareController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
        {
            _azureCosmos = azureCosmos;
            _snowflakeId = snowflakeId;
            _dingDing = dingDing;
            _option = option?.Value;
            _configuration = configuration;
            _notificationService = notificationService;
        }
        /*
         {
            "school": "学校编码",
            "scope":"school|private",
            "tmdInfo":["tmdid":"id1","tmdname":"name1"],
            "type":"coedit共编,share分享",
            "agree":0,1,
            "issuer":"权限颁发者tmdid",
            "opt":"add/del/edit"
            "syllabusId":"分享的课纲章节id",
            "syllabusName":"章节名称",
            "volumeId":"册别id",
            "volumeName":"册别name"
        }
         */

        /// <summary>
        /// 分享及邀请共编，并设置TTL过期时间
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("to")]
        // [AuthToken(Roles = "Teacher")]
        public async Task<IActionResult> To(ShareData request) {
            // var (id, _, _, _) = HttpContext.GetAuthTokenInfo();

            try {
                var client = _azureCosmos.GetCosmosClient();
                Syllabus syllabusD = null;
                //需要判断id== req.issuer  才能进行授权操作
                if (request.scope.Equals("school"))
                {
                    try {
                          syllabusD = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.school}"));
                    } catch (CosmosException ex) {
                        if (ex.Status == 404) {
                            await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/to\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}", GroupNames.成都开发測試群組);
                            return Ok(new { code = 404 });
                        }
                    }
                    if (request.opt .Equals("del"))
                    {
                        if (syllabusD.auth.IsNotEmpty())
                        {
                            List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
                            syllabusD.auth.ForEach(x => {
                                if (request.tmdInfo.Select(tmd => tmd.tmdid).Contains(x.tmdid)) {
                                    syllabusAuths.Add(x);
                                }
                            });
                            syllabusAuths.ForEach(x => {
                                syllabusD.auth.Remove(x);
                            });
                            await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.school}"));
                            request.tmdInfo.ForEach(async x => {
                                await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{request.type}-{x.tmdid}"));
                            });

                        }
                    }
                    else if (request.opt.Equals("add") || request.opt.Equals("edit"))
                    {
                        var schresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(request.school.ToString(), new PartitionKey("Base"));
                        string schname = string.Empty;
                        if (schresponse.Status == 200)
                        {
                            using var schjson = await JsonDocument.ParseAsync(schresponse.ContentStream);
                            schjson.RootElement.TryGetProperty("name", out JsonElement jsonschname);
                            schname = jsonschname.ToString();
                        }
                        else
                        {
                            return BadRequest();
                        }
                        (Syllabus syllabus, List<Share> shares) = DoAuth(request, syllabusD);
                        foreach (var x in shares)
                        {
                            await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"{x.code}"));
                            //发送共编或分享通知
                            Notification notification = new Notification
                            {
                                hubName = "hita",
                                type = "msg",
                                from = $"ies5:{_option.Location}:{request.school}",
                                to = new List<string>() { x.code.Replace("Share-", "").Replace($"{x.type}-", "") },
                                label = $"{x.type}_syllabus",
                                body = new { location = _option.Location, biz = x.type, tmdid = x.issuer, tmdname=x.issuerName, schoolcode = $"{request.school}", schoolname = $"{schname}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
                                expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
                            };
                            var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
                            var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                            var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
                            var location = _option.Location;
                            var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
                        }
                        await client.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<Syllabus>(syllabus, new PartitionKey($"Syllabus-{request.school}"));
                    }
                }
                else if (request.scope.Equals("private"))
                {
                    try { 
                      syllabusD = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.issuer}"));
                    }
                    catch (CosmosException ex)
                    {
                        if (ex.Status == 404)
                        {
                            await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/to\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}", GroupNames.成都开发測試群組);
                            return Ok(new { code = 404 });
                        }
                    }
                    if (request.opt .Equals("del"))
                    {
                        if (syllabusD.auth.IsNotEmpty())
                        {
                            List<SyllabusAuth> syllabusAuths = new List<SyllabusAuth>();
                            syllabusD.auth.ForEach(x => {
                                if (request.tmdInfo.Select(tmd => x.tmdid).Contains(x.tmdid))
                                {
                                    syllabusAuths.Add(x);
                                }
                            });
                            syllabusAuths.ForEach(x => {
                                syllabusD.auth.Remove(x);
                            });
                            await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.issuer}"));
                            request.tmdInfo.ForEach(async x => {
                                try {
                                    await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{request.type}-{x.tmdid}"));
                                } catch 
                                {
                                    //仅处理找不到数据的情况
                                }
                            });
                        }
                    }
                    else if (request.opt.Equals("add") || request.opt.Equals("edit"))
                    {
                        (Syllabus vlm, List<Share> shares) = DoAuth(request, syllabusD);
                        foreach (var x in shares) {
                            await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"{x.code}"));
                            //发送共编或分享通知
                            Notification notification = new Notification
                            {
                                hubName = "hita",
                                type = "msg",
                                from = $"ies5:{_option.Location}:private",
                                to = new List<string>() { x.code.Replace("Share-", "") .Replace($"{x.type}-", "") },
                                label = $"{x.type}_syllabus",
                                body = new { location = _option.Location, biz = x.type, tmdid = x.issuer, tmdname = x.issuerName, status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
                                expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
                            };
                            var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
                            var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
                            var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
                            var location = _option.Location;
                            var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
                        }
                        await client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<Syllabus>(syllabusD, new PartitionKey($"Syllabus-{request.issuer}"));
                    }
                }
                return Ok(new { code = 200 });
            }
            catch (Exception ex) {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/to\n{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
            }
            return Ok(new { code = 500 });
        }

        private (Syllabus, List<Share>) DoAuth(ShareData request, Syllabus syllabus)
        {
            long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            List<Share> shares = new List<Share>();
            request.tmdInfo.ForEach(xmd => {
                var share = new Share
                {
                    id = request.syllabusId,
                    volumeId = request.volumeId,
                    volumeName = request.volumeName,
                    syllabusName = request.syllabusName,
                    code = $"Share-{request.type}-{xmd.tmdid}",
                    pk = "Share",
                    ttl = -1,
                    issuer = request.issuer,
                    issuerName=request.issuerName,
                    createTime = now,
                    school = request.school,
                    scope = request.scope,
                    type = request.type,
                    agree = request.agree
                };
                shares.Add(share);
            });

            if (syllabus.auth.IsNotEmpty())
            {
                request.tmdInfo.ForEach(xmd => {

                    bool flag = false;
                    int indx = 0;
                    for (int index = 0; index < syllabus.auth.Count; index++)
                    {
                        if (syllabus.auth[index].tmdid == xmd.tmdid && request.type == syllabus.auth[index].type)
                        {
                            flag = true;
                            indx = index;
                            break;
                        }
                    }
                    ///更新位置上的授权信息
                    if (flag)
                    {
                        syllabus.auth[indx] = new SyllabusAuth
                        {
                            tmdid = xmd.tmdid,
                            tmdname = xmd.tmdname,
                            type = request.type,
                            agree = request.agree,
                        };
                    }
                    //新增
                    else
                    {
                        syllabus.auth.Add(new SyllabusAuth
                        {
                            tmdid = xmd.tmdid,
                            tmdname = xmd.tmdname,
                            type = request.type,
                            agree = request.agree,
                        });
                    }
                });
            }
            else
            {
                request.tmdInfo.ForEach(xmd => {
                    syllabus.auth = new List<SyllabusAuth>() {
                        new SyllabusAuth {
                            tmdid = xmd.tmdid,
                            tmdname = xmd.tmdname,
                            type = request.type,
                            agree = request.agree,
                        }
                    };
                });
            }
            return (syllabus, shares);
        }
        /// <summary>
        /// {"code":"教师编码","id":"章节id","type":"coedit/share","opt":"ignore/agree"} 
        /// 
        /// 教师操作收到的分享及课纲共编， ignore 忽略，需要删除Share 数据 并更新syllabus.auth
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("agree-share")]
        // [AuthToken(Roles = "Teacher")]
        public async Task<IActionResult> AgreeShare(JsonElement request) {
            try {
                if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
                if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
                if (!request.TryGetProperty("ids", out JsonElement ids)) { return BadRequest(); }
                if (!request.TryGetProperty("opt", out JsonElement opt)) { return BadRequest(); }
                var client = _azureCosmos.GetCosmosClient();
                if (ids.ValueKind.Equals(JsonValueKind.Array)) {
                    List<string> idss = ids.ToObject<List<string>>();
                    foreach (var id in idss) {
                        Share share = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
                        if ($"{opt}".Equals("agree"))
                        {
                            share.agree = 1;
                            await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Share>(share, $"{id}", new PartitionKey($"Share-{type}-{code}"));
                        }
                        else if ($"{opt}".Equals("ignore"))
                        {
                            await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
                        }

                        Syllabus syllabus = null;
                        if (share.scope .Equals("school"))
                        {
                            try
                            {
                                syllabus = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.school}"));
                            }
                            catch
                            {
                                //仅处理差不到数据的情况
                            }
                        }
                        else if (share.scope .Equals("private"))
                        {
                            try
                            {
                                syllabus = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.issuer}"));
                            }
                            catch
                            {
                            }
                        }
                        if (syllabus != null)
                        {
                            if (syllabus.auth.IsNotEmpty())
                            {
                                syllabus.auth.ForEach(x =>
                                {
                                    if (x.tmdid == $"{code}" && x.type == $"{type}")
                                    {
                                        if ($"{opt}".Equals("ignore"))
                                        {
                                            x.agree = 0;
                                        }
                                        else if ($"{opt}".Equals("agree"))
                                        {
                                            x.agree = 1;
                                        }

                                    }
                                });
                            }
                            if (share.scope .Equals("school"))
                            {
                                syllabus = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.school}"));
                            }
                            else if (share.scope .Equals("private"))
                            {
                                syllabus = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.issuer}"));
                            }
                        }
                    }
                }
                return Ok(new { status = 200 });
            } catch (Exception ex) {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/agree-share()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                return Ok(new { status = 500 });
            }
        }
        /// <summary>
        /// 删除共享记录
        /// {"id":"章节id","type:"coedit/share","code":"教师tmdid"}
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("del-share")]
        public async Task<IActionResult> DelShare(JsonElement request) {
            try
            {
                var client = _azureCosmos.GetCosmosClient();
                if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
                if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
                if (!request.TryGetProperty("id", out JsonElement id)) { return BadRequest(); }
                await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
                return Ok(new { status = 200 });
            } catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/del-share()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                return Ok(new { status = 500 });
            }
        }
        /// <summary>
        /// {"code":"教师编码","type":"coedit/share","id":"册别id"} 
        /// 教师拉取自己收到的分享及共编
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("find")]
       // [AuthToken(Roles = "Teacher")]
        public async Task<IActionResult> Find(JsonElement request)
        {
            try
            {
                List<Share> shares = new List<Share>();
                if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
                if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
                request.TryGetProperty("id", out JsonElement id);
                var client = _azureCosmos.GetCosmosClient();
                StringBuilder queryText = new StringBuilder("select value(c) from c");
                queryText.Append($" where c.type='{type}' ");
                if (id.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrEmpty(id.GetString())) {
                    queryText.Append($" and c.id='{id}'");
                }
                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Share>(queryText: queryText.ToString(),
                requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Share-{type}-{code}") }))
                {
                    shares.Add(item);
                }
                var sharesGp  =  shares.GroupBy(x => new {id= x.volumeId ,code=x.scope=="school"?x.school:x.issuer, issuerName=x.issuerName }).Select(y=>new { id=y.Key.id,code=y.Key.code, issuerName=y.Key.issuerName, list=y.ToList()});
                return Ok(new { shares = sharesGp ,status=200});
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/find()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
                return Ok(new {  status = 404 });
            }

        }

        public record ShareView
        {
            public string scope { get; set; }
           // public string code { get; set; }
            public string school { get; set; }
            public string issuer { get; set; }
            public string volumeId { get; set; }
            public List<string> syllabusId { get; set; }
        }

        /*
            {
                "scope": "school/private",
                "school": "学校编码",
                "issuer": "权限颁发者",
                "volumeId": "册别id",
                "syllabusId": ["id1课纲章节节点id","id2课纲章节节点id"],
            }
         */
        /// <summary>
        /// 查看分享
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("view-share")]
       [AuthToken(Roles = "teacher")]
        public async Task<IActionResult> View(ShareView request)
        {
            try
            {
                List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
                Volume volume;
                var client = _azureCosmos.GetCosmosClient();
                string code = null;
                List<string> sid = new List<string>();
                request.syllabusId.ForEach(x => { sid.Add($"'{x}'"); });
                var sidSql= string.Join(",", sid);
                if (request.scope .Equals("school"))
                {
                    code = request.school;
                    var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.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 };
                        treeNodes.Add(tree);

                    }
                    volume = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
                    
                }
                else if (request.scope .Equals("private"))
                {
                    code = request.issuer;
                    var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.issuer}") }))
                    {
                        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 };
                        treeNodes.Add(tree);
                    }
                    volume = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Volume>(request.volumeId, new PartitionKey($"Volume-{code}"));
                }
                else
                {
                    return BadRequest();
                }
                
                return Ok(new { volume,tree= treeNodes });
            }
            catch (Exception ex) {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，teacher/share/view()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        /// <summary>
        ///二维码扫码方式
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("qrcode")]
        //[AuthToken(Roles = "Teacher")]
        public async Task<IActionResult> Qrcode(Favorite request)
        {
            return Ok();
        }
    }
   
}
