using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using ClaudeDo.Ui;
using ClaudeDo.Ui.Localization;
using ClaudeDo.Ui.Services;
using ClaudeDo.Ui.ViewModels;
using ClaudeDo.Ui.Views;
using Microsoft.Extensions.DependencyInjection;

namespace ClaudeDo.App;

public partial class App : Application
{
    private readonly IServiceProvider? _services;

    // Parameterless ctor is required by the XAML previewer / designer.
    public App() { }

    public App(IServiceProvider services) => _services = services;

    public override void Initialize()
    {
        AvaloniaXamlLoader.Load(this);
        if (_services?.GetService<AppSettings>() is { } settings)
            AccentPresetService.Apply(AccentPresets.Find(settings.AccentPreset));
    }

    public override void OnFrameworkInitializationCompleted()
    {
        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
        {
            var services = _services
                ?? throw new InvalidOperationException("App was constructed without a service provider.");

            FocusClearing.Install();

            // The main window is authoritative — closing it shuts the app down even if the
            // modeless Mission Control window is still open.
            desktop.ShutdownMode = ShutdownMode.OnMainWindowClose;

            var shell = services.GetRequiredService<IslandsShellViewModel>();

            // Last-resort backstop: an exception escaping a dispatcher job kills the process, and
            // ClaudeDo hosts third-party UI (the ConPTY terminal control) whose async void key and
            // render handlers have done exactly that — one bad keystroke took the whole app down,
            // losing every open session. Swallowing is the lesser evil here: the failing job is
            // already dead either way, and the user still gets told via the footer error strip.
            Dispatcher.UIThread.UnhandledException += (_, e) =>
            {
                e.Handled = true;
                shell.FlashFooterError(Loc.T("vm.shell.unexpectedError", e.Exception.Message));
            };

            desktop.MainWindow = new MainWindow
            {
                DataContext = shell,
            };

            // Kick off the SignalR retry loop — reconnects indefinitely if the worker
            // is not up yet, or goes down and comes back.
            _ = services.GetRequiredService<WorkerClient>().StartAsync();
        }

        base.OnFrameworkInitializationCompleted();
    }
}
