using Dalamud.Game;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Interface;
using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin;
using Dalamud.Plugin.Services;
using LightlessSync.FileCache;
using LightlessSync.Interop;
using LightlessSync.Interop.Ipc;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Factories;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.PlayerData.Services;
using LightlessSync.Services;
using LightlessSync.Services.Chat;
using LightlessSync.Services.ActorTracking;
using LightlessSync.Services.CharaData;
using LightlessSync.Services.Events;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.Rendering;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.Services.TextureCompression;
using LightlessSync.UI;
using LightlessSync.UI.Components;
using LightlessSync.UI.Components.Popup;
using LightlessSync.UI.Handlers;
using LightlessSync.UI.Tags;
using LightlessSync.UI.Services;
using LightlessSync.WebAPI;
using LightlessSync.WebAPI.Files;
using LightlessSync.WebAPI.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NReco.Logging.File;
using System.Net.Http.Headers;
using System.Reflection;
using OtterTex;
using LightlessSync.Services.LightFinder;
using LightlessSync.Services.PairProcessing;
using LightlessSync.UI.Models;

namespace LightlessSync;

public sealed class Plugin : IDalamudPlugin
{
    private readonly IHost _host;

    public Plugin(IDalamudPluginInterface pluginInterface, ICommandManager commandManager, IDataManager gameData,
        IFramework framework, IObjectTable objectTable, IClientState clientState, ICondition condition, IChatGui chatGui,
        IGameGui gameGui, IDtrBar dtrBar, IPluginLog pluginLog, ITargetManager targetManager, INotificationManager notificationManager,
        ITextureProvider textureProvider, IContextMenu contextMenu, IGameInteropProvider gameInteropProvider, IGameConfig gameConfig,
        ISigScanner sigScanner, INamePlateGui namePlateGui, IAddonLifecycle addonLifecycle, IPlayerState playerState)
    {
        NativeDll.Initialize(pluginInterface.AssemblyLocation.DirectoryName);
        if (!Directory.Exists(pluginInterface.ConfigDirectory.FullName))
            Directory.CreateDirectory(pluginInterface.ConfigDirectory.FullName);
        var traceDir = Path.Join(pluginInterface.ConfigDirectory.FullName, "tracelog");
        if (!Directory.Exists(traceDir))
            Directory.CreateDirectory(traceDir);

        foreach (var file in Directory.EnumerateFiles(traceDir)
            .Select(f => new FileInfo(f))
            .OrderByDescending(f => f.LastWriteTimeUtc).Skip(9))
        {
            int attempts = 0;
            bool deleted = false;
            while (!deleted && attempts < 5)
            {
                try
                {
                    file.Delete();
                    deleted = true;
                }
                catch
                {
                    attempts++;
                    Thread.Sleep(500);
                }
            }
        }

        _host = new HostBuilder()
        .UseContentRoot(pluginInterface.ConfigDirectory.FullName)
        .ConfigureLogging(lb =>
        {
            lb.ClearProviders();
            lb.AddDalamudLogging(pluginLog, gameData.HasModifiedGameDataFiles);
            lb.AddFile(Path.Combine(traceDir, $"lightless-trace-{DateTime.Now:yyyy-MM-dd-HH-mm-ss}.log"), (opt) =>
            {
                opt.Append = true;
                opt.RollingFilesConvention = FileLoggerOptions.FileRollingConvention.Ascending;
                opt.MinLevel = LogLevel.Trace;
                opt.FileSizeLimitBytes = 50 * 1024 * 1024;
            });
            lb.SetMinimumLevel(LogLevel.Trace);
        })
    .ConfigureServices(services =>
    {
        var configDir = pluginInterface.ConfigDirectory.FullName;

        // Core infrastructure
        services.AddSingleton(new WindowSystem("LightlessSync"));
        services.AddSingleton<FileDialogManager>();
        services.AddSingleton(new Dalamud.Localization("LightlessSync.Localization.", string.Empty, useEmbedded: true));
        services.AddSingleton(gameGui);
        services.AddSingleton(gameInteropProvider);
        services.AddSingleton(addonLifecycle);
        services.AddSingleton<IUiBuilder>(pluginInterface.UiBuilder);

        // Core singletons
        services.AddSingleton<LightlessMediator>();
        services.AddSingleton<FileCacheManager>();
        services.AddSingleton<ServerConfigurationManager>();
        services.AddSingleton<ProfileTagService>();
        services.AddSingleton<ApiController>();
        services.AddSingleton<PerformanceCollectorService>();
        services.AddSingleton<NameplateUpdateHookService>();
        services.AddSingleton<HubFactory>();
        services.AddSingleton<FileUploadManager>();
        services.AddSingleton<FileTransferOrchestrator>();
        services.AddSingleton<LightlessPlugin>();
        services.AddSingleton<LightlessProfileManager>();
        services.AddSingleton<TextureCompressionService>();
        services.AddSingleton<TextureDownscaleService>();
        services.AddSingleton<GameObjectHandlerFactory>();
        services.AddSingleton<FileDownloadManagerFactory>();
        services.AddSingleton<PairProcessingLimiter>();
        services.AddSingleton<XivDataAnalyzer>();
        services.AddSingleton<CharacterAnalyzer>();
        services.AddSingleton<TokenProvider>();
        services.AddSingleton<PluginWarningNotificationService>();
        services.AddSingleton<FileCompactor>();
        services.AddSingleton<TagHandler>();
        services.AddSingleton<PairRequestService>();
        services.AddSingleton<ZoneChatService>();
        services.AddSingleton<ChatEmoteService>();
        services.AddSingleton<IdDisplayHandler>();
        services.AddSingleton<PlayerPerformanceService>();
        services.AddSingleton<PenumbraTempCollectionJanitor>();
        services.AddSingleton<LocationShareService>();

        services.AddSingleton<TextureMetadataHelper>(sp =>
            new TextureMetadataHelper(sp.GetRequiredService<ILogger<TextureMetadataHelper>>(), gameData));

        services.AddSingleton(sp => new Lazy<ApiController>(() => sp.GetRequiredService<ApiController>()));

        services.AddSingleton(sp => new PairFactory(
            sp.GetRequiredService<ILoggerFactory>(),
            sp.GetRequiredService<PairLedger>(),
            sp.GetRequiredService<LightlessMediator>(),
            new Lazy<ServerConfigurationManager>(() => sp.GetRequiredService<ServerConfigurationManager>()),
            sp.GetRequiredService<Lazy<ApiController>>()));

        services.AddSingleton(sp => new TransientResourceManager(
            sp.GetRequiredService<ILogger<TransientResourceManager>>(),
            sp.GetRequiredService<TransientConfigService>(),
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<ActorObjectService>(),
            sp.GetRequiredService<GameObjectHandlerFactory>()));

        // Lightless Chara data
        services.AddSingleton<CharaDataManager>();
        services.AddSingleton<CharaDataFileHandler>();
        services.AddSingleton<CharaDataCharacterHandler>();
        services.AddSingleton<CharaDataNearbyManager>();
        services.AddSingleton<CharaDataGposeTogetherManager>();

        // Game / VFX / IPC
        services.AddSingleton(sp => new VfxSpawnManager(
            sp.GetRequiredService<ILogger<VfxSpawnManager>>(),
            gameInteropProvider,
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new BlockedCharacterHandler(
            sp.GetRequiredService<ILogger<BlockedCharacterHandler>>(),
            gameInteropProvider));

        services.AddSingleton(sp => new IpcProvider(
            sp.GetRequiredService<ILogger<IpcProvider>>(),
            pluginInterface,
            sp.GetRequiredService<CharaDataManager>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new PictomancyService(
            sp.GetRequiredService<ILogger<PictomancyService>>(),
            pluginInterface));

        // Tag (Groups) UIs
        services.AddSingleton<SelectPairForTagUi>();
        services.AddSingleton<RenamePairTagUi>();
        services.AddSingleton<SelectSyncshellForTagUi>();
        services.AddSingleton<RenameSyncshellTagUi>();

        // Eventing / utilities
        services.AddSingleton(sp => new EventAggregator(
            configDir,
            sp.GetRequiredService<ILogger<EventAggregator>>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new ActorObjectService(
            sp.GetRequiredService<ILogger<ActorObjectService>>(),
            framework,
            gameInteropProvider,
            objectTable,
            clientState,
            condition,
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new DalamudUtilService(
            sp.GetRequiredService<ILogger<DalamudUtilService>>(),
            clientState,
            objectTable,
            framework,
            gameGui,
            condition,
            gameData,
            targetManager,
            gameConfig,
            playerState,
            sp.GetRequiredService<ActorObjectService>(),
            sp.GetRequiredService<BlockedCharacterHandler>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PerformanceCollectorService>(),
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<PlayerPerformanceConfigService>(),
            new Lazy<PairFactory>(() => sp.GetRequiredService<PairFactory>())));

        // Pairing and Dtr integration
        services.AddSingleton<PairManager>();
        services.AddSingleton<PairStateCache>();
        services.AddSingleton<PairPerformanceMetricsCache>();
        services.AddSingleton<PairLedger>();
        services.AddSingleton<PairUiService>();
        services.AddSingleton<IPairHandlerAdapterFactory, PairHandlerAdapterFactory>();

        services.AddSingleton(sp => new PairHandlerRegistry(
            sp.GetRequiredService<IPairHandlerAdapterFactory>(),
            sp.GetRequiredService<PairManager>(),
            sp.GetRequiredService<PairStateCache>(),
            sp.GetRequiredService<PairPerformanceMetricsCache>(),
            sp.GetRequiredService<ILogger<PairHandlerRegistry>>()));

        services.AddSingleton(sp => new DtrEntry(
            sp.GetRequiredService<ILogger<DtrEntry>>(),
            dtrBar,
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PairUiService>(),
            sp.GetRequiredService<PairRequestService>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<ServerConfigurationManager>(),
            sp.GetRequiredService<LightFinderService>(),
            sp.GetRequiredService<LightFinderScannerService>(),
            sp.GetRequiredService<DalamudUtilService>()));

        services.AddSingleton(sp => new PairCoordinator(
            sp.GetRequiredService<ILogger<PairCoordinator>>(),
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PairHandlerRegistry>(),
            sp.GetRequiredService<PairManager>(),
            sp.GetRequiredService<PairLedger>(),
            sp.GetRequiredService<ServerConfigurationManager>(),
            sp.GetRequiredService<PairPerformanceMetricsCache>()));

        // Light finder / redraw / context menu
        services.AddSingleton<RedrawManager>();
        services.AddSingleton<LightFinderService>();

        services.AddSingleton(sp => new LightFinderPlateHandler(
            sp.GetRequiredService<ILogger<LightFinderPlateHandler>>(),
            addonLifecycle,
            gameGui,
            clientState,
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<LightlessMediator>(),
            objectTable,
            sp.GetRequiredService<PairUiService>(),
            pluginInterface,
            sp.GetRequiredService<PictomancyService>()));

        services.AddSingleton(sp => new LightFinderNativePlateHandler(
            sp.GetRequiredService<ILogger<LightFinderNativePlateHandler>>(),
            clientState,
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<LightlessMediator>(),
            objectTable,
            sp.GetRequiredService<PairUiService>(),
            sp.GetRequiredService<NameplateUpdateHookService>()));

        services.AddSingleton(sp => new LightFinderScannerService(
            sp.GetRequiredService<ILogger<LightFinderScannerService>>(),
            framework,
            sp.GetRequiredService<LightFinderService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<LightFinderPlateHandler>(),
            sp.GetRequiredService<LightFinderNativePlateHandler>(),
            sp.GetRequiredService<ActorObjectService>()));

        services.AddSingleton(sp => new ContextMenuService(
            contextMenu,
            pluginInterface,
            gameData,
            sp.GetRequiredService<ILogger<ContextMenuService>>(),
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<ApiController>(),
            objectTable,
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<PairRequestService>(),
            sp.GetRequiredService<PairUiService>(),
            clientState,
            sp.GetRequiredService<LightFinderScannerService>(),
            sp.GetRequiredService<LightFinderService>(),
            sp.GetRequiredService<LightlessProfileManager>(),
            sp.GetRequiredService<LightlessMediator>(),
            chatGui,
            sp.GetRequiredService<NotificationService>())
            );

        // IPC callers / manager
        services.AddSingleton(sp => new IpcCallerPenumbra(
            sp.GetRequiredService<ILogger<IpcCallerPenumbra>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<RedrawManager>(),
            sp.GetRequiredService<ActorObjectService>()));

        services.AddSingleton(sp => new IpcCallerGlamourer(
            sp.GetRequiredService<ILogger<IpcCallerGlamourer>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<RedrawManager>()));

        services.AddSingleton(sp => new IpcCallerCustomize(
            sp.GetRequiredService<ILogger<IpcCallerCustomize>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcCallerHeels(
            sp.GetRequiredService<ILogger<IpcCallerHeels>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcCallerHonorific(
            sp.GetRequiredService<ILogger<IpcCallerHonorific>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcCallerMoodles(
            sp.GetRequiredService<ILogger<IpcCallerMoodles>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcCallerPetNames(
            sp.GetRequiredService<ILogger<IpcCallerPetNames>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcCallerBrio(
            sp.GetRequiredService<ILogger<IpcCallerBrio>>(),
            pluginInterface,
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddSingleton(sp => new IpcManager(
            sp.GetRequiredService<ILogger<IpcManager>>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<IpcCallerPenumbra>(),
            sp.GetRequiredService<IpcCallerGlamourer>(),
            sp.GetRequiredService<IpcCallerCustomize>(),
            sp.GetRequiredService<IpcCallerHeels>(),
            sp.GetRequiredService<IpcCallerHonorific>(),
            sp.GetRequiredService<IpcCallerMoodles>(),
            sp.GetRequiredService<IpcCallerPetNames>(),
            sp.GetRequiredService<IpcCallerBrio>()));

        // Notifications / HTTP
        services.AddSingleton(sp => new NotificationService(
            sp.GetRequiredService<ILogger<NotificationService>>(),
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<DalamudUtilService>(),
            notificationManager,
            chatGui,
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PairRequestService>(),
            sp.GetRequiredService<PairUiService>(),
            sp.GetRequiredService<PairFactory>()));

        services.AddSingleton(sp =>
        {
            var httpClient = new HttpClient();
            var ver = Assembly.GetExecutingAssembly().GetName().Version;
            httpClient.DefaultRequestHeaders.UserAgent.Add(
                new ProductInfoHeaderValue("LightlessSync", $"{ver!.Major}.{ver.Minor}.{ver.Build}"));
            return httpClient;
        });

        // Lightless Config services
        services.AddSingleton(sp => new UiThemeConfigService(configDir));
        services.AddSingleton(sp => new ChatConfigService(configDir));
        services.AddSingleton(sp =>
        {
            var cfg = new LightlessConfigService(configDir);
            var theme = sp.GetRequiredService<UiThemeConfigService>();
            LightlessSync.UI.Style.MainStyle.Init(cfg, theme);
            return cfg;
        });
        services.AddSingleton(sp => new ServerConfigService(configDir));
        services.AddSingleton(sp => new NotesConfigService(configDir));
        services.AddSingleton(sp => new PairTagConfigService(configDir));
        services.AddSingleton(sp => new SyncshellTagConfigService(configDir));
        services.AddSingleton(sp => new TransientConfigService(configDir));
        services.AddSingleton(sp => new XivDataStorageService(configDir));
        services.AddSingleton(sp => new PlayerPerformanceConfigService(configDir));
        services.AddSingleton(sp => new CharaDataConfigService(configDir));

        // Config adapters
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<LightlessConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<UiThemeConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<ChatConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<ServerConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<NotesConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<PairTagConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<SyncshellTagConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<TransientConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<XivDataStorageService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<PlayerPerformanceConfigService>());
        services.AddSingleton<IConfigService<ILightlessConfiguration>>(sp => sp.GetRequiredService<CharaDataConfigService>());

        services.AddSingleton<ConfigurationMigrator>();
        services.AddSingleton<ConfigurationSaveService>();

        // Scoped factories / UI
        services.AddScoped<DrawEntityFactory>();
        services.AddScoped<CacheMonitor>();
        services.AddScoped<UiFactory>();
        services.AddScoped<SelectTagForPairUi>();
        services.AddScoped<SelectTagForSyncshellUi>();
        services.AddScoped<WindowMediatorSubscriberBase, SettingsUi>();
        services.AddScoped<WindowMediatorSubscriberBase, CompactUi>();
        services.AddScoped<WindowMediatorSubscriberBase, IntroUi>();
        services.AddScoped<WindowMediatorSubscriberBase, DownloadUi>();
        services.AddScoped<WindowMediatorSubscriberBase, PopoutProfileUi>();
        services.AddScoped<WindowMediatorSubscriberBase, DataAnalysisUi>();
        services.AddScoped<WindowMediatorSubscriberBase, JoinSyncshellUI>();
        services.AddScoped<WindowMediatorSubscriberBase, CreateSyncshellUI>();
        services.AddScoped<WindowMediatorSubscriberBase, EventViewerUI>();
        services.AddScoped<WindowMediatorSubscriberBase, CharaDataHubUi>();
        services.AddScoped<WindowMediatorSubscriberBase, UpdateNotesUi>();
        services.AddScoped<WindowMediatorSubscriberBase, ZoneChatUi>();

        services.AddScoped<WindowMediatorSubscriberBase, EditProfileUi>(sp => new EditProfileUi(
            sp.GetRequiredService<ILogger<EditProfileUi>>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<UiSharedService>(),
            sp.GetRequiredService<FileDialogManager>(),
            sp.GetRequiredService<LightlessProfileManager>(),
            sp.GetRequiredService<ProfileTagService>(),
            sp.GetRequiredService<PerformanceCollectorService>()));

        services.AddScoped<WindowMediatorSubscriberBase, PopupHandler>();

        services.AddScoped<WindowMediatorSubscriberBase, LightFinderUI>(sp => new LightFinderUI(
            sp.GetRequiredService<ILogger<LightFinderUI>>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PerformanceCollectorService>(),
            sp.GetRequiredService<LightFinderService>(),
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<UiSharedService>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<LightFinderScannerService>(),
            sp.GetRequiredService<LightFinderPlateHandler>()));

        services.AddScoped<WindowMediatorSubscriberBase, SyncshellFinderUI>(sp => new SyncshellFinderUI(
            sp.GetRequiredService<ILogger<SyncshellFinderUI>>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PerformanceCollectorService>(),
            sp.GetRequiredService<LightFinderService>(),
            sp.GetRequiredService<UiSharedService>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<LightFinderScannerService>(),
            sp.GetRequiredService<PairUiService>(),
            sp.GetRequiredService<DalamudUtilService>(),
            sp.GetRequiredService<LightlessProfileManager>()));

        services.AddScoped<IPopupHandler, BanUserPopupHandler>();
        services.AddScoped<IPopupHandler, CensusPopupHandler>();

        services.AddScoped<WindowMediatorSubscriberBase, LightlessNotificationUi>(sp =>
            new LightlessNotificationUi(
                sp.GetRequiredService<ILogger<LightlessNotificationUi>>(),
                sp.GetRequiredService<LightlessMediator>(),
                sp.GetRequiredService<PerformanceCollectorService>(),
                sp.GetRequiredService<LightlessConfigService>()));

        services.AddScoped<CacheCreationService>();
        services.AddScoped<PlayerDataFactory>();
        services.AddScoped<VisibleUserDataDistributor>();

        services.AddScoped(sp => new UiService(
            sp.GetRequiredService<ILogger<UiService>>(),
            pluginInterface.UiBuilder,
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<WindowSystem>(),
            sp.GetServices<WindowMediatorSubscriberBase>(),
            sp.GetRequiredService<UiFactory>(),
            sp.GetRequiredService<FileDialogManager>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PairFactory>()));

        services.AddScoped(sp => new CommandManagerService(
            commandManager,
            sp.GetRequiredService<PerformanceCollectorService>(),
            sp.GetRequiredService<ServerConfigurationManager>(),
            sp.GetRequiredService<CacheMonitor>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<LightlessConfigService>()));

        services.AddScoped(sp => new UiSharedService(
            sp.GetRequiredService<ILogger<UiSharedService>>(),
            sp.GetRequiredService<IpcManager>(),
            sp.GetRequiredService<ApiController>(),
            sp.GetRequiredService<CacheMonitor>(),
            sp.GetRequiredService<FileDialogManager>(),
            sp.GetRequiredService<LightlessConfigService>(),
            sp.GetRequiredService<DalamudUtilService>(),
            pluginInterface,
            textureProvider,
            sp.GetRequiredService<Dalamud.Localization>(),
            sp.GetRequiredService<ServerConfigurationManager>(),
            sp.GetRequiredService<TokenProvider>(),
            sp.GetRequiredService<LightlessMediator>()));

        services.AddScoped(sp => new NameplateService(
            sp.GetRequiredService<ILogger<NameplateService>>(),
            sp.GetRequiredService<LightlessConfigService>(),
            clientState,
            gameGui,
            objectTable,
            sp.GetRequiredService<LightlessMediator>(),
            sp.GetRequiredService<PairUiService>(),
            sp.GetRequiredService<NameplateUpdateHookService>()));

        // Hosted services
        services.AddHostedService(sp => sp.GetRequiredService<ConfigurationSaveService>());
        services.AddHostedService(sp => sp.GetRequiredService<ActorObjectService>());
        services.AddHostedService(sp => sp.GetRequiredService<LightlessMediator>());
        services.AddHostedService(sp => sp.GetRequiredService<ZoneChatService>());
        services.AddHostedService(sp => sp.GetRequiredService<NotificationService>());
        services.AddHostedService(sp => sp.GetRequiredService<FileCacheManager>());
        services.AddHostedService(sp => sp.GetRequiredService<ConfigurationMigrator>());
        services.AddHostedService(sp => sp.GetRequiredService<DalamudUtilService>());
        services.AddHostedService(sp => sp.GetRequiredService<PerformanceCollectorService>());
        services.AddHostedService(sp => sp.GetRequiredService<DtrEntry>());
        services.AddHostedService(sp => sp.GetRequiredService<EventAggregator>());
        services.AddHostedService(sp => sp.GetRequiredService<IpcProvider>());
        services.AddHostedService(sp => sp.GetRequiredService<LightlessPlugin>());
        services.AddHostedService(sp => sp.GetRequiredService<ContextMenuService>());
        services.AddHostedService(sp => sp.GetRequiredService<LightFinderService>());
        services.AddHostedService(sp => sp.GetRequiredService<LightFinderPlateHandler>());
        services.AddHostedService(sp => sp.GetRequiredService<LightFinderNativePlateHandler>());
    }).Build();

        _ = _host.StartAsync();
    }

    public void Dispose()
    {
        _host.StopAsync().GetAwaiter().GetResult();
        _host.Dispose();
    }
}
