using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Newtonsoft.Json.Linq;

namespace OAuthSample
{
    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 => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            #region OAuth 协议测试
            //services.AddAuthentication(options =>
            //{
            //    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            //    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            //    options.DefaultChallengeScheme = "MicrosoftOAuth";
            //})
            //.AddCookie()
            //.AddOAuth("MicrosoftOAuth", options =>
            //{
            //    options.ClientId = "2a73e89d-6e5e-44c7-9b3d-0428bd9ae2ad";
            //    options.ClientSecret = "mmusUZFZO83))]nibQQ671]";
            //    options.TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
            //    options.UserInformationEndpoint = "https://graph.microsoft.com/v1.0/me";
            //    options.AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";

            //    options.CallbackPath = new PathString("/signin-microsoft");

            //    options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
            //    options.ClaimActions.MapJsonKey(ClaimTypes.Name, "displayName");
            //    options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "givenName");
            //    options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "surname");
            //    options.ClaimActions.MapCustomJson(ClaimTypes.Email, user => user.Value<string>("mail") ?? user.Value<string>("userPrincipalName"));

            //    options.Scope.Add("https://graph.microsoft.com/user.read");
            //    options.SaveTokens = true;

            //    options.Events.OnCreatingTicket = async context =>
            //    {
            //        var request = new HttpRequestMessage(HttpMethod.Get, options.UserInformationEndpoint);
            //        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);

            //        var response = await context.Backchannel.SendAsync(request);
            //        if (!response.IsSuccessStatusCode)
            //        {
            //            throw new HttpRequestException($"An error occurred when retrieving Microsoft user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Microsoft Account API is enabled.");
            //        }

            //        var payload = JObject.Parse(await response.Content.ReadAsStringAsync());

            //        context.RunClaimActions(payload);
            //    };
            //});
            #endregion

            #region OIDC 协议测试
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = "MicrosoftOIDC";
            })
            .AddCookie()
            .AddOpenIdConnect("MicrosoftOIDC", options =>
            {
                options.ClientId = "2a73e89d-6e5e-44c7-9b3d-0428bd9ae2ad";
                options.ClientSecret = "mmusUZFZO83))]nibQQ671]";

                options.MetadataAddress = "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration";
                options.CallbackPath = new PathString("/signin-microsoft");

                options.Scope.Add("openid");
                options.Scope.Add("profile");

                options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                options.ResponseMode = OpenIdConnectResponseMode.FormPost;

                //options.GetClaimsFromUserInfoEndpoint = true;

                options.TokenValidationParameters.NameClaimType = "name";

                options.TokenValidationParameters.ValidateIssuer = false;

                options.SaveTokens = true;

            });
            #endregion

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

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

            app.UseAuthentication();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

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

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}
