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();

        // Apply persisted language before any UI is created so bindings resolve to the saved culture.
        try
        {
            var settings = host.Services.GetRequiredService<SettingsService>().GetSettingsAsync().GetAwaiter().GetResult();
            if (!string.IsNullOrWhiteSpace(settings.Lang))
                Localization.TranslationSource.Instance.CurrentCulture = new System.Globalization.CultureInfo(settings.Lang);
        }
        catch (Exception ex)
        {
            Log.Warning(ex, "Failed to apply persisted language at startup");
        }

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

        // Apply persisted theme (System/Light/Dark) before MainWindow constructs so brushes resolve correctly.
        try
        {
            var theme = host.Services.GetRequiredService<ThemeManager>();
            var settings = host.Services.GetRequiredService<SettingsService>().GetSettingsAsync().GetAwaiter().GetResult();
            theme.ApplyFromString(settings.Theme);
        }
        catch (Exception ex)
        {
            Log.Warning(ex, "Failed to apply persisted theme at startup");
        }

        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")));

        // Phase 10: Branding Data Foundation
        services.AddSingleton(_ => new BrandingRepository(Path.Combine(appData, "branding.json")));
        services.AddSingleton<IBrandingService, BrandingService>();
        services.AddTransient<IGraphUserDirectoryService, GraphUserDirectoryService>();

        services.AddSingleton<MsalClientFactory>();
        services.AddSingleton<SessionManager>();
        services.AddSingleton<ISessionManager>(sp => sp.GetRequiredService<SessionManager>());
        services.AddSingleton<ProfileService>();
        services.AddSingleton<SettingsService>();
        services.AddSingleton<ThemeManager>();
        services.AddSingleton<MainWindowViewModel>();
        // Phase 11-04: ProfileManagementViewModel and SettingsViewModel now receive IBrandingService and GraphClientFactory
        services.AddTransient<ProfileManagementViewModel>();
        services.AddTransient<SettingsViewModel>();
        services.AddTransient<ProfileManagementDialog>();
        services.AddTransient<SettingsView>();

        // Phase 3: Storage
        services.AddTransient<IStorageService, StorageService>();
        services.AddTransient<StorageCsvExportService>();
        services.AddTransient<StorageHtmlExportService>();
        services.AddTransient<StorageViewModel>();
        services.AddTransient<StorageView>();

        // Phase 3: File Search
        services.AddTransient<ISearchService, SearchService>();
        services.AddTransient<SearchCsvExportService>();
        services.AddTransient<SearchHtmlExportService>();
        services.AddTransient<SearchViewModel>();
        services.AddTransient<SearchView>();

        // Phase 3: Duplicates
        services.AddTransient<IDuplicatesService, DuplicatesService>();
        services.AddTransient<DuplicatesHtmlExportService>();
        services.AddTransient<DuplicatesCsvExportService>();
        services.AddTransient<DuplicatesViewModel>();
        services.AddTransient<DuplicatesView>();

        // Versions cleanup
        services.AddTransient<IVersionCleanupService, VersionCleanupService>();
        services.AddTransient<VersionCleanupHtmlExportService>();
        services.AddTransient<VersionCleanupViewModel>();
        services.AddTransient<VersionCleanupView>();

        // Phase 2: Permissions
        services.AddTransient<ISystemGroupTargetResolver, SystemGroupTargetResolver>();
        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));

        // Phase 4: Bulk Operations Infrastructure
        var templatesDir = Path.Combine(appData, "templates");
        services.AddSingleton(_ => new TemplateRepository(templatesDir));
        services.AddSingleton<GraphClientFactory>();
        services.AddTransient<ICsvValidationService, CsvValidationService>();
        services.AddTransient<BulkResultCsvExportService>();

        // Phase 4: File Transfer
        services.AddTransient<IFileTransferService, FileTransferService>();
        services.AddTransient<TransferViewModel>();
        services.AddTransient<TransferView>();

        // Phase 4: Bulk Members
        services.AddTransient<IBulkMemberService, BulkMemberService>();
        services.AddTransient<BulkMembersViewModel>();
        services.AddTransient<BulkMembersView>();

        // Phase 4: Bulk Sites
        services.AddTransient<IBulkSiteService, BulkSiteService>();
        services.AddTransient<BulkSitesViewModel>();
        services.AddTransient<BulkSitesView>();

        // Phase 4: Templates
        services.AddTransient<ITemplateService, TemplateService>();
        services.AddTransient<TemplatesViewModel>();
        services.AddTransient<TemplatesView>();

        // Phase 4: Folder Structure
        services.AddTransient<IFolderStructureService, FolderStructureService>();
        services.AddTransient<FolderStructureViewModel>();
        services.AddTransient<FolderStructureView>();

        // Phase 17: Group Expansion
        services.AddTransient<ISharePointGroupResolver, SharePointGroupResolver>();

        // Phase 18: Auto-Take Ownership
        services.AddTransient<IOwnershipElevationService, OwnershipElevationService>();

        // Phase 19: App Registration & Removal
        services.AddSingleton<IAppRegistrationService, AppRegistrationService>();

        // Phase 7: User Access Audit
        services.AddTransient<IUserAccessAuditService, UserAccessAuditService>();
        services.AddTransient<IGraphUserSearchService, GraphUserSearchService>();
        services.AddTransient<UserAccessCsvExportService>();
        services.AddTransient<UserAccessHtmlExportService>();
        services.AddTransient<UserAccessAuditViewModel>();
        services.AddTransient<UserAccessAuditView>();

        services.AddSingleton<MainWindow>();
    }
}
