using Barcode.Host.Server.HostedService;
using Barcode.Host.Server.Hubs;
using Barcode.Host.Server.Models;
using Barcode.Host.Server.Services;
using Barcode.Host.Shared.Models;
using Barcode.Host.Shared.Models.Stateless;
using Serilog;
using System.Reflection;

namespace Barcode.Host.Server;

public class Program
{

    private static (string, WebApplicationOptions) Get(string[] args)
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        string? assemblyName = assembly.GetName()?.Name;
        if (string.IsNullOrEmpty(assemblyName))
            throw new Exception();
        string baseAssemblyName = assemblyName.Split('.')[0];
        string webRootPath = Path.Combine(AppContext.BaseDirectory.Split(baseAssemblyName)[0], baseAssemblyName, "wwwroot");
        if (!Directory.Exists(webRootPath))
            webRootPath = string.Empty;
        WebApplicationOptions webApplicationOptions = new()
        {
            Args = args,
            ContentRootPath = AppContext.BaseDirectory,
            WebRootPath = webRootPath
        };
        return new(assemblyName, webApplicationOptions);
    }

    public static int Main(string[] args)
    {
        LoggerConfiguration loggerConfiguration = new();
        (string assemblyName, _) = Get(args);
        WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
        _ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
        AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
        if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
            throw new Exception("Working directory name must have a value!");
        string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assemblyName, appSettings.WorkingDirectoryName);
        Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
        _ = ConfigurationLoggerConfigurationExtensions.Configuration(loggerConfiguration.ReadFrom, webApplicationBuilder.Configuration);
        _ = SerilogHostBuilderExtensions.UseSerilog(webApplicationBuilder.Host);
        Log.Logger = loggerConfiguration.CreateLogger();
        Serilog.ILogger log = Log.ForContext<Program>();
        try
        {
            if (appSettings.IsStaging && appSettings.IsDevelopment)
                throw new NotSupportedException("Please check appsettings file(s)!");
            if (appSettings.IsStaging != webApplicationBuilder.Environment.IsStaging())
                throw new NotSupportedException("Please check appsettings file(s)!");
            if (appSettings.IsDevelopment != webApplicationBuilder.Environment.IsDevelopment())
                throw new NotSupportedException("Please check appsettings file(s)!");
            _ = webApplicationBuilder.Services.AddRazorPages();
            _ = webApplicationBuilder.Services.AddSignalR();
            _ = webApplicationBuilder.Services.AddControllersWithViews();
            _ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
            _ = webApplicationBuilder.Services.AddHttpClient();
            _ = webApplicationBuilder.Services.AddSingleton<IFileService, FileService>();
            _ = webApplicationBuilder.Services.AddSingleton<IPostService, PostService>();
            _ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>();
            _ = webApplicationBuilder.Services.AddSingleton<ISerialService, SerialService>();
            _ = webApplicationBuilder.Services.AddSingleton<ILastScanService, LastScanService>();
            _ = webApplicationBuilder.Services.AddSingleton<ILinuxGroupManager, LinuxGroupManager>();
            _ = webApplicationBuilder.Services.AddHostedService<TimedHostedService>();
            _ = webApplicationBuilder.Services.AddSwaggerGen();
            WebApplication webApplication = webApplicationBuilder.Build();
            if (appSettings.IsDevelopment)
            {
                _ = webApplication.UseSwagger();
                _ = webApplication.UseDeveloperExceptionPage();
                _ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
            }
            if (!appSettings.IsDevelopment)
            {
                _ = webApplication.UseExceptionHandler("/Error");
                _ = webApplication.UseHsts();
            }
            _ = webApplication.Lifetime.ApplicationStopped.Register(Log.CloseAndFlush);
            _ = webApplication.UseStaticFiles();
            _ = webApplication.UseRouting();
            _ = webApplication.UseAuthorization();
            _ = webApplication.MapControllers();
            _ = webApplication.MapRazorPages();
            _ = webApplication.MapHub<NotificationHub>($"/{nameof(NotificationHub)}");
            log.Information("Starting Web Application");
            webApplication.Run();
            return 0;
        }
        catch (Exception ex)
        {
            log.Fatal(ex, "Host terminated unexpectedly");
            return 1;
        }
        finally
        {
            Log.CloseAndFlush();
        }
    }

}