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.Models;
using TEAMModelOS.SDK.DI;
using TEAMModelOS.SDK.Extension;
using TEAMModelOS.SDK.Models;

namespace TEAMModelOS.Controllers.Common
{
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    //[Authorize(Roles = "IES5")
    [Route("common/work")]
    [ApiController]
    public class WorkController : 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 WorkController(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();
                TeacherWork work = request.ToObject<TeacherWork>();
                work.owner = "school";
                try
                {
                    work.ttl = -1;
                    work.code = "TeacherWork-" + work.school;
                    long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                    work.createTime = now;

                    if (string.IsNullOrEmpty(work.id))
                    {
                        work.id = Guid.NewGuid().ToString();
                        await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(work, new PartitionKey($"{work.code}"));
                    }
                    else
                    {
                        await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(work, new PartitionKey($"{work.code}"));
                    }
                }
                catch (Exception e)
                {
                    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-saveMore\n{e.Message}{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
                }
                return Ok(new { work.id, code = (int)HttpStatusCode.OK });

            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/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($"TeacherWork-{code}"));
                if (response.Status == (int)HttpStatusCode.OK)
                {
                    var json = await JsonDocument.ParseAsync(response.ContentStream);
                    TeacherWork work = json.ToObject<TeacherWork>();
                    //List<List<string>> standard = work.items.answers;                  
                    bool flag = work.teachers.Exists(s => s.id.Equals(tId.GetString()));
                    List<string> ids = work.teachers.Select(e => e.id).ToList();
                    int index = ids.IndexOf(tId.GetString());
                    if (flag)
                    {
                        foreach (var record in work.teachers)
                        {
                            if (record.id.Equals(tId.GetString()))
                            {
                                record.hw = ans.GetString();
                                record.hwTime = now;
                            }
                        }
                    }
                    else {
                        Submits submits = new();
                        submits.id = tId.GetString();
                        submits.hw = ans.GetString();
                        submits.hwTime = now;
                        work.teachers.Add(submits);
                    }
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(work, work.id, new PartitionKey($"{work.code}"));
                }
                else
                {
                    return Ok(new { code = HttpStatusCode.NotFound });
                }

                return Ok(new { code = HttpStatusCode.OK });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/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($"TeacherWork-{code}"));
                return Ok(new { id, code = response.Status });



            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/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> works = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"TeacherWork-{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())
                        {
                            works.Add(obj.ToObject<object>());
                        }
                    }
                    if (iscontinuation)
                    {
                        continuationToken = item.GetContinuationToken();
                        break;
                    }

                }
                return Ok(new { works });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/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<TeacherWork> works = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<TeacherWork>(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherWork-{code}") }))
                {
                    works.Add(item);
                }
                return Ok(new { works });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }


        /// <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> works = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherWork-{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())
                        {
                            works.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { works });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/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> works = 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($"TeacherWork-{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())
                        {
                            works.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { works });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，TeacherWork/find-summary-by-teacher()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }
    }
}
