using System;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.CookiePolicy;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using pwt_0x01_ng.Models.Identity;
using pwt_0x01_ng.Models.Database;
using pwt_0x01_ng.Models.ApplicationServices;
using Microsoft.EntityFrameworkCore;

namespace pwt_0x01_ng
{
	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.
		public void ConfigureServices(IServiceCollection services)
		{
			services.Configure<CookiePolicyOptions>(options =>
			{
				// This lambda determines whether user consent for non-essential cookies is needed for a given request.
				options.CheckConsentNeeded = context => false;
				options.MinimumSameSitePolicy = SameSiteMode.Lax;
				options.HttpOnly = HttpOnlyPolicy.Always;
				options.Secure = CookieSecurePolicy.Always;
			});

			services.AddControllersWithViews();
			IMvcBuilder builder = services.AddRazorPages();
#if DEBUG
			if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT").Equals("Development")){
				builder.AddRazorRuntimeCompilation();
			}
#endif

			var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
			services.AddDbContext<DBContext>(options =>
				options.UseNpgsql(
					connectionString
				)
			);


			services.AddIdentity<User, Role>().AddEntityFrameworkStores<DBContext>().AddDefaultTokenProviders();
			services.Configure<IdentityOptions>(o =>
			{
				/* dev fun settings */
				o.Password.RequireDigit = false;
				o.Password.RequireUppercase = false;
				o.Password.RequireLowercase = false;
				o.Password.RequireNonAlphanumeric = false;
				o.Password.RequiredLength = config.min_passwd_length;
				o.Password.RequiredUniqueChars = 1;
				o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(1);
				o.Lockout.MaxFailedAccessAttempts = 3;
				o.Lockout.AllowedForNewUsers = false;
				o.User.RequireUniqueEmail = true;
				/* FIXME
				 * o.Password.RequireDigit = true;
				 * o.Password.RequiredLength = 18;
				 * o.Password.RequiredUniqueChars = 10;
				 * o.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
				 * o.Lockout.MaxFailedAccessAttempts = 3;
				 * o.Lockout.AllowedForNewUsers = true;
				 * o.User.RequireUniqueEmail = true;
				 */
			});
			services.ConfigureApplicationCookie(o => {
				o.Cookie.HttpOnly = true;
				o.ExpireTimeSpan = TimeSpan.FromDays(2);
				o.SlidingExpiration = true;
				o.LoginPath = "/Security/Account/Login";
				o.LogoutPath = "/Security/Account/Logout";
			});
			services.AddScoped<ISecurityApplicationService, SecurityIdentityApplicationService>();
			services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
			services.AddResponseCompression();
			services.AddSession();
		}

		// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
		public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
		{
			if (env.EnvironmentName.Equals("Development"))
			{
				app.UseDeveloperExceptionPage();
			}
			else
			{
				app.UseExceptionHandler("/Home/Error");
			}
			app.UseStatusCodePages();
			app.UseStatusCodePagesWithReExecute("/Home/HandleError/{0}");

			app.UseRouting();
			app.UseAuthentication();
			app.UseAuthorization();
			app.UseSession();
			app.UseEndpoints(endpoints =>
			{
				endpoints.MapRazorPages();
				endpoints.MapControllerRoute(
					name: "areas",
					pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}"
				);
				endpoints.MapControllerRoute(
					name: "default",
					pattern: "{controller=Home}/{action=Index}/{id?}"
				);
				endpoints.MapControllerRoute(
					name: "default",
					pattern: "{controller=Products}/{action=Details}/{id?}"
				);
			});

			app.UseStaticFiles();
			app.UseCookiePolicy();

		}
	}
}