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

namespace TEAMModelOS.Controllers.Common
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")
    [Route("common/ExamLite")]
    [ApiController]
    public class ExamLiteController : 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;
        private readonly AzureRedisFactory _azureRedis;
        public IConfiguration _configuration { get; set; }
        public ExamLiteController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
           IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
        {
            _azureCosmos = azureCosmos;
            _serviceBus = serviceBus;
            _snowflakeId = snowflakeId;
            _dingDing = dingDing;
            _option = option?.Value;
            _azureStorage = azureStorage;
            _azureRedis = azureRedis;
            _configuration = configuration;
        }
        /// <summary>
        /// 保存评测信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "teacher,admin")]
        [HttpPost("save")]
        public async Task<IActionResult> Save(JsonElement request)
        {
            try
            {
                var client = _azureCosmos.GetCosmosClient();
                ExamLite trExam = request.ToObject<ExamLite>();
                trExam.owner = "school";
                string id = await ExamService.saveMoreAsync(client, _dingDing, trExam);
                return Ok(new { id, code = (int)HttpStatusCode.OK });

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

        }


        /// <summary>
        /// 作答
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "teacher,admin")]
        [HttpPost("record-in")]
        public async Task<IActionResult> RecordIn(JsonElement request)
        {
            try
            {
                if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
                if (!request.TryGetProperty("ans", out JsonElement ans)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                List<List<string>> answer = ans.ToObject<List<List<string>>>();
                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"ExamLite-{code}"));
                if (response.Status == (int)HttpStatusCode.OK)
                {
                    var json = await JsonDocument.ParseAsync(response.ContentStream);
                    ExamLite trExam = json.ToObject<ExamLite>();
                    //List<List<string>> standard = trExam.items.answers;                  
                    bool flag = trExam.teachers.Exists(s => s.id.Equals(tId.GetString()));
                    List<string> ids = trExam.teachers.Select(e => e.id).ToList();
                    int index = ids.IndexOf(tId.GetString());
                    if (flag)
                    {
                        foreach (var record in trExam.teachers)
                        {
                            if (record.id.Equals(tId.GetString()))
                            {
                                record.answer = answer;
                                record.time = now;
                            }
                        }
                    }
                    else {
                        Record record = new();
                        record.id = tId.GetString();
                        record.answer = answer;
                        record.time = now;
                        trExam.teachers.Add(record);
                    }
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(trExam, trExam.id, new PartitionKey($"{trExam.code}"));
                }
                else
                {
                    return Ok(new { code = HttpStatusCode.NotFound });
                }

                return Ok(new { code = HttpStatusCode.OK });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TrExam/record-in()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [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();
                var client = _azureCosmos.GetCosmosClient();
                var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"ExamLite-{code}"));
                return Ok(new { id, code = response.Status });



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

        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find")]
        public async Task<IActionResult> Find(JsonElement requert)
        {
            try
            {
                if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                var query = $"select c.id,c.name,c.createTime from c ";
                string continuationToken = string.Empty;
                string token = default;
                //是否需要进行分页查询，默认不分页
                bool iscontinuation = false;
                if (requert.TryGetProperty("token", out JsonElement token_1))
                {
                    token = token_1.GetString();
                    iscontinuation = true;
                };
                //默认不指定返回大小
                int? topcout = null;
                if (requert.TryGetProperty("count", out JsonElement jcount))
                {
                    if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
                    {
                        topcout = data;
                    }
                }

                List<object> exam = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"ExamLite-{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())
                        {
                            exam.Add(obj.ToObject<object>());
                        }
                    }
                    if (iscontinuation)
                    {
                        continuationToken = item.GetContinuationToken();
                        break;
                    }

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

        }

        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-summary")]
        public async Task<IActionResult> FindSummary(JsonElement requert)
        {
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                List<ExamLite> trExams = new();
                ExamLite examLite = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamLite>(id.GetString(), new PartitionKey($"ExamLite-{code}"));
                if (examLite != null)
                {
                    (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, examLite.tchLists, examLite.school);
                    return Ok(new { examLite, teachers = tchList.Select(t => t.id).ToList(), status = 200 });
                }
                else
                {
                    return Ok(new { examLite, status = 404 });
                }
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TrExam/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return Ok(new {status = 404 });
            }

        }


        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-by-teacher")]
        public async Task<IActionResult> FindByTeacher(JsonElement requert)
        {
            try
            {
                if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                var query = $"select c.id,c.name,c.createTime,A0.time from c join A0 in c.teachers where A0.id = '{tId}'";
                List<object> exams = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamLite-{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())
                        {
                            exams.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { exams });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TrExam/find-by-teacher()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("find-summary-by-teacher")]
        public async Task<IActionResult> FindSummaryByTeacher(JsonElement requert)
        {
            try
            {
                if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
                if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                if (!requert.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                List<object> exams = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c join A0 in c.teachers where A0.id = '{tId}' and c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamLite-{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())
                        {
                            exams.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { exams });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TrExam/find-summary-by-teacher()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
    }

}
