using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PSLauncher.App.Services;
using PSLauncher.App.ViewModels;
using PSLauncher.App.Views;
using PSLauncher.Core.Configuration;
using PSLauncher.Core.Downloads;
using PSLauncher.Core.Installations;
using PSLauncher.Core.Integrity;
using PSLauncher.Core.Licensing;
using PSLauncher.Core.Manifests;
using PSLauncher.Core.Process;
using PSLauncher.Core.Updates;
using PSLauncher.Models;
using Serilog;

namespace PSLauncher.App;

public partial class App : Application
{
    private IHost? _host;

    public static string LogsDirectory { get; private set; } = string.Empty;

    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        // Logs avant tout — pour ne rien perdre des erreurs au boot
        LogsDirectory = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
            "PSLauncher", "logs");
        Directory.CreateDirectory(LogsDirectory);

        Log.Logger = new LoggerConfiguration()
            .MinimumLevel.Debug()
            .Enrich.FromLogContext()
            .WriteTo.Debug()
            .WriteTo.File(
                path: Path.Combine(LogsDirectory, "app-.log"),
                rollingInterval: RollingInterval.Day,
                retainedFileCountLimit: 10,
                outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {SourceContext} {Message:lj}{NewLine}{Exception}")
            .CreateLogger();

        Log.Information("PSLauncher starting (logs in {Path})", LogsDirectory);

        AppDomain.CurrentDomain.UnhandledException += (_, args) =>
            Log.Fatal((Exception)args.ExceptionObject, "Unhandled exception (AppDomain)");
        DispatcherUnhandledException += (_, args) =>
        {
            Log.Error(args.Exception, "Unhandled UI exception");
            args.Handled = false;
        };

        _host = Host.CreateDefaultBuilder()
            .UseSerilog()
            .ConfigureServices((_, services) =>
            {
                services.AddSingleton<IConfigStore, ConfigStore>();
                services.AddSingleton<LocalConfig>(sp => sp.GetRequiredService<IConfigStore>().Load());

                services.AddSingleton(sp =>
                {
                    var http = new HttpClient(new SocketsHttpHandler
                    {
                        PooledConnectionLifetime = TimeSpan.FromMinutes(5),
                        AutomaticDecompression = System.Net.DecompressionMethods.All
                    })
                    {
                        Timeout = Timeout.InfiniteTimeSpan
                    };
                    http.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("PSLauncher", "0.5"));
                    return http;
                });

                services.AddSingleton<IInstallationRegistry>(sp =>
                    new InstallationRegistry(
                        sp.GetRequiredService<ILogger<InstallationRegistry>>(),
                        () => sp.GetRequiredService<LocalConfig>().InstallRoot));

                services.AddSingleton<IProcessLauncher, ProcessLauncher>();
                services.AddSingleton<IIntegrityService, IntegrityService>();
                services.AddSingleton<IZipInstaller, ZipInstaller>();
                services.AddSingleton<IDownloadStateStore, DownloadStateStore>();

                services.AddSingleton<IManifestService>(sp =>
                    new ManifestService(
                        sp.GetRequiredService<HttpClient>(),
                        () => sp.GetRequiredService<LocalConfig>().ServerBaseUrl,
                        sp.GetRequiredService<ILogger<ManifestService>>()));

                services.AddSingleton<IDownloadManager, DownloadManager>();
                services.AddSingleton<IUpdateChecker, UpdateChecker>();

                services.AddSingleton<ILicenseService>(sp =>
                    new LicenseService(
                        sp.GetRequiredService<HttpClient>(),
                        () => sp.GetRequiredService<LocalConfig>().ServerBaseUrl,
                        sp.GetRequiredService<IConfigStore>(),
                        sp.GetRequiredService<LocalConfig>(),
                        sp.GetRequiredService<ILogger<LicenseService>>()));

                services.AddSingleton<IToastService, ToastService>();

                services.AddTransient<SettingsViewModel>();
                services.AddSingleton<MainViewModel>();
                services.AddSingleton<MainWindow>();
            })
            .Build();

        var window = _host.Services.GetRequiredService<MainWindow>();
        window.DataContext = _host.Services.GetRequiredService<MainViewModel>();
        MainWindow = window;
        window.Show();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        Log.Information("PSLauncher shutting down");
        Log.CloseAndFlush();
        _host?.Dispose();
        base.OnExit(e);
    }
}
