using Azure.Cosmos;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.Models.Dto;
using TEAMModelOS.SDK.Models;
using TEAMModelOS.SDK;
using TEAMModelOS.SDK.Context.Constant.Common;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
using TEAMModelOS.SDK.Helper.Common.StringHelper;

namespace TEAMModelOS.Controllers.Learn
{
    /// <summary>
    /// 投票活动
    /// </summary>
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")]
    [Route("common/vote")]
    [ApiController]
    public class VoteController : ControllerBase
    {
        private readonly SnowflakeId _snowflakeId;
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly AzureServiceBusFactory _serviceBus;

        public VoteController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId)
        {
            _snowflakeId = snowflakeId;
            _azureCosmos = azureCosmos;
            _serviceBus = serviceBus;
        }


        /// <summary>
        /// 新增 或 修改投票活动
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("upsert")]
        public async Task<IActionResult> Upsert(VoteDto request)
        {
            /*ResponseBuilder builder = ResponseBuilder.custom();
            //新增
            if (string.IsNullOrEmpty(request.vote.id))
            {
                request.vote.id = _snowflakeId.NextId()+"";
                request.vote.status = 100;
                request.vote.code = typeof(Vote).Name + "-" + request.vote.code;
            }
            if (request.vote.publishModel.Equals("0"))
            {
                request.vote.startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                request.vote.status = 200;
                
            } else if (request.vote.publishModel.Equals("1")) {

                string msgId = _snowflakeId.NextId() + "";
                long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime, 200, msgId);
                request.vote.sequenceNumber = SequenceNumber;
            }*/


            //新增ote
            //string code = request.vote.code;
            var client = _azureCosmos.GetCosmosClient();
            Vote vote = new Vote();
            request.vote.school = request.vote.code;
            request.vote.code = request.vote.pk + "-" + request.vote.code;
            request.vote.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
            /*if (request.vote.publishModel.Equals("0"))
            {
                //request.vote.startTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                request.vote.progress = "going";
            }
            else if (request.vote.publishModel.Equals("1"))
            {

                string msgId = _snowflakeId.NextId() + "";
                long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Survey>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime, "going", msgId);
                request.vote.sequenceNumber = SequenceNumber;

            }*/
            if (string.IsNullOrEmpty(request.vote.id))
            {
                request.vote.id = Guid.NewGuid().ToString();
                //request.survey.status = 100;
                request.vote.progress = "pending";
                /* long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
                 request.vote.sequenceNumber = SequenceNumber;*/
                vote = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request.vote, new PartitionKey($"{request.vote.code}"));
                /*if (request.vote.scope.Equals("school"))
                {
                    vote = await client.GetContainer("TEAMModelOS", "School").CreateItemAsync(request.vote, new PartitionKey($"Vote-{code}"));
                }
                else
                {
                    vote = await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(request.vote, new PartitionKey($"Vote-{code}"));
                }*/
            }
            else
            {
                Vote info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Vote>(request.vote.id, new PartitionKey($"{request.vote.code}"));
                if (info.progress.Equals("going"))
                {
                    return Ok(new { v = "活动正在进行中" });
                }
                //request.vote.code = info.code;
                request.vote.progress = info.progress;
                /* await _serviceBus.GetServiceBusClient().cancelMessage(Constants.TopicName,info.sequenceNumber);
                 long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.startTime);
                 request.vote.sequenceNumber = SequenceNumber;*/
                vote = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request.vote, info.id, new PartitionKey($"{info.code}"));
                /*if (request.vote.scope.Equals("school"))
                {
                    vote = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(request.vote, request.vote.id, new PartitionKey($"{request.vote.code}"));
                }
                else
                {
                    vote = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(request.vote, request.vote.id, new PartitionKey($"{request.vote.code}"));
                }*/
            }
            //Vote homeWork = await _azureCosmos.SaveOrUpdate<Vote>(request.vote);

            //设定结束时间
            //_timerWorkService.TimerWork<Vote>(request.vote.endTime, 300, new Dictionary<string, object> { { "id", request.vote.id } });
            //设定结束时间
            //await _serviceBus.GetServiceBusClient().SendLeamMessage<Vote>(Constants.TopicName, request.vote.id, request.vote.code, request.vote.endTime);
            //清除作业
            /*  if (!request.reset)
              {
                  //根据作业发布对象查找到每一个具体学生生成关联关系表 HomeWorkStudent

                  List<VoteRecord> voteRecords = await _azureCosmos.FindByDict<VoteRecord>(new Dictionary<string, object> { { "id", request.vote.id } });

                  if (voteRecords.IsNotEmpty())
                  {
                      await _azureCosmos.DeleteAll(voteRecords);
                  }*/
            //List<Target> targets = request.@params.vote.target;
            //List<VoteRecord> votekStudents = new List<VoteRecord>();
            //foreach (Target target in targets)
            //{
            //    //查询之前是否有 关联关系表 HomeWorkStudent 有则删除

            //    List<ClassStudent> classroom = await _cosmos.FindByDict<ClassStudent>(new Dictionary<string, object> { { "id", target.classroomCode } });
            //    if (classroom.IsNotEmpty() && classroom[0].code!=null)
            //    {
            //        foreach (ClassStudent student in classroom)
            //        {
            //            VoteRecord voteStudent = new VoteRecord();
            //            voteStudent.id = request.@params.vote.id;
            //            voteStudent.code = student.code;
            //            voteStudent.classroom.code = target.classroomCode;
            //            voteStudent.classroom.name = target.classroomName;
            //            votekStudents.Add(voteStudent);
            //        }
            //    }
            //}
            //if (votekStudents.IsNotEmpty())
            //{
            //    foreach (VoteRecord voteRecord in votekStudents)
            //    {
            //        List<Student> student = await _cosmos.FindByDict<Student>(new Dictionary<string, object> { { "studentId", voteRecord.code } });
            //        if (student.IsNotEmpty())
            //        {
            //            voteRecord.name = student[0].name;
            //            voteRecord.code = student[0].studentId;
            //        }
            //    }
            //    await _cosmos.SaveOrUpdateAll(votekStudents);
            //}
            /*            }*/
            //return builder.Data(homeWork).build();
            return Ok(new { vote });
        }

        /// <summary>
        /// 查询投票活动
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>

        [ProducesDefaultResponseType]
        [HttpPost("find")]
        public async Task<IActionResult> Find(JsonElement requert)
        {

            var client = _azureCosmos.GetCosmosClient();
            if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
            if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
            StringBuilder sql = new StringBuilder();
            sql.Append("select c.id,c.code,c.name,c.targetClassIds,c.options,c.description,c.status,c.startTime,c.selectMax,c.endTime,c.secret,c.progress from c ");
            /*if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
            if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
            if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();
            if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest();*/
            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");
            }
            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
            List<object> votes = new List<object>();
            await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{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())
                    {
                        votes.Add(obj.ToObject<object>());
                    }
                }
            }
            /*if (scope.ToString().Equals("school"))
            {
                await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{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())
                        {
                            votes.Add(obj.ToObject<object>());
                        }
                    }
                }
            }
            else
            {
                await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{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())
                        {
                            votes.Add(obj.ToObject<object>());
                        }
                    }
                }
            }*/


            return Ok(new { votes, votes.Count });
            /*ResponseBuilder builder = ResponseBuilder.custom();
            List<Vote> data = new List<Vote>();
            if (StringHelper.getKeyCount(request) > 0)
            {
                data = await _azureCosmos.FindByDict<Vote>(request);
            }
            else
            {
                return builder.Error(ResponseCode.PARAMS_ERROR, "参数异常！").build();

            }
            return builder.Data(data).Extend(new Dictionary<string, object> { { "count", data.Count } }).build();*/
        }

        /// <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();
                var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
                return Ok(new { code = response.Status });
                /*if (scope.ToString().Equals("school"))
                {
                    var response = await client.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
                    return Ok(new { code = response.Status });
                }
                else
                {
                    var response = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
                    return Ok(new { code = response.Status });
                }*/

            }
            catch (Exception e)
            {
                return BadRequest();
            }
            //ResponseBuilder builder = ResponseBuilder.custom();
            /* List<IdPk> idPks = await _azureCosmos.DeleteAll<Vote>(request);
             if (idPks.IsNotEmpty())
             {
                 foreach (IdPk idPk in idPks) 
                 { 
                     List<VoteRecord> votes =  await _azureCosmos.FindByDict<VoteRecord>(new Dictionary<string, object> {  { "id", idPk.id } });
                     await _azureCosmos.DeleteAll(votes);
                 }
                 //builder.Data(idPks);
             }
             else
             {
                 return Ok("删除失败！");
                 //return builder.Error(ResponseCode.FAILED, "删除失败！").build();
             }
             return Ok(idPks);*/
            //return builder.build();
        }

        // TODO 优化代码

        /// <summary>
        /// 撤消投票
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("cancel")]
        public async Task<IActionResult> Cancel(JsonElement request)
        {
            //request.TryGetProperty("id", out JsonElement voteId);
            ////ResponseBuilder builder = ResponseBuilder.custom();
            //List<Vote> votes = await _azureCosmos.FindByDict<Vote>(new Dictionary<string, object> { { "id", voteId } });

            //foreach (Vote vote in votes)
            //{
            //    vote.status = 100;
            //    vote.progress = "pending";
            //}
            //List<Vote> vote1 = await _azureCosmos.UpdateAll<Vote>(votes);

            ////查询之前是否有 关联关系表 HomeWorkStudent 有则删除
            //List<VoteRecord> voteStudents = await _azureCosmos.FindByDict<VoteRecord>(new Dictionary<string, object> { { "id", voteId } });
            //if (voteStudents.IsNotEmpty())
            //{
            //    await _azureCosmos.DeleteAll(voteStudents);
            //}
            ////return builder.Data(vote1).build();
            //return Ok(vote1);
            return Ok();
        }

        // TODO 代码优化

        /// <summary>
        /// 查询 投票 学生关联
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("find-record")]
        public async Task<IActionResult> FindRecord(JsonElement request)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //List<VoteRecord> data = new List<VoteRecord>();
            //List<Options> options = new List<Options>();

            //if (StringHelper.getKeyCount(request) > 0)
            //{
            //    data = await _azureCosmos.FindByDict<VoteRecord>(request);
            //    if (data.IsNotEmpty()) {
            //        List< Vote > votes = await _azureCosmos.FindByDict<Vote>(new Dictionary<string, object> { { "id", data[0].id } });
            //        List<OptionsVote> options2 = votes[0].options;
            //        foreach (IGrouping<string, VoteRecord> voteStudents in data.GroupBy(x => x.option))
            //        {
            //            Options options1 = new Options();
            //            options1.optionKey = voteStudents.Key;
            //            options2.ForEach(x => { if (x.code == voteStudents.Key) options1.optionValue = x.value; });
            //            if(options1.optionValue == null) options1.optionValue = "Null";
            //            foreach (VoteRecord voteStudent in voteStudents)
            //            {
            //                options1.students.Add(voteStudent);
            //            }
            //            options.Add(options1);
            //        }
            //    }
            //}
            //else
            //{
            //    //return builder.Error(ResponseCode.PARAMS_ERROR, "参数异常！").build();
            //    return Ok("参数异常！");
            //}
            ////return builder.Data(options).Extend(new Dictionary<string, object> { { "count", data.Count } }).build();
            //return Ok(new { options, data.Count });
            return Ok();
        }

        // TODO 代码优化

        /// <summary>
        /// 学生投票
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [HttpPost("upsert-record")]
        public async Task<IActionResult> UpsertRecord(List<VoteRecord> request)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //await _azureCosmos.SaveOrUpdateAll<VoteRecord>(request);
            return Ok(request);
            //return builder.Data(request).build();
        }


        public class Options
        {

            public Options()
            {
                students = new List<VoteRecord>();
            }

            /// <summary>
            /// 选项Key
            /// </summary>
            public string optionKey { get; set; }

            /// <summary>
            /// 选项value
            /// </summary>
            public string optionValue { get; set; }

            /// <summary>
            /// 选项人
            /// </summary>
            public List<VoteRecord> students { get; set; }
        }

    }
}