using BukiVedi.App.Middlewares;
using BukiVedi.Shared;
using BukiVedi.Shared.Apps;
using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.FileProviders;
using System.Net;
using System.Text;
using ZeroLevel;

namespace BukiVedi.App
{
    public class Program
    {
        static int PORT = 80;

        public static async Task Main(string[] args)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Log.AddTextFileLogger(new ZeroLevel.Logging.TextFileLoggerOptions().SetFolderPath("logs"), ZeroLevel.Logging.LogLevel.FullDebug);

            var builder = WebApplication.CreateBuilder(args);

            builder.WebHost.ConfigureKestrel((context, serverOptions) =>
            {
                var kestrelSection = context.Configuration.GetSection("Kestrel");
                serverOptions.Configure(kestrelSection)
                    .Endpoint("HTTP", listenOptions =>
                    {
                        serverOptions.Listen(IPAddress.Any, PORT);
                    });
            });

            try
            {
                await ConfigureServices(builder.Services);
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Fault services initialization");
                return;
            }
            var app = builder.Build();

            app.UseCookiePolicy(new CookiePolicyOptions
            {
                MinimumSameSitePolicy = SameSiteMode.Strict
            });

            app.UseAuthentication();

            app.UseAuthorization();

            app.UseBukiVediAuthMiddleware();

            app.UseStaticFiles(new StaticFileOptions
            {
                FileProvider = new PhysicalFileProvider(
                   Path.Combine(builder.Environment.ContentRootPath, "web")),
                RequestPath = "/web",
                OnPrepareResponse = ctx =>
                {
                    var path = ctx.Context.Request.Path;
                    if (path.HasValue && path.Value.Contains("index.html", StringComparison.OrdinalIgnoreCase))
                    {
                        if ((ctx.Context.User?.Identity?.IsAuthenticated ?? false) == false)
                        {
                            ctx.Context.Response.ContentLength = 0;
                            ctx.Context.Response.Body = Stream.Null;
                            ctx.Context.Response.Redirect("/web/login.html");
                        }
                    }
                }
            });

            app.MapControllers();

            app.Run();
        }

        public static async Task ConfigureServices(IServiceCollection services)
        {
            var platformAdmin = new Member
            {
                Login = AppSettings.Settings.Login,
                PasswordHash = Cryptor.HashPassword(AppSettings.Settings.Password),
                DisplayName = "Admin"
            };
            IAuthProvider authProvider = new AuthProvider(Tables.Members);
            if (null == (await authProvider.GetAccountByLogin(platformAdmin.Login)))
            {
                await authProvider.CreateAccount(platformAdmin);
            }
            var library = new Library();
            services.AddSingleton<IAuthProvider>(authProvider);
            services.AddSingleton<ILibrary>(library);
            services.AddSingleton<IAuthorHandler>(new AuthorHandler(library));
            services.AddSingleton<ITagsHandler>(new TagsHandler(library));
            services.AddSingleton<IBooksHandler>(new BooksHandler(library));

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o =>
            {
                o.LoginPath = new PathString("/web/login.html");
            });

            services.AddAuthorization(options =>
            {
                options.AddPolicy("authorized", policy =>
                {
                    policy.RequireAuthenticatedUser();
                    policy.AuthenticationSchemes = new List<string>()
                    {
                        CookieAuthenticationDefaults.AuthenticationScheme
                    };
                });
            });

            services.AddControllers();
        }
    }
}
