using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting.WindowsServices;
using Microsoft.Extensions.Logging;
using OI.Metrology.Archive.Models;
using OI.Metrology.Archive.Repositories;
using OI.Metrology.Archive.Services;
using OI.Metrology.Shared.Models;
using OI.Metrology.Shared.Models.Stateless;
using OI.Metrology.Shared.Repositories;
using OI.Metrology.Shared.Services;
using System;
using System.IO;
using System.Reflection;

namespace OI.Metrology.Archive;

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.WorkingDirectoryName))
            throw new Exception("Working directory name must have a value!");
        string workingDirectory = IWorkingDirectory.GetWorkingDirectory(assemblyName, _AppSettings.WorkingDirectoryName);
        Environment.SetEnvironmentVariable(nameof(workingDirectory), workingDirectory);
        try
        {
            _ = webApplicationBuilder.Services.Configure<ApiBehaviorOptions>(options => options.SuppressModelStateInvalidFilter = true);
            _ = webApplicationBuilder.Services.AddControllersWithViews();
            _ = new MetrologyRepository(new SQLDbConnectionFactory(_AppSettings), null);
            _ = webApplicationBuilder.Services.AddDistributedMemoryCache();
            _ = webApplicationBuilder.Services.AddMemoryCache();
            _ = webApplicationBuilder.Services.AddSingleton<AppSettings, AppSettings>(_ => _AppSettings);
            _ = webApplicationBuilder.Services.AddScoped<IAttachmentsService, AttachmentsService>();
            _ = webApplicationBuilder.Services.AddScoped<IInboundDataService, InboundDataService>();
            _ = webApplicationBuilder.Services.AddScoped<IMetrologyRepository, MetrologyRepository>();
            _ = webApplicationBuilder.Services.AddScoped<IRdsMaxRepo, RdsMaxRepo>();
            _ = webApplicationBuilder.Services.AddSingleton<IDbConnectionFactory, SQLDbConnectionFactory>();
            _ = 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>();
#pragma warning disable CA1416
                _ = webApplicationBuilder.Logging.AddEventLog(settings =>
                {
                    if (string.IsNullOrEmpty(settings.SourceName))
                        settings.SourceName = webApplicationBuilder.Environment.ApplicationName;
                });
#pragma warning restore
            }
            WebApplication webApplication = webApplicationBuilder.Build();
            logger = webApplication.Services.GetRequiredService<ILogger<Program>>();
            if (!webApplicationBuilder.Environment.IsDevelopment())
            {
                _ = webApplication.UseExceptionHandler("/Error");
                _ = 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", "Archive V1"));
            }
            _ = webApplication.UseFileServer(enableDirectoryBrowsing: true);
            _ = webApplication.UseStaticFiles();
            _ = webApplication.UseSession();
            _ = webApplication.UseHttpsRedirection();
            _ = 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;
        }
    }

}