using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Infrastructure;
using Infrastructure.Filters;
using Infrastructure.Identity;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;

namespace Api
{
  public class Startup
  {
    public Startup(IConfiguration configuration)
    {
      Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
      var tokenOptions = Configuration.GetSection("Token").Get<TokenOptions>();
      services.AddSingleton(tokenOptions);

      // services.AddHNServicesInMemory();
      services.AddHNServicesEF();

      services
        .AddIdentityCore<User>(options =>
        {
          // FIXME uniquement pour nos besoins :)
          options.Password.RequiredLength = options.Password.RequiredUniqueChars = 0;
          options.Password.RequireDigit = options.Password.RequireLowercase = options.Password.RequireUppercase = options.Password.RequireNonAlphanumeric = false;
        })
        .AddRoles<Role>()
        .AddSignInManager()
        .AddEntityFrameworkStores<HNDbContext>();

      services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
          options.TokenValidationParameters = new TokenValidationParameters
          {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = tokenOptions.Issuer,
            ValidAudience = tokenOptions.Audience,
            IssuerSigningKey = tokenOptions.Key
          };
        });

      services.AddControllers(options =>
      {
        options.Filters.Add<CustomExceptionFilter>();
        options.Filters.Add(new AuthorizeFilter());
      });
      services.AddOpenApiDocument(doc =>
      {
        doc.AddSecurity("JWT", Enumerable.Empty<string>(), new NSwag.OpenApiSecurityScheme
        {
          Type = NSwag.OpenApiSecuritySchemeType.ApiKey,
          Name = "Authorization",
          In = NSwag.OpenApiSecurityApiKeyLocation.Header,
          Description = "Jeton: Bearer {votre jeton}"
        });

        doc.PostProcess = od =>
        {
          od.Info.Title = "Hacker News Clone API";
        };
      });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
      app.UseHNDatabaseMigrations();
      app.UseOpenApi();

      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }

      app.UseSwaggerUi3();
      //   app.UseReDoc();

      app.UseCors(o =>
      {
        // o.WithOrigins("http://mon.site.web");
        o.AllowAnyMethod();
        o.AllowAnyOrigin();
        o.AllowAnyHeader();
      });

      app.UseRouting();

      app.UseAuthentication();
      app.UseAuthorization();

      app.UseEndpoints(endpoints =>
      {
        endpoints.MapGet("/", async context =>
              {
                await context.Response.WriteAsync("Hello World!");
              });
        endpoints.MapControllers();
      });
    }
  }
}
