using Azure.Cosmos;
using Azure.Messaging.ServiceBus;
using Microsoft.Azure.Documents;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models;

namespace TEAMModelFunction
{
    public class ExamTrigger
    {
        public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing, 
            CosmosClient client, Document input ,string code,long stime,long etime, string school)
        {
            ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
            List<ExamClassResult> examClassResults = new List<ExamClassResult>();
            List<ExamSubject> examSubjects = new List<ExamSubject>();
            if (info.scope.Equals("teacher", StringComparison.OrdinalIgnoreCase) || info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
            {
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{info.creatorId}") }))
                {
                    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>());
                        }
                    }
                }
            }
            else {
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.examId = '{info.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.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>());
                        }
                    }
                }
            }
            

            List<ChangeRecord> records = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", info.progress } });
            //ChangeRecord record = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{info.progress}"));
            switch (info.progress)
            {
                case "pending":
                    var message = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
                    message.ApplicationProperties.Add("name", "Exam");
                    if (records.Count > 0)
                    {
                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
                        records[0].sequenceNumber = start;
                        await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
                    }
                    else
                    {
                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", message, DateTimeOffset.FromUnixTimeMilliseconds(stime));
                        ChangeRecord changeRecord = new ChangeRecord
                        {
                            RowKey = input.Id,
                            PartitionKey = "pending",
                            sequenceNumber = start,
                            msgId = message.MessageId
                        };
                        await _azureStorage.Save<ChangeRecord>(changeRecord);
                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
                    }
                    break;
                case "going":
                    if (examClassResults.Count == 0)
                    {
                        foreach (string cla in info.targetClassIds)
                        {
                            int m = 0;
                            foreach (ExamSubject subject in info.subjects)
                            {
                                string classCode = "";
                                if (string.IsNullOrEmpty(info.school) || !info.scope.Equals("school",StringComparison.OrdinalIgnoreCase))
                                {
                                    classCode = "ExamClassResult-" + info.creatorId;
                                }
                                else {
                                    classCode = "ExamClassResult-" + info.school;
                                }
                                ExamClassResult result = new ExamClassResult
                                {
                                    code = classCode,
                                    examId = info.id,
                                    id = Guid.NewGuid().ToString(),
                                    subjectId = subject.id,
                                    year = info.year,
                                    scope = info.scope
                                };
                                result.info.id = cla;
                                if (info.scope.Equals("private", StringComparison.OrdinalIgnoreCase))
                                {
                                    var sresponse = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.creatorId}"));
                                    if (sresponse.Status == 200)
                                    {
                                        using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                        Class classroom = json.ToObject<Class>();
                                        result.info.name = classroom.name;
                                        result.gradeId = classroom.gradeId;
                                        List<string> ans = new List<string>();
                                        List<double> ansPoint = new List<double>();
                                        foreach (double p in info.papers[m].point)
                                        {
                                            //ans.Add(new List<string>());
                                            ansPoint.Add(-1);
                                        }
                                        foreach (StudentSimple stu in classroom.students)
                                        {
                                            result.studentIds.Add(stu.id);
                                            result.studentAnswers.Add(ans);
                                            result.studentScores.Add(ansPoint);
                                            result.sum.Add(0);
                                        }
                                    }
                                }
                                else {
                                    var sresponse = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(cla, new Azure.Cosmos.PartitionKey($"Class-{info.school}"));
                                    if (sresponse.Status == 200)
                                    {
                                        using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                                        Class classroom = json.ToObject<Class>();
                                        result.info.name = classroom.name;
                                        result.gradeId = classroom.gradeId;
                                        List<string> ans = new List<string>();
                                        List<double> ansPoint = new List<double>();
                                        foreach (double p in info.papers[m].point)
                                        {
                                            //ans.Add(new List<string>());
                                            ansPoint.Add(-1);
                                        }
                                        foreach (StudentSimple stu in classroom.students)
                                        {
                                            result.studentIds.Add(stu.id);
                                            result.studentAnswers.Add(ans);
                                            result.studentScores.Add(ansPoint);
                                            result.sum.Add(0);
                                        }
                                    }
                                }
                                
                                //result.progress = info.progress;
                                result.school = info.school;
                                m++;
                                await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(result, new Azure.Cosmos.PartitionKey($"{result.code}"));
                            }
                        }
                        // 发送信息通知
                        var messageEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
                        messageEnd.ApplicationProperties.Add("name", "Exam");
                        if (records.Count > 0)
                        {
                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", records[0].sequenceNumber);
                            records[0].sequenceNumber = end;
                            await _azureStorage.SaveOrUpdate<ChangeRecord>(records[0]);
                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(record, record.id, new Azure.Cosmos.PartitionKey($"{record.code}"));
                        }
                        else
                        {
                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
                            ChangeRecord changeRecord = new ChangeRecord
                            {
                                RowKey = input.Id,
                                PartitionKey = "going",
                                sequenceNumber = end,
                                msgId = messageEnd.MessageId
                            };
                            await _azureStorage.Save<ChangeRecord>(changeRecord);
                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
                        }
                    }
                    else
                    {
                        //处理单科结算时科目与试卷信息匹配的问题
                        int gno = 0;
                        foreach (ExamSubject subject in info.subjects)
                        {
                            if (subject.classCount == info.targetClassIds.Count)
                            {
                                await createClassResultAsync(info, examClassResults, subject, gno,_azureCosmos);
                            }
                            gno++;
                        }
                    }
                    break;
                case "finish":
                    int fno = 0;
                    foreach (ExamSubject subject in info.subjects)
                    {
                        await createClassResultAsync(info, examClassResults, subject, fno, _azureCosmos);
                        fno++;
                    }

                    break;
            }
        }
        public static async Task createClassResultAsync(ExamInfo info, List<ExamClassResult> examClassResults, ExamSubject subject, int no, AzureCosmosFactory _azureCosmos)
        {
            //保证试卷信息与科目信息同步
            ExamResult result = new ExamResult();
            //人数总和
            int Count = 0;
            int m = 0;
            List<ClassRange> classRanges = new List<ClassRange>();
            foreach (ExamClassResult classResult in examClassResults)
            {
                if (classResult.subjectId.Equals(subject.id))
                {
                    foreach (List<double> scores in classResult.studentScores)
                    {
                        List<double> newScores = new List<double>();
                        foreach (double sc in scores) {
                            newScores.Add(sc > -1 ? sc : 0);
                        }
                        result.studentScores.Add(newScores);
                    }
                    //处理班级信息
                    ClassRange range = new ClassRange();
                    range.id = classResult.info.id;
                    range.name = classResult.info.name;
                    range.gradeId = classResult.gradeId;
                    List<int> ran = new List<int>();
                    int stuCount = classResult.studentIds.Count;
                    Count += stuCount;
                    if (m == 0)
                    {
                        ran.Add(0);
                        ran.Add(stuCount - 1);
                    }
                    else
                    {
                        ran.Add(Count - stuCount);
                        ran.Add(Count - 1);
                    }
                    m++;
                    range.range = ran;
                    classRanges.Add(range);
                    //处理学生ID 
                    foreach (string id in classResult.studentIds)
                    {
                        result.studentIds.Add(id);
                    }
                }
            }
            result.classes = classRanges;
            result.code = "ExamResult-" + info.id;
            result.school = info.school;
            result.id = subject.id;
            result.examId = info.id;
            result.subjectId = subject.id;
            result.year = info.year;
            result.paper = info.papers[no];
            //result.point = info.papers[j].point;
            result.scope = info.scope;
            result.name = info.name;
            result.time = info.startTime;
            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").UpsertItemAsync(result, new Azure.Cosmos.PartitionKey($"ExamResult-{info.id}"));

        }
    }
}
