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");
    }
}