using Microsoft.Extensions.DependencyInjection;
using YMhut.Box.Core.Api;
using YMhut.Box.Core.App;
using YMhut.Box.Core.Data;
using YMhut.Box.Core.DevEnvironments;
using YMhut.Box.Core.Downloads;
using YMhut.Box.Core.Feedback;
using YMhut.Box.Core.Logging;
using YMhut.Box.Core.Media;
using YMhut.Box.Core.Net;
using YMhut.Box.Core.Plugins;
using YMhut.Box.Core.Settings;
using YMhut.Box.Core.SolarSystem;
using YMhut.Box.Core.Startup;
using YMhut.Box.Core.System;
using YMhut.Box.Core.Tools;

namespace YMhut.Box.WinUI.Services;

public static class AppServices
{
    private static IServiceProvider? _provider;

    public static IServiceProvider Provider => _provider ?? throw new InvalidOperationException("Services have not been configured.");

    public static void Configure(string? root = null)
    {
        var services = new ServiceCollection();
        var paths = AppPaths.ForCurrentUser(root, InstallLayoutPaths.ResolveAssetsRoot());

        services.AddSingleton(paths);
        services.AddSingleton(new AppSettingsStore(paths.Root));
        services.AddSingleton<ISettingsService, AppSettingsService>();
        services.AddSingleton<IAgreementAcceptanceStore, AgreementAcceptanceStore>();
        services.AddSingleton<ILogService>(provider => new ResilientLogService(
            new SqliteLogService(provider.GetRequiredService<AppPaths>()),
            provider.GetRequiredService<AppPaths>()));
        services.AddSingleton<IStartupCheckStore, StartupCheckStore>();
        services.AddSingleton<IInstallIntegrityCheckService>(provider => new InstallIntegrityCheckService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IStartupCheckStore>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IPluginStateStore, PluginStateStore>();
        services.AddSingleton<PluginLogService>();
        services.AddSingleton<IBuiltInPluginInstallerService>(provider => new BuiltInPluginInstallerService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetService<ILogService>(),
            provider.GetRequiredService<ISettingsService>()));
        services.AddSingleton<IPluginHostProcessService>(provider => new PluginHostProcessService(provider.GetService<ILogService>()));
        services.AddSingleton<IPluginRegistryService>(provider => new PluginRegistryService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IPluginStateStore>(),
            provider.GetService<ILogService>(),
            provider.GetRequiredService<ISettingsService>(),
            provider.GetRequiredService<IBuiltInPluginInstallerService>()));
        services.AddSingleton<IHttpService>(provider => new HttpService(
            logService: provider.GetService<ILogService>(),
            settingsService: provider.GetService<ISettingsService>()));
        services.AddSingleton<IDownloadQueueStore, DownloadQueueStore>();
        services.AddSingleton<IDirectDownloadValidator, DirectDownloadValidator>();
        services.AddSingleton<IDownloadHostProcessService>(provider => new DownloadHostProcessService(provider.GetService<ILogService>()));
        services.AddSingleton<IDownloadManagerService>(provider => new DownloadManagerService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IDownloadQueueStore>(),
            provider.GetRequiredService<IDownloadHostProcessService>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IDevEnvironmentDetectionService>(provider => new DevEnvironmentDetectionService(provider.GetService<ILogService>()));
        services.AddSingleton<IDevEnvironmentCatalogService>(provider => new DevEnvironmentCatalogService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IHttpService>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IApiManager>(provider => new ApiManager(provider.GetRequiredService<IHttpService>(), provider.GetService<ILogService>()));
        services.AddSingleton<IRemoteMediaCatalogService>(provider => new RemoteMediaCatalogService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IApiManager>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IRemoteMediaResolver, RemoteMediaResolver>();
        services.AddSingleton<IIndependentWindowHostLauncher>(provider => new IndependentWindowHostLauncher(provider.GetService<ILogService>()));
        services.AddSingleton<IToolLinkNavigationService>(provider => new ToolLinkNavigationService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IIndependentWindowHostLauncher>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IOpenSourceReferenceService>(provider => new OpenSourceReferenceService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IReferenceDataService, ReferenceDataService>();
        services.AddSingleton<ISystemMetricsService, SystemMetricsService>();
        services.AddSingleton<ITitleWeatherService>(provider => new TitleWeatherService(
            provider.GetRequiredService<IHttpService>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IHardwareInfoService>(provider => new HardwareInfoService(provider.GetService<ILogService>()));
        services.AddSingleton<IRiskConfirmationStore>(provider => new RiskConfirmationStore(
            provider.GetRequiredService<AppPaths>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IExternalToolCatalogService>(provider => new ExternalToolCatalogService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<IExternalToolLaunchService>(provider => new ExternalToolLaunchService(
            provider.GetService<ILogService>(),
            provider.GetService<ISettingsService>()));
        services.AddSingleton<IBuiltinReferenceToolCatalog, BuiltinReferenceToolCatalog>();
        services.AddSingleton<IBuiltinReferenceToolService>(provider => new BuiltinReferenceToolService(
            provider.GetService<ILogService>(),
            provider.GetService<ISettingsService>(),
            provider.GetService<IHardwareInfoService>()));
        services.AddSingleton<IToolWorkerService>(provider => new ProcessToolWorkerService(
            provider.GetService<IApiManager>(),
            provider.GetService<IReferenceDataService>(),
            provider.GetService<ILogService>()));
        services.AddSingleton(_ => new ToolCatalog(ToolCatalog.DefaultModules()));
        services.AddSingleton<IToolResultExperienceCatalog, ToolResultExperienceCatalog>();
        services.AddSingleton<ToolResultWebBridge>();
        services.AddSingleton<ToolPageWebBridge>();
        services.AddSingleton<IFeedbackPackageService>(provider => new FeedbackPackageService(
            provider.GetRequiredService<ILogService>(),
            provider.GetRequiredService<ISystemMetricsService>(),
            provider.GetRequiredService<ToolCatalog>()));
        services.AddSingleton<IFeedbackSubmissionService>(_ => new FeedbackSubmissionService());
        services.AddSingleton<IFeedbackRecordStore>(_ => new FeedbackRecordStore());
        services.AddSingleton<IStartupService, WindowsStartupService>();
        services.AddSingleton<ITrayService, WindowsTrayService>();
        services.AddSingleton<IAppInstallerUpdateService, AppInstallerUpdateService>();
        services.AddSingleton<IAppVersionService, AppVersionService>();
        services.AddSingleton<ISolarEphemerisService>(provider => new SolarEphemerisService(
            provider.GetRequiredService<AppPaths>(),
            provider.GetRequiredService<IHttpService>(),
            provider.GetService<ILogService>()));
        services.AddSingleton<WebView2EnvironmentFactory>();
        services.AddSingleton<IUiPerformanceCoordinator, UiPerformanceCoordinator>();
        services.AddSingleton<WindowStateService>();
        services.AddSingleton<IStartupInitializationService, StartupInitializationService>();

        _provider = services.BuildServiceProvider();
    }

    public static T GetRequiredService<T>() where T : notnull
    {
        return Provider.GetRequiredService<T>();
    }
}
