using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog;
using OTSSignsOrchestrator.Core.Configuration;
using OTSSignsOrchestrator.Core.Data;
using OTSSignsOrchestrator.Core.Services;
using OTSSignsOrchestrator.Desktop.Services;
using OTSSignsOrchestrator.Desktop.ViewModels;
using OTSSignsOrchestrator.Desktop.Views;

namespace OTSSignsOrchestrator.Desktop;

public class App : Application
{
    public static IServiceProvider Services { get; private set; } = null!;

    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
    }

    public override void OnFrameworkInitializationCompleted()
    {
        var services = new ServiceCollection();
        ConfigureServices(services);
        Services = services.BuildServiceProvider();

        // Apply migrations
        using (var scope = Services.CreateScope())
        {
            var db = scope.ServiceProvider.GetRequiredService<XiboContext>();
            db.Database.Migrate();
        }

        Log.Information("ApplicationLifetime type: {Type}", ApplicationLifetime?.GetType().FullName ?? "null");

        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            Log.Information("Creating MainWindow...");

            // Import existing instance secrets from Bitwarden (fire-and-forget, non-blocking)
            _ = Task.Run(async () =>
            {
                try
                {
                    // Pre-load config settings from Bitwarden so they're available immediately
                    using var scope = Services.CreateScope();
                    var settings = scope.ServiceProvider.GetRequiredService<SettingsService>();
                    await settings.PreloadCacheAsync();
                    Log.Information("Bitwarden config settings pre-loaded");

                    // Import existing instance secrets that aren't yet tracked
                    var postInit = Services.GetRequiredService<PostInstanceInitService>();
                    await postInit.ImportExistingInstanceSecretsAsync();
                }
                catch (Exception ex)
                {
                    Log.Warning(ex, "Failed to pre-load settings or import instance secrets on startup");
                }
            });

            var vm = Services.GetRequiredService<MainWindowViewModel>();
            Log.Information("MainWindowViewModel resolved");

            var window = new MainWindow
            {
                DataContext = vm
            };

            desktop.MainWindow = window;
            Log.Information("MainWindow assigned to lifetime");

            window.Show();
            window.Activate();
            Log.Information("MainWindow Show() + Activate() called");

            desktop.ShutdownRequested += (_, _) =>
            {
                var ssh = Services.GetService<SshConnectionService>();
                ssh?.Dispose();
            };
        }
        else
        {
            Log.Warning("ApplicationLifetime is NOT IClassicDesktopStyleApplicationLifetime — window cannot be shown");
        }

        base.OnFrameworkInitializationCompleted();
    }

    private static void ConfigureServices(IServiceCollection services)
    {
        // Configuration (reloadOnChange so runtime writes to appsettings.json are picked up)
        var config = new ConfigurationBuilder()
            .SetBasePath(AppContext.BaseDirectory)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build();

        services.AddSingleton<IConfiguration>(config);

        // Options
        services.Configure<GitOptions>(config.GetSection(GitOptions.SectionName));
        services.Configure<DockerOptions>(config.GetSection(DockerOptions.SectionName));
        services.Configure<XiboOptions>(config.GetSection(XiboOptions.SectionName));
        services.Configure<DatabaseOptions>(config.GetSection(DatabaseOptions.SectionName));
        services.Configure<FileLoggingOptions>(config.GetSection(FileLoggingOptions.SectionName));
        services.Configure<BitwardenOptions>(config.GetSection(BitwardenOptions.SectionName));

        // Logging
        services.AddLogging(builder =>
        {
            builder.ClearProviders();
            builder.AddSerilog(dispose: true);
        });

        // Data Protection
        var keysDir = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "OTSSignsOrchestrator", "keys");
        Directory.CreateDirectory(keysDir);

        services.AddDataProtection()
            .PersistKeysToFileSystem(new DirectoryInfo(keysDir))
            .SetApplicationName("OTSSignsOrchestrator");

        // Database
        var connStr = config.GetConnectionString("Default") ?? "Data Source=otssigns-desktop.db";
        services.AddDbContext<XiboContext>(options => options.UseSqlite(connStr));

        // HTTP
        services.AddHttpClient();
        services.AddHttpClient("XiboApi");
        services.AddHttpClient("XiboHealth");
        services.AddHttpClient("AuthentikApi");

        // SSH services (singletons — maintain connections)
        services.AddSingleton<SshConnectionService>();

        // Docker services via SSH (singletons — SetHost() must persist across scopes)
        services.AddSingleton<SshDockerCliService>();
        services.AddSingleton<SshDockerSecretsService>();
        services.AddSingleton<IDockerCliService>(sp => sp.GetRequiredService<SshDockerCliService>());
        services.AddSingleton<IDockerSecretsService>(sp => sp.GetRequiredService<SshDockerSecretsService>());

        // Core services
        services.AddTransient<SettingsService>();
        services.AddTransient<GitTemplateService>();
        services.AddTransient<ComposeRenderService>();
        services.AddTransient<ComposeValidationService>();
        services.AddTransient<XiboApiService>();
        services.AddTransient<InstanceService>();
        services.AddTransient<IBitwardenSecretService, BitwardenSecretService>();
        services.AddTransient<IAuthentikService, AuthentikService>();
        services.AddSingleton<PostInstanceInitService>();

        // ViewModels
        services.AddSingleton<MainWindowViewModel>(); // singleton: one main window, nav state shared
        services.AddTransient<HostsViewModel>();
        services.AddTransient<InstancesViewModel>();
        services.AddTransient<InstanceDetailsViewModel>();
        services.AddTransient<CreateInstanceViewModel>();
        services.AddTransient<SecretsViewModel>();
        services.AddTransient<SettingsViewModel>();
        services.AddTransient<LogsViewModel>();
    }
}
