using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.SDK;
using TEAMModelOS.SDK.DI;

using TEAMModelOS.SDK.Models;
using TEAMModelOS.SDK.Helper.Common.StringHelper;
using Microsoft.AspNetCore.Http;
using System.IdentityModel.Tokens.Jwt;
using Azure.Cosmos;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
using System.Text;
using Azure.Messaging.ServiceBus;
using Microsoft.Extensions.Configuration;

namespace TEAMModelOS.Controllers
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")]
    [Route("paper")]
    [ApiController]
    public class PaperController: ControllerBase
    {
        private readonly SnowflakeId _snowflakeId;
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly AzureStorageFactory _azureStorage;
        private readonly AzureServiceBusFactory _serviceBus;
        public IConfiguration _configuration { get; set; }
        public PaperController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId,AzureStorageFactory azureStorage, AzureServiceBusFactory serviceBus, IConfiguration configuration)
        {
            _azureCosmos = azureCosmos;
            _snowflakeId = snowflakeId;
            _azureStorage = azureStorage;
            _serviceBus = serviceBus;
            _configuration = configuration;
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("delete")]
        public async Task<IActionResult> Delete(JsonElement request)
        {
            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
            if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
            //ResponseBuilder builder = ResponseBuilder.custom();
            Paper paper;
            var client = _azureCosmos.GetCosmosClient();
            //删除blob 相关资料
            await _azureStorage.GetBlobServiceClient().DelectBlobs(code.ToString().Replace("Paper-",""), $"paper/{id}");
            //通知删除信息
            var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"paper/{id}", name = code.ToString().Replace("Paper-", "")}.ToJsonString());
            messageBlob.ApplicationProperties.Add("name", "BlobRoot");
            var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
            await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
            if (scope.ToString().Equals("school"))
            {
                paper = await client.GetContainer("TEAMModelOS", "School").DeleteItemAsync<Paper>(id.ToString(), new PartitionKey($"{code}"));
            }
            else {
                paper = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Paper>(id.ToString(), new PartitionKey($"{code}"));
            }

            //IdPk items = await _azureCosmos.DeleteAsync<Paper>(request.id, request.pk);
            return Ok(new { paper });
        }

        /// <summary>
        /// 查询试卷摘要信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-summary")]
        public async Task<IActionResult> findSummary(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
            if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
            var jwt = new JwtSecurityToken(id_token.GetString());
            if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
            var id = jwt.Payload.Sub;
            var client = _azureCosmos.GetCosmosClient();
            List<object> papers = new List<object>();
            var query = $"select c.id,c.subjectCode,c.code,c.periodCode,c.name,c.itemCount,c.level,c.pointItem,c.pointScore,c.score,c.gradeCode from c where c.id = {id}";
            await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{school_code}") }))
            {
                using var json = await JsonDocument.ParseAsync(item.ContentStream);
                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                {
                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                    {
                        papers.Add(obj.ToObject<object>());
                    }
                }
            }
            return Ok(new { papers });
            /* List<string> props = new List<string> {
                 "subjectCode", "id", "code", "periodCode",
                 "name","itemCount","level","pointItem","pointScore","score", "gradeCode"
             };
             if (StringHelper.getKeyCount(request) > 0)
             {
                 return builder.Data(await _azureCosmos.FindByDict<Paper>(request, propertys: props)).build();
             }
             else {
                 return builder.build();
             }*/

        }

        /// <summary>
        /// 查询试卷
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find")]
        public async Task<IActionResult> Find(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
            if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
            if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
            /*var jwt = new JwtSecurityToken(id_token.GetString());
            if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.Ordinal)) return BadRequest();
            var id = jwt.Payload.Sub;*/
            var client = _azureCosmos.GetCosmosClient();
            StringBuilder sql = new StringBuilder();
            Dictionary<string, object> dict = new Dictionary<string, object>();
            var emobj = requert.EnumerateObject();
            while (emobj.MoveNext())
            {
                dict[emobj.Current.Name] = emobj.Current.Value;
            }
            //处理code
            if (dict.TryGetValue("code", out object _))
            {
                dict.Remove("code");
            }           
            List<object> papers = new List<object>();
            
            if (scope.ToString().Equals("school"))
            {
                sql.Append("select c.id,c.code,c.name,c.blob,c.periodId,c.gradeIds,c.subjectId,c.subjectName,c.score,c.useCount,c.scope,c.scoring from c");
                AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
                {
                    using var json = await JsonDocument.ParseAsync(item.ContentStream);

                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                    {
                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                        {
                            papers.Add(obj.ToObject<object>());
                        }
                    }
                }
            }
            if (scope.ToString().Equals("private"))
            {
                sql.Append("select c.id,c.code,c.name,c.blob,c.subjectName,c.score,c.useCount,c.scope,c.scoring from c");
                AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
                await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
                {
                    using var json = await JsonDocument.ParseAsync(item.ContentStream);

                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                    {
                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                        {
                            papers.Add(obj.ToObject<object>());
                        }
                    }
                }
            }
            return Ok(new { papers });
            /*if (StringHelper.getKeyCount(request) > 0) {
                return builder.Data(await _azureCosmos.FindByDict<Paper>(request)).build();
            }
            else
            {
                return builder.build();
            }*/

        }
        /// <summary>
        /// 保存试卷
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("upsert")]
        public async Task<IActionResult> Upsert(JsonElement request)
        {
            var client = _azureCosmos.GetCosmosClient();
            if (!request.TryGetProperty("paper", out JsonElement papers)) return BadRequest();
            if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
            Paper paper;
            paper = papers.ToObject<Paper>();            
            paper.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            paper.size = await _azureStorage.GetBlobContainerClient(paper.code).GetBlobsSize($"paper/{paper.id}");
            var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"paper/{paper.id}", name = $"{paper.code}" }.ToJsonString());
            messageBlob.ApplicationProperties.Add("name", "BlobRoot");
            var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
            await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
            paper.code = "Paper-" + paper.code;
            if (option.ToString().Equals("insert"))
            {               
                var response = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(paper.id, new PartitionKey($"{paper.code}"));
                if (response.Status == 200)
                {
                    return Ok(new { error = ResponseCode.DATA_EXIST, V = "试卷已经存在！" });
                }
                else
                {
                    if (paper.scope.Equals("private"))
                    {
                        //paper.JsonRemove("periodId");
                        paper = await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(paper, new PartitionKey($"{paper.code}"));
                    }
                    else
                    {
                        //paper.JsonRemove("periodId");
                        paper = await client.GetContainer("TEAMModelOS", "School").CreateItemAsync(paper, new PartitionKey($"{paper.code}"));
                    }
                }
            }
            else
            {
                if (paper.scope.Equals("private"))
                {
                    paper = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(paper, paper.id, new PartitionKey($"{paper.code}"));
                }
                else
                {
                    paper = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(paper, paper.id, new PartitionKey($"{paper.code}"));
                }
            }
            return Ok(new { paper });
            /*ResponseBuilder builder = ResponseBuilder.custom();
            if (string.IsNullOrEmpty(request.id))
            {
                request.id = _snowflakeId.NextId() + ""; 
                request.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                await _azureCosmos.SaveOrUpdate(request);
            }
            else
            {
                await _azureCosmos.SaveOrUpdate(request);
            }
            
            return builder.Data(request).build();*/
            //return Ok();
        }

    }
}
