using System;
using System.IO;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Falcon.Extend;
using FAuth.DataBase;
using FAuth.Extensions;
using FAuth.Extensions.Account;
using FAuth.Extensions.Decryptor;
using FAuth.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Redis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Writers;

namespace FAuth
{
    /// <summary>
    /// 应用设置
    /// </summary>
    public class Startup
    {
        public Startup(IConfiguration configuration) {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        /// <summary>
        /// 注册到服务容器
        /// </summary>
        /// <param name="services">服务容器</param>
        public void ConfigureServices(IServiceCollection services) {
            //注册Json序列化
            services.AddMsJsonProvider();
            //注册数据库
            services.AddScoped<DbContext,FAuthDb>();
            services.AddDbContext<FAuthDb>(option => {
                var dbType = this.Configuration.GetValue<string>("Database:UseDb").ToLower();
                switch(dbType) {
                    case "mysql":
                        option.UseMySql(this.Configuration.GetValue<string>("Database:FAuthDbMySql"));
                        break;
                    case "sqlserver":
                        option.UseSqlServer(this.Configuration.GetValue<string>("Database:FAuthDbSqlServer"));
                        break;
                    default:
                        throw new Exception("Database:UseDb配置错误！只能为mysql或sqlserver");
                }
            });
            services.AddAccountHelper();
            //注册Redis
            var rop = this.Configuration.GetSection("Redis").Get<RedisCacheOptions>();
            services.AddRedis(rop);
            //注册MVC
            services.AddControllersWithViews()
                .AddJsonOptions(option => {
                    option.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
                    option.JsonSerializerOptions.PropertyNamingPolicy = null;
                });

            //注册Swagger
            services.AddSwaggerGen(c => {
                var option = this.Configuration.GetSection("SwaggerDoc");
                c.SwaggerDoc("V1",new OpenApiInfo {
                    Title = option.GetValue<string>("Title"),
                    Version = option.GetValue<string>("Version"),
                    Description = option.GetValue<string>("Description"),
                    Contact = new OpenApiContact {
                        Name = option.GetValue<string>("Contact:Name"),
                        Url = new Uri(option.GetValue<string>("Contact:Url")),
                    },
                });
                var xmlPath = Path.Combine(AppContext.BaseDirectory,typeof(Program).Assembly.GetName().Name + ".xml");
                c.IncludeXmlComments(xmlPath,true);
                c.AddXmlEnumEnable(xmlPath);
            });
            //注册用户票据生成器
            services.AddAESCrypto();
            var UTDO = Configuration.GetSection("UserTicketDecryptorOption");
            services.AddUserTicketDryptor(UTDO);
            //注册api错误处理器
            services.AddScoped<ApiExceptionFilterAttribute>();
        }

        // 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.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();
            }

            using(var socpe = app.ApplicationServices.CreateScope()) {
                var db = socpe.ServiceProvider.GetService<FAuthDb>();
                db.InitSync().Wait();
            }

            //app.UseHttpsRedirection();
            app.UseStaticFiles();


            app.UseSwagger();
            app.UseSwaggerUI(c => {
                c.SwaggerEndpoint("/swagger/V1/swagger.json","接口文档");
                c.RoutePrefix = "api";
            });

            app.UseRouting();
            app.UseEndpoints(endpoints => {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}");
            });
        }
    }
}
