using Microsoft.AspNetCore.Mvc;
using ProtoBuf.Meta;
using System.Collections.Generic;
using System.Linq;

namespace AsbCloudWebApi.Controllers
{
    /// <summary>
    /// Схемы ProtoBuf
    /// </summary>
    [Route("api/proto")]
    [ApiController]
    public class ProtobufController : ControllerBase
    {
        private IEnumerable<MetaType> GetMetaTypes()
        {
            var metaTypes = RuntimeTypeModel.Default
                .GetTypes()
                .OfType<MetaType>();
            var fileteredMetaTypes = metaTypes
                .Where(t => t.Type.MemberType == System.Reflection.MemberTypes.TypeInfo)
                .Where(t => !t.Type.IsGenericType)
                .Where(t => !t.Type.IsArray);
            return fileteredMetaTypes;
        }

        /// <summary>
        /// названия доступных типов
        /// </summary>
        /// <returns></returns>
        [HttpGet("types")]
        [ProducesResponseType(typeof(IEnumerable<string>), (int)System.Net.HttpStatusCode.OK)]
        public IActionResult GetTypes()
        {
            var typesNames = GetMetaTypes()
                .Select(t => t.Type?.Name);
            return Ok(typesNames);
        }

        /// <summary>
        /// .proto файл со всеми доступными типами
        /// </summary>
        /// <returns></returns>
        [HttpGet("schema")]
        [ProducesResponseType(typeof(IEnumerable<string>), (int)System.Net.HttpStatusCode.OK)]
        public IActionResult GetSchema()
        {
            var types = GetMetaTypes().Select(mt => mt.Type);
            SchemaGenerationOptions opts = new() { };
            opts.Types.AddRange(types);
            var protoFileContentString = ProtoBuf.Serializer.GetProto(opts);
            var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString);
            return File(protoFileContentBytes, "text/plain", "types.proto");
        }

        /// <summary>
        /// .proto файл со всеми доступными типами
        /// </summary>
        /// <returns></returns>
        [HttpGet("schema/{typeName}")]
        [ProducesResponseType(typeof(IEnumerable<string>), (int)System.Net.HttpStatusCode.OK)]
        [ProducesResponseType(typeof(ValidationProblemDetails), (int)System.Net.HttpStatusCode.BadRequest)]
        public IActionResult GetSchema(string typeName)
        {
            if (string.IsNullOrEmpty(typeName))
                return this.ValidationBadRequest(nameof(typeName), "require typeName");

            var type = RuntimeTypeModel.Default
                .GetTypes()
                .OfType<MetaType>()
                .FirstOrDefault(t => t.Type.Name.Equals(typeName, System.StringComparison.InvariantCultureIgnoreCase));

            if (type is null)
                return NoContent();

            SchemaGenerationOptions opts = new() { };
            opts.Types.Add(type.Type);
            var protoFileContentString = ProtoBuf.Serializer.GetProto(opts);
            var protoFileContentBytes = System.Text.Encoding.UTF8.GetBytes(protoFileContentString);
            return File(protoFileContentBytes, "text/plain", $"{typeName}.proto");
        }
    }
}