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;

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

                if (string.IsNullOrEmpty(study.id))
                {
                    study.id = Guid.NewGuid().ToString();
                    await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(study, new PartitionKey($"{study.code}"));
                }
                else
                {
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
                }
                return Ok(new { study });
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }


        /// <summary>
        /// 签到
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "teacher,admin")]
        [HttpPost("sign-in")]
        public async Task<IActionResult> Sign(JsonElement request)
        {
            await _dingDing.SendBotMsg($"OS，{_option.Location}，study/sign-in()\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
            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();
                var client = _azureCosmos.GetCosmosClient();
                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                if (response.Status == (int)HttpStatusCode.OK)
                {
                    var json = await JsonDocument.ParseAsync(response.ContentStream);
                    Study study = json.ToObject<Study>();
                    //bool flag = false;
                    bool flag = study.teachers.Exists(s => s.id.Equals(tId.GetString()) && string.IsNullOrEmpty(s.sign));
                    if (flag)
                    {
                        if (study.startTime < now)
                        {
                            foreach (Setting setting in study.teachers)
                            {
                                if (setting.id.Equals(tId.GetString()))
                                {
                                    setting.sign = "2";
                                    setting.signTime = now;
                                }
                            }
                        }
                        else
                        {
                            foreach (Setting setting in study.teachers)
                            {
                                if (setting.id.Equals(tId.GetString()))
                                {
                                    setting.sign = "1";
                                    setting.signTime = now;
                                }
                            }
                        }
                    }
                    else {
                        if (study.startTime < now)
                        {

                            Setting setting = new Setting();
                            setting.id = tId.GetString();
                            setting.sign = "2";
                            setting.signTime = now;
                            study.teachers.Add(setting);
                        }
                        else {
                            Setting setting = new Setting();
                            setting.id = tId.GetString();
                            setting.sign = "1";
                            setting.signTime = now;
                            study.teachers.Add(setting);
                        }
                    }
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
                }
                else {
                    return Ok(new { code = HttpStatusCode.NotFound});
                }
               
                return Ok();
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/sign-in()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        /*/// <summary>
        /// 上传作业
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [ProducesDefaultResponseType]
        [AuthToken(Roles = "teacher,admin")]
        [HttpPost("upload")]
        public async Task<IActionResult> Upload(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("hw", out JsonElement hw)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                if (response.Status == (int)HttpStatusCode.OK)
                {
                    var json = await JsonDocument.ParseAsync(response.ContentStream);
                    Study study = json.ToObject<Study>();
                    bool flag = study.teachers.Exists(s => s.id.Equals(tId.GetString()));
                    if (flag)
                    {
                        foreach (Setting setting in study.teachers)
                        {
                            if (setting.id.Equals(tId.GetString()))
                            {
                                setting.hwTime = now;
                                setting.hw = hw.GetString();
                            }
                        }
                    }
                    else {

                        Setting setting = new Setting();
                        setting.id = tId.GetString();
                        setting.hwTime = now;
                        setting.hw = hw.GetString();
                        study.teachers.Add(setting);
                    }                
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
                }
                else
                {
                    return Ok(new { code = HttpStatusCode.NotFound });
                }

                return Ok(new { code = HttpStatusCode.OK});
            }
            catch (Exception ex)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/upload()\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 sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                if (sresponse.Status == 200)
                {
                    using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
                    Study study = json.ToObject<Study>();
                    if (!string.IsNullOrEmpty(study.examId)) {
                        await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{code}"));
                    }
                    if (!string.IsNullOrEmpty(study.surveyId)) {
                        await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.surveyId, new PartitionKey($"Survey-{code}"));
                    }
                    if (!string.IsNullOrEmpty(study.workId))
                    {
                        await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.workId, new PartitionKey($"TeacherWork-{code}"));
                    }
                }
                var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                return Ok(new { id, code = response.Status });

            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/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.img,c.name,c.type,c.startTime,c.endTime,c.presenter,c.topic,c.address,c.owner 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> studies = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Study-{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())
                        {
                            studies.Add(obj.ToObject<object>());
                        }
                    }
                    if (iscontinuation)
                    {
                        continuationToken = item.GetContinuationToken();
                        break;
                    }

                }
                return Ok(new { studies });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/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<string> teachers = new List<string>();
                Study study = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Study>(id.GetString(), new PartitionKey($"Study-{code}"));
                if (study != null)
                {
                    (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, study.tchLists, study.school);
                    return Ok(new { study, teachers = tchList.Select(t => t.id).ToList(), status = 200 });
                }
                else
                {
                    return Ok(new { study, status = 404 });
                }              
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/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.img,c.name,c.startTime,c.type,c.endTime,c.presenter,c.topic,c.address,c.owner from c join A0 in c.teachers where A0.id = '{tId}'";
                List<object> studies = new();
                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{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())
                        {
                            studies.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { studies });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/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> studies = 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($"Study-{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())
                        {
                            studies.Add(obj.ToObject<object>());
                        }
                    }
                }
                return Ok(new { studies });
            }
            catch (Exception e)
            {
                await _dingDing.SendBotMsg($"OS，{_option.Location}，study/find-summary-by-teacher()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
                return BadRequest();
            }

        }

        [ProducesDefaultResponseType]
        //[AuthToken(Roles = "Teacher")]
        [HttpPost("audit")]
        public async Task<IActionResult> Audit(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("type", out JsonElement type)) return BadRequest();
                var client = _azureCosmos.GetCosmosClient();
                long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Study-{code}"));
                if (response.Status == (int)HttpStatusCode.OK)
                {
                    var json = await JsonDocument.ParseAsync(response.ContentStream);
                    Study study = json.ToObject<Study>();
                    bool flag = study.teachers.Exists(s => s.id.Equals(tId.GetString()));
                    if (flag)
                    {
                        foreach (Setting setting in study.teachers)
                        {
                            if (setting.id.Equals(tId.GetString()))
                            {
                                setting.status = type.GetInt32();
                                setting.aTime = now;
                            }
                        }


                    }
                    else {
                        Setting setting = new Setting();
                        setting.id = tId.GetString();
                        setting.status = type.GetInt32();
                        setting.aTime = now;
                        study.teachers.Add(setting);
                    }
                    await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(study, study.id, new PartitionKey($"{study.code}"));
                }
                else
                {
                    return Ok(new { code = HttpStatusCode.NotFound });
                }

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

        }
    }
}
