using System.IO;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Infrastructure.Auth;
using SharepointToolbox.Infrastructure.Logging;
using SharepointToolbox.Infrastructure.Persistence;
using SharepointToolbox.Services;
using SharepointToolbox.Services.Export;
using SharepointToolbox.ViewModels;
using SharepointToolbox.ViewModels.Tabs;
using SharepointToolbox.Views.Dialogs;
using SharepointToolbox.Views.Tabs;
using System.Windows;

namespace SharepointToolbox;

public partial class App : Application
{
    [STAThread]
    public static void Main(string[] args)
    {
        using IHost host = Host.CreateDefaultBuilder(args)
            .UseSerilog((ctx, cfg) => cfg
                .WriteTo.File(
                    Path.Combine(
                        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                        "SharepointToolbox", "logs", "app-.log"),
                    rollingInterval: RollingInterval.Day,
                    retainedFileCountLimit: 30))
            .ConfigureServices(RegisterServices)
            .Build();

        host.Start();
        App app = new();
        app.InitializeComponent();

        var mainWindow = host.Services.GetRequiredService<MainWindow>();

        // Wire LogPanelSink now that we have the RichTextBox
        Log.Logger = new LoggerConfiguration()
            .WriteTo.File(
                Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                    "SharepointToolbox", "logs", "app-.log"),
                rollingInterval: RollingInterval.Day,
                retainedFileCountLimit: 30)
            .WriteTo.Sink(new LogPanelSink(mainWindow.GetLogPanel()))
            .CreateLogger();

        // Global exception handlers
        app.DispatcherUnhandledException += (s, e) =>
        {
            Log.Fatal(e.Exception, "Unhandled UI exception");
            MessageBox.Show(
                $"A fatal error occurred:\n{e.Exception.Message}\n\nCheck log for details.",
                "Fatal Error", MessageBoxButton.OK, MessageBoxImage.Error);
            e.Handled = true;
        };
        TaskScheduler.UnobservedTaskException += (s, e) =>
        {
            Log.Fatal(e.Exception, "Unobserved task exception");
            e.SetObserved();
        };

        app.MainWindow = mainWindow;
        app.MainWindow.Visibility = Visibility.Visible;
        app.Run();
    }

    private static void RegisterServices(HostBuilderContext ctx, IServiceCollection services)
    {
        var appData = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "SharepointToolbox");
        services.AddSingleton(_ => new ProfileRepository(Path.Combine(appData, "profiles.json")));
        services.AddSingleton(_ => new SettingsRepository(Path.Combine(appData, "settings.json")));
        services.AddSingleton<MsalClientFactory>();
        services.AddSingleton<SessionManager>();
        services.AddSingleton<ISessionManager>(sp => sp.GetRequiredService<SessionManager>());
        services.AddSingleton<ProfileService>();
        services.AddSingleton<SettingsService>();
        services.AddSingleton<MainWindowViewModel>();
        services.AddTransient<ProfileManagementViewModel>();
        services.AddTransient<SettingsViewModel>();
        services.AddTransient<ProfileManagementDialog>();
        services.AddTransient<SettingsView>();

        // Phase 2: Permissions
        services.AddTransient<IPermissionsService, PermissionsService>();
        services.AddTransient<ISiteListService, SiteListService>();
        services.AddTransient<CsvExportService>();
        services.AddTransient<HtmlExportService>();
        services.AddTransient<PermissionsViewModel>();
        services.AddTransient<PermissionsView>();
        services.AddTransient<SitePickerDialog>();
        services.AddTransient<Func<TenantProfile, SitePickerDialog>>(sp =>
            profile => new SitePickerDialog(sp.GetRequiredService<ISiteListService>(), profile));

        services.AddSingleton<MainWindow>();
    }
}
