using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Hosting.WindowsServices;
using OI.Metrology.Server.Models;
using OI.Metrology.Server.Repositories;
using OI.Metrology.Server.Repository;
using OI.Metrology.Server.Services;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Services;
using System.Reflection;

namespace OI.Metrology.Server;

public class Program
{

    private static (string, WebApplicationOptions) Get(string[] args)
    {
        string webRootPath;
        Assembly assembly = Assembly.GetExecutingAssembly();
        string? assemblyName = assembly.GetName()?.Name;
        if (string.IsNullOrEmpty(assemblyName))
            throw new Exception();
        string baseAssemblyName = assemblyName.Split('.')[0];
        if (WindowsServiceHelpers.IsWindowsService())
            webRootPath = Path.Combine(AppContext.BaseDirectory, "wwwroot");
        else
            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)
    {
        ILogger<Program>? logger = null;
        (string assemblyName, WebApplicationOptions _) = Get(args);
        WebApplicationBuilder webApplicationBuilder = WebApplication.CreateBuilder(args);
        _ = webApplicationBuilder.Configuration.AddUserSecrets<Program>();
        AppSettings appSettings = Models.Binder.AppSettings.Get(webApplicationBuilder.Configuration);
        if (string.IsNullOrEmpty(appSettings.Company))
            throw new Exception("Company name must have a value!");
        if (string.IsNullOrEmpty(appSettings.WorkingDirectoryName))
            throw new Exception("Working directory name must have a value!");
        try
        {
            _ = webApplicationBuilder.Services.AddMemoryCache();
            _ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
            _ = webApplicationBuilder.Services.AddControllersWithViews();
            _ = webApplicationBuilder.Services.AddDistributedMemoryCache();

            AppSettingsRepository appSettingsRepository = new(appSettings);
            SQLDbConnectionFactory sqlDbConnectionFactory = new(appSettings);
            ClientSettingsRepository clientSettingsRepository = new(appSettings);

            _ = webApplicationBuilder.Services.AddHttpClient();
            _ = webApplicationBuilder.Services.AddSingleton(_ => appSettings);
            _ = webApplicationBuilder.Services.AddSingleton<IPinRepository, PinRepository>();
            _ = webApplicationBuilder.Services.AddScoped<IExportRepository, ExportRepository>();
            _ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
            _ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
            _ = webApplicationBuilder.Services.AddSingleton<IInboundRepository, InboundRepository>();
            _ = webApplicationBuilder.Services.AddScoped<IMetrologyRepository, MetrologyRepository>();
            _ = webApplicationBuilder.Services.AddSingleton<IFileShareRepository, FileShareRepository>();
            _ = webApplicationBuilder.Services.AddSingleton<IToolTypesRepository, ToolTypesRepository>();
            _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSRepository, InfinityQSRepository>();
            _ = webApplicationBuilder.Services.AddScoped<IOpenInsightV1Repository, OpenInsightV1Repository>();
            _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV2Repository, InfinityQSV2Repository>();
            _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV3Repository, InfinityQSV3Repository>();
            _ = webApplicationBuilder.Services.AddSingleton<IInfinityQSV4Repository, InfinityQSV4Repository>();
            _ = webApplicationBuilder.Services.AddSingleton<IClientSettingsRepository>(_ => clientSettingsRepository);
            _ = webApplicationBuilder.Services.AddSingleton<IServiceShopOrderRepository, ServiceShopOrderRepository>();
            _ = webApplicationBuilder.Services.AddSingleton<ISpreadingResistanceProfileService, SpreadingResistanceProfileService>();
            _ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>(_ => sqlDbConnectionFactory);
            _ = webApplicationBuilder.Services.AddSingleton<IAppSettingsRepository<Models.Binder.AppSettings>>(_ => appSettingsRepository);

            _ = webApplicationBuilder.Services.AddSwaggerGen();
            _ = webApplicationBuilder.Services.AddSession(sessionOptions =>
                {
                    sessionOptions.IdleTimeout = TimeSpan.FromSeconds(2000);
                    sessionOptions.Cookie.HttpOnly = true;
                    sessionOptions.Cookie.IsEssential = true;
                }
            );
            if (WindowsServiceHelpers.IsWindowsService())
            {
                _ = webApplicationBuilder.Services.AddSingleton<IHostLifetime, WindowsServiceLifetime>();
                _ = webApplicationBuilder.Logging.AddEventLog(settings =>
                {
#pragma warning disable CA1416
                    if (string.IsNullOrEmpty(settings.SourceName))
                        settings.SourceName = webApplicationBuilder.Environment.ApplicationName;
#pragma warning restore
                });
            }
            WebApplication webApplication = webApplicationBuilder.Build();
            logger = webApplication.Services.GetRequiredService<ILogger<Program>>();
            _ = webApplication.UseCors(corsPolicyBuilder => corsPolicyBuilder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
            if (!webApplicationBuilder.Environment.IsDevelopment())
            {
                _ = webApplication.UseExceptionHandler("/Error");
                _ = webApplication.UseHttpsRedirection();
                _ = webApplication.UseHsts();
            }
            else
            {
                if (string.IsNullOrEmpty(appSettings.URLs))
                {
                    Environment.ExitCode = -1;
                    webApplication.Lifetime.StopApplication();
                }
                _ = webApplication.UseSwagger();
                _ = webApplication.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Server V1"));
            }
            _ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
            _ = webApplication.UseStaticFiles();
            _ = webApplication.UseSession();
            _ = webApplication.UseMiddleware<ApiLoggingMiddleware>();
            _ = webApplication.MapControllers();
            logger.LogInformation("Starting Web Application");
            webApplication.Run();
            return 0;
        }
        catch (Exception ex)
        {
            try
            { logger?.LogCritical(ex, "Host terminated unexpectedly"); }
            catch (Exception) { }
            throw;
        }
    }

}