using Azure.Cosmos;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.Models;
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
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")
    [Route("common/exam")]
    [ApiController]
    public class ExamController : ControllerBase
    {
        private readonly AzureCosmosFactory _azureCosmos;
        private readonly SnowflakeId _snowflakeId;
        private readonly AzureServiceBusFactory _serviceBus;
        private readonly DingDing _dingDing;
        private readonly Option _option;
        private readonly AzureStorageFactory _azureStorage;

        public ExamController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage)
        {
            _azureCosmos = azureCosmos;
            _serviceBus = serviceBus;
            _snowflakeId = snowflakeId;
            _dingDing = dingDing;
            _option = option?.Value;
            _azureStorage = azureStorage;
        }

        /// <summary>
        /// 保存考试信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("save")]
        public async Task<IActionResult> Save(ExamInfo request)
        {
            try
            {
                //新增
                //string code = request.code;
                var client = _azureCosmos.GetCosmosClient();
                ExamInfo exam;
                string code = request.code;
                request.code = "Exam-" + request.code;
                request.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                if (string.IsNullOrEmpty(request.id))
                {
                    request.id = Guid.NewGuid().ToString();
                    request.progress = "pending";
                    int count = 0;
                    for (int i = 0; i < request.targetClassIds.Count; i++)
                    {
                        if (request.scope.Equals("private") || request.scope.Equals("teacher"))
                        {
                             var sresponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(request.targetClassIds[i], new PartitionKey($"Class-{code}"));
                            if (sresponse.Status == 200)
                            {
                                using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                Class classroom = json.ToObject<Class>();
                                count += classroom.students.Count;
                            }
                        }
                        else {
                             var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(request.targetClassIds[i], new PartitionKey($"Class-{code}"));
                            if (sresponse.Status == 200)
                            {
                                using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                Class classroom = json.ToObject<Class>();
                                count += classroom.students.Count;
                            }
                        }
                        
                        
                    }
                    request.stuCount = count;
                    foreach (PaperSimple simple in request.papers) {
                        simple.blob = "/exam/" + request.id + "/paper/" + simple.id;
                    }
                    //request.papers
                    /*long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
                    request.sequenceNumber = SequenceNumber;*/
                    exam = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
                    //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
                    //request.sequenceNumber = SequenceNumber;
                }
                else
                {
                    ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(request.id, new PartitionKey($"{request.code}"));
                    if (info.progress.Equals("going"))
                    {
                        return Ok(new { v = "活动正在进行中" });
                    }
                    request.progress = info.progress;
                    foreach (PaperSimple simple in request.papers)
                    {
                        simple.blob = "/exam/" + request.id + "/paper/" + simple.id;
                    }
                    /*  await _serviceBus.GetServiceBusClient().cancelMessage(Constants.TopicName, info.sequenceNumber);
                      long SequenceNumber = await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
                      request.sequenceNumber = SequenceNumber;*/
                    exam = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request, request.id, new PartitionKey($"{request.code}"));
                    //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.startTime);
                }
                //Survey homeWork = await _azureCosmos.SaveOrUpdate<Survey>(request.survey);

                //设定结束时间
                //string msgEndId = _snowflakeId.NextId() + "";
                //await _serviceBus.GetServiceBusClient().SendLeamMessage<ExamInfo>(Constants.TopicName, request.id, request.code, request.endTime);
                return Ok(new { exam });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        //TODO blob 批量删除
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("delete")]
        public async Task<IActionResult> Delete(JsonElement request)
        {
            /* ResponseBuilder builder = ResponseBuilder.custom();
             IdPk items = await _azureCosmos.DeleteAsync<ExamInfo>(request.id, request.pk);
             await _azureCosmos.DeleteAll<Paper>(new Dictionary<string, object>() { { "code", request.id } });
             return builder.Data(items).build();*/
            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();
                //string school_code = code.ToString().Substring(typeof(ExamClassResult).Name.Length + 1);
                var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{code}"));
                List<ExamClassResult> examClassResults = new List<ExamClassResult>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{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())
                        {
                            examClassResults.Add(obj.ToObject<ExamClassResult>());
                        }
                    }
                }
                foreach (ExamClassResult classResult in examClassResults)
                {
                    await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(classResult.id, new PartitionKey($"ExamClassResult-{code}"));
                }
                //await _azureCosmos.DeleteAll(examClassResults);
                return Ok(new { id });



            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/delete()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }
        }
        /// <summary>
        /// 查询考试信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find")]
        public async Task<IActionResult> Find(JsonElement requert)
        {
            try
            {
                //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("school", out JsonElement school_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();
                List<ExamInfo> examInfo = new List<ExamInfo>();
                var query = $"select c.id,c.name,c.code,c.period,c.startTime,c.endTime,c.stuCount,c.type,c.progress,c.examType,c.createTime, c.subjects, c.grades, c.scope from c ";
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{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())
                        {
                            //obj.TryGetProperty("progress", out JsonElement progress);
                            examInfo.Add(obj.ToObject<ExamInfo>());
                        }
                    }
                }               
                return Ok(new { examInfo });
                /*if (StringHelper.getKeyCount(request) > 0)
                {
                    return builder.Data(await _azureCosmos.FindByDict<ExamInfo>(request)).build();
                }
                else {
                    return builder.build();
                }*/
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-summary")]
        public async Task<IActionResult> FindSummary(JsonElement requert)
        {
            try
            { 
                //ResponseBuilder builder = ResponseBuilder.custom();
                //if (!requert.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
                if (!requert.TryGetProperty("id", out JsonElement id)) 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();
                List<ExamInfo> examInfo = new List<ExamInfo>();
                //var query = $"select value(c) from c ";
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{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())
                        {
                            //obj.TryGetProperty("progress", out JsonElement progress);
                            examInfo.Add(obj.ToObject<ExamInfo>());
                        }
                    }
                }
                return Ok(new { examInfo });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        
        /// <summary>
        /// 学生回答问题
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("upsert-record")]
        public async Task<IActionResult> upsertRecord(JsonElement request)
        {

            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
            //if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
            if (!request.TryGetProperty("answer", out JsonElement answer)) return BadRequest();
            if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
            if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
            if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
            if (!request.TryGetProperty("multipleRule", out JsonElement multipleRule)) return BadRequest();
            //if (!request.TryGetProperty("answers ", out JsonElement tandardAnswer)) return BadRequest();
            if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
            //根据不同评测的类型返回对应的编码
            if (!request.TryGetProperty("code", out JsonElement school)) return BadRequest();
            try
            {
                var client = _azureCosmos.GetCosmosClient();
                List<ExamClassResult> examClassResults = new List<ExamClassResult>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
                    queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
                {
                    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())
                        {
                            examClassResults.Add(obj.ToObject<ExamClassResult>());
                        }
                    }
                }

                ExamClassResult classResult = new ExamClassResult() ;
                List<PaperSimple> standerAnswers = new List<PaperSimple>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
                    queryText: $"select A0.point,A0.answers from c join A0 in c.papers where c.id = '{id}'and A0.id = '{paperId}'",
                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{school}") }))
                {
                    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())
                        {
                            standerAnswers.Add(obj.ToObject<PaperSimple>());
                        }
                    }
                }
                List<List<string>> ans = answer.ToObject<List<List<string>>>();
                List<List<string>> standard = new List<List<string>>();
                List<double> points = new List<double>();
                int rule = int.Parse(multipleRule.ToString());
                foreach (PaperSimple simple in standerAnswers) {
                    standard = simple.answers;
                    points = simple.point;
                }
                List<Task<string>> tasks = new List<Task<string>>();
                foreach (ExamClassResult result in examClassResults) {
                    int index = result.studentIds.IndexOf(studentId.ToString());
                    //classResult.studentAnswers[index] = ans;
                    if (index == -1)
                    {
                        List<double> ansPoint = new List<double>();
                        foreach (List<string> num in standard)
                        {
                            //ans.Add(new List<string>());
                            ansPoint.Add(-1);
                        }
                        result.studentIds.Add(studentId.ToString());
                        result.studentScores.Add(ansPoint);
                        result.studentAnswers.Add(new List<string>());
                        result.sum.Add(0);
                    }
                    //int flagCount = 0;
                    /*foreach (List<string> str in ans) {

                            if (str.Count == 0) {
                                flagCount++;
                        }
                    }    */                
                    int newIndex = result.studentIds.IndexOf(studentId.ToString());
                    /*if (flagCount != standard.Count)
                    {*/
/*                    StringBuilder builder = new StringBuilder();
                    builder.Append(result.examId + "/");
                    builder.Append(result.subjectId + "/");
                    builder.Append(studentId);*/
                        string FileName = result.examId + "/" + result.subjectId + "/" + studentId;
                        string blob = FileName + "/" + "ans.json";
                        tasks.Add(_azureStorage.UploadFileByContainer(school.ToString(), ans.ToJsonString(), "exam", FileName + "/" + "ans.json", false));
                        result.studentAnswers[newIndex].Add(blob);
                    //}                  
                    for (int i = 0; i < ans.Count; i++)
                    {                         
                        //result.studentAnswers[index][i] = ans[i];
                        //算分处理
                        if (standard[i].Count > 0)
                        {
                            if (ans[i].Count == standard[i].Count && standard[i].Count == 1)
                            {
                                foreach (string right in ans[i])
                                {
                                    if (standard[i].Contains(right))
                                    {
                                        result.studentScores[newIndex][i] = points[i];
                                    }
                                    else
                                    {
                                        result.studentScores[newIndex][i] = 0;
                                    }
                                }

                            }
                            else
                            {
                                if (rule > 0)
                                {
                                    int falseCount = 0;
                                    if (ans[i].Count > 0)
                                    {
                                        foreach (string obj in ans[i])
                                        {
                                            if (!standard[i].Contains(obj))
                                            {
                                                falseCount++;
                                            }
                                        }
                                        switch (rule)
                                        {
                                            case 1:
                                                if (ans[i].Count == standard[i].Count)
                                                {
                                                    if (falseCount == 0)
                                                    {
                                                        result.studentScores[newIndex][i] = points[i];
                                                    }
                                                    else
                                                    {
                                                        result.studentScores[newIndex][i] = 0;
                                                    }
                                                }
                                                else
                                                {
                                                    result.studentScores[newIndex][i] = 0;
                                                }
                                                break;
                                            case 2:
                                                if (falseCount > 0)
                                                {
                                                    result.studentScores[newIndex][i] = 0;
                                                }
                                                else
                                                {
                                                    if (ans[i].Count == standard[i].Count)
                                                    {
                                                        result.studentScores[newIndex][i] = points[i];
                                                    }
                                                    else
                                                    {
                                                        result.studentScores[newIndex][i] = points[i] / 2;
                                                    }

                                                }
                                                break;
                                            case 3:
                                                if (falseCount > 0)
                                                {
                                                    result.studentScores[newIndex][i] = 0;
                                                }
                                                else
                                                {
                                                    if (ans[i].Count == standard[i].Count)
                                                    {
                                                        result.studentScores[newIndex][i] = points[i];
                                                    }
                                                    else
                                                    {
                                                        result.studentScores[newIndex][i] = System.Math.Round((double)ans[i].Count / standard[i].Count * points[i], 1);
                                                    }

                                                }
                                                break;
                                            case 4:
                                                if (ans[i].Count == standard[i].Count)
                                                {
                                                    result.studentScores[newIndex][i] = points[i];
                                                }
                                                else
                                                {
                                                    double persent = (double)(standard[i].Count - 2 * falseCount) / standard[i].Count;
                                                    if (persent <= 0)
                                                    {
                                                        result.studentScores[newIndex][i] = 0;
                                                    }
                                                    else
                                                    {
                                                        result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                    else {
                                        result.studentScores[newIndex][i] = 0;
                                    }
                                    
                                }
                            }
                        }
                    }
                    /*if (result.studentScores.Contains(-1)) { 

                    }*/
                    bool flag = true;
                    foreach (List<double> scores in result.studentScores)
                    {
                        foreach (double score in scores)
                        {
                            if (score == -1)
                            {
                                flag = false;
                                break;
                            }
                        }
                    }
                    if (flag)
                    {
                        ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{school}"));
                        result.progress = true;
                        exam.subjects.ForEach(s =>
                        {
                            if (s.id.Equals(subjectId.ToString()))
                            {
                                s.classCount += 1;
                            }
                        });
                        await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{school}"));
                    }
                    result.sum[newIndex] = result.studentScores[newIndex].Sum();
                    classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
                }
                await Task.WhenAll(tasks);
                
                return Ok(new { classResult });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/upsertRecord()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("upsert-record-by-teacher")]
        public async Task<IActionResult> upsertRecordByTeacher(JsonElement request)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            try
            {
                if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!request.TryGetProperty("point", out JsonElement point)) return BadRequest();
                if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
                if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
                //此参数表明此次操作对象为个人还是校本的评测内容
                if (!request.TryGetProperty("code", out JsonElement school)) return BadRequest();
                if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
                //要先处理状态，判断卷子是否存在，并判断卷子归属的考试是否允许再次提交
                //List<ExamInfo> exams = await _azureCosmos.FindByDict<ExamInfo>(new Dictionary<string, object> { { "id", request.examCode } });
                List<double> ans = point.ToObject<List<double>>();
                var client = _azureCosmos.GetCosmosClient();
                List<ExamClassResult> examClassResults = new List<ExamClassResult>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(
                    queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
                {
                    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())
                        {
                            examClassResults.Add(obj.ToObject<ExamClassResult>());
                        }
                    }
                }
                ExamClassResult classResult = new ExamClassResult();
                //ExamInfo classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{code}"));
                //ExamClassResult classResult = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamClassResult>(id.ToString(), new PartitionKey($"{code}"));
                /*foreach (double index in ans) {
                    classResult.studentScores.in
                }*/
                foreach (ExamClassResult result in examClassResults) {
                    int index = result.studentIds.IndexOf(studentId.ToString());
                    for (int i = 0; i < ans.Count; i++)
                    {
                        result.studentScores[index][i] = ans[i];
                    }
                    if (!result.progress)
                    {
                        bool flag = true;
                        foreach (List<double> scores in result.studentScores)
                        {
                            foreach (double score in scores)
                            {
                                if (score == -1)
                                {
                                    flag = false;
                                    break;
                                }
                            }
                        }
                        if (flag)
                        {
                            ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{school}"));
                            result.progress = true;
                            exam.subjects.ForEach(s =>
                            {
                                if (s.id.Equals(subjectId.ToString()))
                                {
                                    s.classCount += 1;
                                }
                            });
                            await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{school}"));
                        }
                    }
                    else
                    {
                        ExamInfo exam = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{school}"));
                        exam.updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                        await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"Exam-{school}"));
                    }
                    result.sum[index] = result.studentScores[index].Sum();
                    classResult = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
                }
                
                return Ok(new { classResult });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/upsertRecordByTeacher()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

            /*if (exams.IsNotEmpty())
            {
                ExamInfo examInfo = exams[0];
                //提交答案时间必须是状态已发布，且时间在起止时间内
                if (examInfo.startTime <= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() && examInfo.status == 200 &&
                   examInfo.endTime >= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds())
                {
                    return builder.Data(await _azureCosmos.SaveOrUpdate(request)).build();
                }
                else
                {
                    return builder.Error(ResponseCode.FAILED, "请在作答时间段内提交答案!").build();
                }
            }
            else
            {
                return builder.Error(ResponseCode.DATA_EXIST, "考试不存在!").build();
            }*/
        }

        /// <summary>
        /// 查询评测详细信息（教师或者学生通用）
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-summary-record")]
        public async Task<IActionResult> findSummaryRecord(JsonElement requert)
        {            
            //var (id, school) = HttpContext.GetAuthTokenInfo();
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                //if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
                if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
                if (!requert.TryGetProperty("code", out JsonElement school_code)) return BadRequest();
                if (!requert.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
                // 如果只有学生id则返回学生参加过的考试 只返回相关摘要信息
                var client = _azureCosmos.GetCosmosClient();
                //string code = school_code.ToString().Substring(5);
                //ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{school_code}"));
                List<object> examClassResults = new List<object>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id, c.code,c.info,c.studentIds,c.studentAnswers,c.studentScores from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}'",
                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{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())
                        {
                            examClassResults.Add(obj.ToObject<object>());
                        }
                    }
                }
                /*if (StringHelper.getKeyCount(requert) == 1 && requert.TryGetProperty("code", out JsonElement code))
                {
                    List<object> props = new List<object>();
                    await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c where c.id = {id}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{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())
                            {
                                props.Add(obj.ToObject<object>());
                            }
                        }
                    }
                    return Ok(new { props });
                }
                else
                {
                    if (requert.TryGetProperty("examCode", out JsonElement _))
                    {
                        //List<string> props = new List<string> { "id", "code", "examCode", "status", "mark", "score" };
                        //List<ExamRecord> examRecords = await _azureCosmos.FindByDict<ExamRecord>(request, props);
                        //return builder.Data(examRecords).Extend(new Dictionary<string, object> { { "props", props } }).build();
                        List<object> props = new List<object>();
                        await foreach (var item in client.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select c.id, c.code, c.examCode, c.status ,c.mark, c.score from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamRecord-{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())
                                {
                                    props.Add(obj.ToObject<object>());
                                }
                            }
                        }
                        return Ok(new { props });
                    }                   
                }*/
                return Ok(new { examClassResults });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/findSummaryRecord()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        //学生端查询评测列表
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Student")]
        [HttpPost("find-summary-by-student")]
        public async Task<IActionResult> findSummaryStudent(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //var (id, school) = HttpContext.GetAuthTokenInfo();
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
                if (!requert.TryGetProperty("code", out JsonElement school)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                var query = $"select c.id,c.code,A0.id paperId,A0.code paperCode,A0.name paperName,A0.multipleRule,A0.scope,A0.blob from c join A0 in c.papers where c.id ='{id}'";
                List<object> papers = new List<object>();
                List<object> subjects = new List<object>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{school}") }))
                {
                    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>());
                        }
                    }
                }
                var querySubject = $"select A0.id,A0.name from c join A0 in c.subjects where c.id ='{id}'";
                //List<object> props = new List<object>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: querySubject, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{school}") }))
                {
                    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())
                        {
                            subjects.Add(obj.ToObject<object>());
                        }
                    }
                }
                var queryAnswers = $"select c.id,c.code,c.studentIds,c.subjectId,c.studentAnswers,c.studentScores,c.sum from c where c.examId ='{id}' and array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult' ";
                List<ExamClassResult> answers = new List<ExamClassResult>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryAnswers,
                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{school}") }))
                {
                    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())
                        {
                            answers.Add(obj.ToObject<ExamClassResult>());
                        }
                    }
                }
                List<List<string>> stuAns = new List<List<string>>();
                List<List<double>> stuScore = new List<List<double>>();
                List<double> total = new List<double>();
                if (answers.Count > 0)
                {
                    foreach (ExamClassResult result in answers) {
                        int index = result.studentIds.IndexOf(studentId.ToString());
                        if (index == -1)
                        {
                            break;
                        }
                        stuAns.Add(result.studentAnswers[index]);
                        stuScore.Add(result.studentScores[index]);
                        total.Add(result.sum.Where(s => s <= 59).Count());
                        total.Add(result.sum.Where(s => s > 59 && s <= 70 ).Count());
                        total.Add(result.sum.Where(s => s > 70 && s <= 80).Count());
                        total.Add(result.sum.Where(s => s > 80 && s <= 90).Count());
                        total.Add(result.sum.Where(s => s > 90 && s <= 100).Count());
                    }                   
                }
                return Ok(new { papers, subjects,stuScore, stuAns, total });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/find-summary-by-student()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        //查询学生活动列表
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Student")]
        [HttpPost("find-all-by-student")]
        public async Task<IActionResult> findAllStudent(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //var (id, school) = HttpContext.GetAuthTokenInfo();
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!requert.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
                //if (!requert.TryGetProperty("school", out JsonElement school)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                var query = $"select c.id,c.code,c.name,c.startTime,c.endTime,c.type,c.progress,c.school,c.scope from c where array_contains(c.targetClassIds,'{id}') and c.progress != 'pending' ";
                List<object> props = new List<object>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
                {
                    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())
                        {
                            props.Add(obj.ToObject<object>());
                        }
                    }
                }
                var queryClass = $"select c.examId,c.subjectId,c.studentIds,c.studentAnswers,c.studentScores from c where array_contains(c.studentIds,'{studentId}') and c.pk = 'ExamClassResult'";
                List<ExamClassResult> Classes = new List<ExamClassResult>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: queryClass))
                {
                    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())
                        {
                            Classes.Add(obj.ToObject<ExamClassResult>());
                        }
                    }
                }
                List<ExamClassResult> result = new List<ExamClassResult>();
                foreach (ExamClassResult classResult in Classes) {
                    int index = classResult.studentIds.IndexOf(studentId.ToString());
                    ExamClassResult result1 = new ExamClassResult();
                    result1.examId = classResult.examId;
                    result1.subjectId = classResult.subjectId;
                    result1.studentAnswers.Add(classResult.studentAnswers[index]);
                    result1.studentScores.Add(classResult.studentScores[index]);
                    result.Add(result1);
                }
                

                return Ok(new {props, result });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
        //查询学生活动列表
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Student")]
        [HttpPost("find-score-by-student")]
        public async Task<IActionResult> findScoreByStudent(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //var (id, school) = HttpContext.GetAuthTokenInfo();
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                //if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                var query = $"select c.examId,c.subjectId,c.studentScores from c where array_contains(c.studentIds,'{id}') ";
                List<object> props = new List<object>();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query))
                {
                    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())
                        {
                            props.Add(obj.ToObject<object>());
                        }
                    }
                }

                return Ok(props);
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/findAllStudent\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }


        //查询学生活动列表
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Student")]
        [HttpPost("finish")]
        public async Task<IActionResult> finish(JsonElement requert)
        {
            //ResponseBuilder builder = ResponseBuilder.custom();
            //var (id, school) = HttpContext.GetAuthTokenInfo();
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
                info.progress = "finish";
                info = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(info, info.id, new PartitionKey($"Exam-{code}"));
                return Ok(info);
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，exam/finish\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
    }
}
