namespace Hims.Api.Middleware
{
    using System;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using Filters;
    using Infrastructure.Configurations;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.OpenApi.Models;
    using Swashbuckle.AspNetCore.SwaggerUI;

    /// <summary>
    /// Swagger API documentation components start-up configuration
    /// </summary>
    public class SwaggerMiddleware
    {
        /// <summary>
        /// Configures the service.
        /// </summary>
        /// <param name="services">
        /// The services.
        /// </param>
        /// <param name="configuration">
        /// The configuration.
        /// </param>
        public static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            var appConfiguration = configuration.GetSection("ApplicationConfiguration").Get<ApplicationConfiguration>();

            services.AddSwaggerGen(options =>
            {
                options.CustomSchemaIds( type => type.ToString() );
                options.SwaggerDoc(
                    "v" + appConfiguration.Version,
                    new OpenApiInfo
                    {
                        Version = "v" + appConfiguration.Version,
                        Title = "Careaxes Rest API"
                    });
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Api.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Domain.Configurations.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Domain.Helpers.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Domain.Repositories.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Domain.Services.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Shared.DataFilters.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Shared.EntityModels.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Shared.Library.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Hims.Shared.UserModels.xml"));
                options.IgnoreObsoleteActions();
                options.IgnoreObsoleteProperties();
                options.DescribeAllParametersInCamelCase();
                options.UseInlineDefinitionsForEnums();
                options.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
                options.AddSecurityDefinition(
                    "Bearer",
                    new OpenApiSecurityScheme
                    {
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey,
                        Description = "Careaxes Rest API Authorization header using the Bearer scheme. Example: \"Bearer {token}\""
                    });

                options.OperationFilter<SecurityRequirementsOperationFilter>();
                options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();
            });
        }

        /// <summary>
        /// Configures the specified application.
        /// </summary>
        /// <param name="app">
        /// The application.
        /// </param>
        /// <param name="configuration">
        /// The configuration.
        /// </param>
        /// <param name="assembly">
        /// The assembly.
        /// </param>
        public static void Configure(IApplicationBuilder app, IConfiguration configuration, Assembly assembly)
        {
            var appConfiguration = configuration.GetSection("ApplicationConfiguration").Get<ApplicationConfiguration>();

            app.UseSwagger();
            app.UseSwaggerUI(c =>
            {
                c.IndexStream = () => assembly.GetManifestResourceStream("Hims.Api.Swagger.index.html");

                // Core
                c.SwaggerEndpoint(appConfiguration.BaseUrl + "/swagger" + "/v" + appConfiguration.Version + "/swagger.json", "Careaxes Rest API v" + appConfiguration.Version + " Documentation");

                // Display
                c.DefaultModelsExpandDepth(0);
                c.DefaultModelRendering(ModelRendering.Example);
                c.DisplayRequestDuration();
                c.DocExpansion(DocExpansion.List);
                c.EnableDeepLinking();
                c.EnableFilter();
                c.ShowExtensions();
                c.DocumentTitle = "Careaxes Rest API";
                c.RoutePrefix = "api-docs";
                c.InjectStylesheet(appConfiguration.BaseUrl + "/assets/css/swagger.css");
                c.InjectJavascript(appConfiguration.BaseUrl + "/assets/js/jquery.min.js");
                c.InjectJavascript(appConfiguration.BaseUrl + "/assets/js/swagger.js");
                c.EnableFilter();
                c.ShowExtensions();

                // Network
                c.SupportedSubmitMethods(SubmitMethod.Post, SubmitMethod.Get, SubmitMethod.Put, SubmitMethod.Delete);
            });
        }
    }
}
