using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using Nexus.Contracts.Apps;
using NexusShell.Models;
using NexusShell.Services;
using NexusShell.Views;
using NexusShell.ViewModels;

namespace NexusShell;

public partial class MainWindow : Window, INexusFileOpenRouter
{
    private readonly LoginView _loginView = new();
    private readonly NexusDesktopView _desktopView = new();
    private readonly List<MonitorDesktopWindow> _secondaryMonitors = [];
    private bool _isLauncherOpen;
    private bool _isNotificationCenterOpen;
    private NexusFilesWindow? _filesWindow;
    private NexusBrowserWindow? _browserWindow;
    private NexusCalculatorWindow? _calculatorWindow;
    private NexusPhotosWindow? _photosWindow;
    private NexusMediaWindow? _mediaWindow;
    private NexusDeviceManagerWindow? _deviceManagerWindow;
    private NexusStoreWindow? _storeWindow;
    private NexusAppHubWindow? _appHubWindow;

    public MainWindow(bool overlayMode)
    {
        InitializeComponent();

        if (overlayMode)
        {
            WindowState = WindowState.Maximized;
            WindowStyle = WindowStyle.SingleBorderWindow;
        }
        else
        {
            WindowState = WindowState.Maximized;
            WindowStyle = WindowStyle.None;
            ResizeMode = ResizeMode.NoResize;
        }

        _loginView.DataContext = App.Services.LoginViewModel;
        _desktopView.DataContext = App.Services.DesktopViewModel;
        LauncherPanel.DataContext = App.Services.LauncherViewModel;
        NotificationPanel.DataContext = App.Services.DesktopViewModel;

        App.Services.LoginViewModel.LoginSucceeded += (_, _) => ShowDesktop();
        App.Services.DesktopViewModel.OpenLauncherRequested += (_, _) => OpenLauncher();
        App.Services.DesktopViewModel.OpenAppHubRequested += (_, _) => OpenAppHub();
        App.Services.DesktopViewModel.OpenNotificationCenterRequested += (_, _) => ToggleNotificationCenter();
        App.Services.DesktopViewModel.OpenSettingsRequested += (_, _) => OpenSettings();
        App.Services.DesktopViewModel.OpenFilesRequested += (_, path) => OpenFiles(path);
        App.Services.DesktopViewModel.OpenBrowserRequested += (_, url) => OpenBrowser(url);
        App.Services.DesktopViewModel.OpenUpdateInfoRequested += (_, _) => OpenUpdateInfo();
        App.Services.DesktopViewModel.OpenConsoleRequested += (_, _) => OpenNexusConsole();
        App.Services.DesktopViewModel.OpenCalculatorRequested += (_, _) => OpenCalculator();
        App.Services.DesktopViewModel.OpenStoreRequested += (_, _) => OpenStore();
        App.Services.DesktopViewModel.OpenDiagnosticsRequested += (_, _) => OpenDiagnostics();
        App.Services.SettingsViewModel.OpenUpdateInfoRequested += (_, _) => OpenUpdateInfo();
        App.Services.SettingsViewModel.OpenNexusConsoleRequested += (_, _) => OpenNexusConsole();
        App.Services.LauncherViewModel.CloseRequested += (_, _) => CloseLauncher();
        App.Services.LauncherViewModel.OpenAppHubRequested += (_, _) => OpenAppHub();
        App.Services.LauncherViewModel.OpenSettingsRequested += (_, _) => OpenSettings();
        App.Services.LauncherViewModel.OpenFilesRequested += (_, path) => OpenFiles(path);
        App.Services.LauncherViewModel.OpenBrowserRequested += (_, url) => OpenBrowser(url);
        App.Services.LauncherViewModel.OpenCalculatorRequested += (_, _) => OpenCalculator();
        App.Services.LauncherViewModel.OpenPhotosRequested += (_, hint) => OpenPhotos(hint);
        App.Services.LauncherViewModel.OpenMediaRequested += (_, hint) => OpenMedia(hint);
        App.Services.LauncherViewModel.OpenStoreRequested += (_, _) => OpenStore();
        App.Services.LauncherViewModel.OpenConsoleRequested += (_, _) => OpenNexusConsole();
        App.Services.LauncherViewModel.OpenUpdateInfoRequested += (_, _) => OpenUpdateInfo();
        App.Services.LauncherViewModel.OpenDiagnosticsRequested += (_, _) => OpenDiagnostics();
        App.Services.LauncherViewModel.OpenDeviceManagerRequested += (_, section) => OpenDeviceManager(section);
        App.Services.LauncherViewModel.OpenPlaceholderRequested += (_, app) => OpenPlaceholderApp(app);
        App.Services.LauncherViewModel.LogoutRequested += (_, _) => Logout();
        App.Services.LauncherViewModel.LockRequested += (_, _) => LockWorkstation();
        App.Services.LauncherViewModel.RestartRequested += (_, _) => RequestSystemRestart();
        App.Services.LauncherViewModel.ShutdownRequested += (_, _) => RequestSystemShutdown();
        App.Services.LauncherViewModel.LaunchSucceeded += (_, _) => App.Services.DesktopViewModel.Refresh();
        App.Services.LauncherViewModel.LaunchBlocked += (_, message) =>
        {
            App.Services.DiagnosticsService.LogWorkspace("launcher_launch_blocked", message);
            MessageBox.Show(message, "Ninja Nexus", MessageBoxButton.OK, MessageBoxImage.Information);
        };
        LauncherPanel.DismissRequested += (_, _) => CloseLauncher();
        NotificationPanel.DismissRequested += (_, _) => CloseNotificationCenter();

        Loaded += MainWindow_OnLoaded;
        Closed += (_, _) => CloseSecondaryMonitors();
    }

    public void ApplyShellSettings()
    {
        CloseSecondaryMonitors();

        var settings = App.Services.UserSettingsService.Current;
        var shell = App.Services.ShellEnvironmentService;
        shell.ApplyPrimaryWindow(this, settings, App.Services.PlatformLockService);

        if (IsLoaded)
        {
            _secondaryMonitors.AddRange(
                shell.SyncSecondaryMonitors(this, settings, App.Services.DesktopViewModel));
        }
    }

    public void OpenWindowsUnlockDialog()
    {
        var profile = App.Services.ProfileService.CurrentProfile;
        var actor = profile?.Email ?? profile?.DisplayName ?? "admin";
        var vm = new NexusWindowsUnlockViewModel(App.Services.PlatformLockService, actor);
        var window = new NexusWindowsUnlockWindow
        {
            Owner = this,
            DataContext = vm,
        };

        void OnSuccess(object? _, EventArgs __)
        {
            vm.UnlockSucceeded -= OnSuccess;
            vm.CancelRequested -= OnCancel;
            window.DialogResult = true;
            window.Close();
            ApplyShellSettings();
        }

        void OnCancel(object? _, EventArgs __)
        {
            vm.UnlockSucceeded -= OnSuccess;
            vm.CancelRequested -= OnCancel;
            window.DialogResult = false;
            window.Close();
        }

        vm.UnlockSucceeded += OnSuccess;
        vm.CancelRequested += OnCancel;
        window.ShowDialog();
    }

    private void CloseSecondaryMonitors()
    {
        foreach (var monitor in _secondaryMonitors)
        {
            monitor.Close();
        }

        _secondaryMonitors.Clear();
    }

    private async void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        ApplyShellSettings();

        if (!await EnsureDeviceEnrolledAsync())
        {
            Application.Current.Shutdown();
            return;
        }

        if (await App.Services.AuthService.TryRestoreSessionAsync())
        {
            ShowDesktop();
        }
        else
        {
            ShowLogin();
        }
    }

    private static async Task<bool> EnsureDeviceEnrolledAsync()
    {
        if (App.Services.IdentityService.IsEnrolled)
        {
            return true;
        }

        var setupWindow = new NexusSetupFlowWindow
        {
            DataContext = App.Services.SetupFlowViewModel,
            Owner = Application.Current.MainWindow,
        };

        var completed = false;
        void OnCompleted(object? _, EventArgs __)
        {
            completed = true;
            setupWindow.DialogResult = true;
            setupWindow.Close();
        }

        void OnCancel(object? _, EventArgs __)
        {
            setupWindow.DialogResult = false;
            setupWindow.Close();
        }

        App.Services.SetupFlowViewModel.SetupCompleted += OnCompleted;
        App.Services.SetupFlowViewModel.CancelRequested += OnCancel;

        setupWindow.ShowDialog();

        App.Services.SetupFlowViewModel.SetupCompleted -= OnCompleted;
        App.Services.SetupFlowViewModel.CancelRequested -= OnCancel;

        if (!completed)
        {
            return false;
        }

        App.Services.IdentityService.LoadAll();
        await App.Services.NexusAgentService.StopAsync();
        await App.Services.NexusAgentService.StartAsync();
        if (Application.Current.MainWindow is MainWindow mainWindow)
        {
            mainWindow.ApplyShellSettings();
        }
        return App.Services.IdentityService.IsEnrolled;
    }

    private void ShowLogin()
    {
        CloseAllOverlays();
        MainContent.Content = _loginView;
    }

    private void ShowDesktop()
    {
        App.Services.PolicyService.Refresh();
        App.Services.DesktopViewModel.Refresh();
        App.Services.LauncherViewModel.RefreshLists();
        App.Services.SettingsViewModel.Refresh();
        MainContent.Content = _desktopView;
        App.Services.DiagnosticsService.LogLifecycle("identity_ready", "Bruger session klar");
        App.Services.DesktopViewModel.NotifyWorkspaceLoaded();
        _ = RunUpdateCheckAsync();
    }

    private async Task RunUpdateCheckAsync()
    {
        if (!App.Services.CheckOnStartup)
        {
            return;
        }

        try
        {
            await App.Services.RefreshUpdateStatusAsync();

            if (App.Services.UpdateService.LastResult?.IsUpdateAvailable == true)
            {
                var apply = await App.Services.TryAutoUpdateAsync();
                if (apply.RestartScheduled)
                {
                    return;
                }
            }
        }
        catch
        {
            App.Services.DesktopViewModel.NotifyUpdateStatus();
            App.Services.SettingsViewModel.NotifyUpdateStatusChanged();
        }
    }

    private void Logout()
    {
        CloseLauncher();
        App.Services.AuthService.Logout();
        App.Services.LoginViewModel.Email = "user@nexus.local";
        App.Services.LoginViewModel.Password = string.Empty;
        App.Services.LoginViewModel.ErrorMessage = null;
        _loginView.ClearPassword();
        ShowLogin();
    }

    private static void LockWorkstation()
    {
        _ = LockWorkStation();
    }

    private void RequestSystemRestart()
    {
        CloseLauncher();
        Process.Start(new ProcessStartInfo
        {
            FileName = "shutdown",
            Arguments = "/r /t 0",
            CreateNoWindow = true,
            UseShellExecute = false,
        });
    }

    private void RequestSystemShutdown()
    {
        CloseLauncher();
        Process.Start(new ProcessStartInfo
        {
            FileName = "shutdown",
            Arguments = "/s /t 0",
            CreateNoWindow = true,
            UseShellExecute = false,
        });
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool LockWorkStation();

    private void OpenLauncher()
    {
        CloseNotificationCenter();
        App.Services.DesktopViewModel.ActivateDock("App Hub");
        App.Services.LauncherViewModel.ShowAllApps = true;
        App.Services.LauncherViewModel.RefreshLists();
        LauncherPanel.Visibility = Visibility.Visible;
        LauncherPanel.PlayOpenAnimation();
        _isLauncherOpen = true;
    }

    private void OpenAppHub()
    {
        CloseAllOverlays();
        App.Services.DesktopViewModel.ActivateDock("App Hub");
        App.Services.LauncherViewModel.SearchText = string.Empty;
        App.Services.LauncherViewModel.ShowAllApps = true;
        App.Services.LauncherViewModel.RefreshLists();

        if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-app-hub", out var existing) &&
            existing is { IsVisible: true })
        {
            App.Services.WorkspaceWindowManager.Activate("nexus-app-hub");
            return;
        }

        _appHubWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
            new NexusAppHubWindow
            {
                DataContext = App.Services.LauncherViewModel,
            },
            "nexus-app-hub",
            "Nexus App Hub",
            "apps");
        App.Services.LauncherViewModel.CloseRequested += OnAppHubClose;
        _appHubWindow.Closed += (_, _) =>
        {
            App.Services.LauncherViewModel.CloseRequested -= OnAppHubClose;
            _appHubWindow = null;
        };
        _appHubWindow.Show();
    }

    private void CloseLauncher()
    {
        if (!_isLauncherOpen)
        {
            return;
        }

        _isLauncherOpen = false;
        LauncherPanel.PlayCloseAnimation(() =>
        {
            LauncherPanel.Visibility = Visibility.Collapsed;
        });
    }

    private void OnAppHubClose(object? sender, EventArgs e) => _appHubWindow?.Close();

    private void OpenPlaceholderApp(AppEntry app)
    {
        CloseAllOverlays();
        var workspaceId = string.IsNullOrWhiteSpace(app.Id)
            ? $"nexus-placeholder-{Guid.NewGuid():N}"
            : app.Id;

        if (App.Services.WorkspaceWindowManager.TryGetWindow(workspaceId, out var existing) &&
            existing is { IsVisible: true })
        {
            App.Services.WorkspaceWindowManager.Activate(workspaceId);
            return;
        }

        var vm = new NexusAppPlaceholderViewModel(app);
        var window = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
            new NexusAppPlaceholderWindow
            {
                DataContext = vm,
            },
            workspaceId,
            vm.Name,
            "placeholder");

        vm.CloseRequested += (_, _) => window.Close();
        vm.OpenDiagnosticsRequested += (_, _) => OpenDiagnostics();
        vm.OpenAppHubRequested += (_, _) => OpenAppHub();
        window.Show();
    }

    private void ToggleNotificationCenter()
    {
        if (_isNotificationCenterOpen)
        {
            CloseNotificationCenter();
        }
        else
        {
            OpenNotificationCenter();
        }
    }

    private void OpenNotificationCenter()
    {
        CloseLauncher();
        App.Services.DesktopViewModel.RefreshStatus();
        NotificationPanel.Visibility = Visibility.Visible;
        NotificationPanel.PlayOpenAnimation();
        _isNotificationCenterOpen = true;
    }

    private void CloseNotificationCenter()
    {
        if (!_isNotificationCenterOpen)
        {
            return;
        }

        _isNotificationCenterOpen = false;
        NotificationPanel.PlayCloseAnimation(() =>
        {
            NotificationPanel.Visibility = Visibility.Collapsed;
        });
    }

    private void CloseAllOverlays()
    {
        CloseLauncher();
        CloseNotificationCenter();
    }

    private void OpenNexusConsole()
    {
        if (!App.Services.LockdownService.DeveloperConsoleEnabled)
        {
            return;
        }

        if (!App.Services.PolicyService.CanAccessConsole())
        {
            return;
        }

        var role = App.Services.ProfileService.CurrentProfile?.Role;
        if (!App.Services.NexusConsoleService.CanAccessRole(role))
        {
            return;
        }

        App.Services.NexusConsoleViewModel.Reset();
        if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-console", out var existing) &&
            existing is { IsVisible: true })
        {
            App.Services.WorkspaceWindowManager.Activate("nexus-console");
            return;
        }

        var window = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
            new NexusConsoleWindow
            {
                DataContext = App.Services.NexusConsoleViewModel,
            },
            "nexus-console",
            "Nexus Console",
            "terminal");
        window.WireEvents(App.Services.NexusConsoleViewModel);
        window.Show();
    }

    public void OpenBrowserFromConsole(string? url) => OpenBrowser(url);

    public void OpenFilesFromConsole(string? path) => OpenFiles(path);

    public void RestartShellFromConsole()
    {
        var exe = Environment.ProcessPath;
        if (!string.IsNullOrWhiteSpace(exe))
        {
            Process.Start(new ProcessStartInfo
            {
                FileName = exe,
                UseShellExecute = true,
            });
        }

        Application.Current.Shutdown();
    }

    private void OpenDeveloperConsole()
    {
        if (!App.Services.LockdownService.DeveloperConsoleEnabled)
        {
            return;
        }

        App.Services.DeveloperConsoleViewModel.Reset();
        var window = new DeveloperConsoleWindow
        {
            Owner = this,
            DataContext = App.Services.DeveloperConsoleViewModel,
        };
        App.Services.DeveloperConsoleViewModel.ExitRequested += OnDeveloperConsoleExit;
        window.Closed += (_, _) =>
            App.Services.DeveloperConsoleViewModel.ExitRequested -= OnDeveloperConsoleExit;
        window.ShowDialog();
    }

    private void OnDeveloperConsoleExit(object? sender, EventArgs e)
    {
        foreach (Window window in Application.Current.Windows)
        {
            if (window is DeveloperConsoleWindow devWindow)
            {
                devWindow.Close();
            }
        }
    }

    private void OpenSettings()
    {
        if (!App.Services.PolicyService.CanOpenSettings())
        {
            return;
        }

        CloseAllOverlays();
        App.Services.DesktopViewModel.ActivateDock("Settings");
        try
        {
            App.Services.SettingsViewModel.Refresh();
            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-settings", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-settings");
                return;
            }

            var window = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusSettingsWindow
                {
                    DataContext = App.Services.SettingsViewModel,
                },
                "nexus-settings",
                "Nexus Settings",
                "settings");
            App.Services.SettingsViewModel.CloseRequested += OnSettingsClose;
            window.Closed += (_, _) =>
            {
                App.Services.SettingsViewModel.CloseRequested -= OnSettingsClose;
            };
            window.Show();
        }
        catch (Exception ex)
        {
            App.Services.ShellEnvironmentService.Restore();
            MessageBox.Show(
                $"Indstillinger kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OpenDiagnostics()
    {
        App.Services.SettingsViewModel.OpenSection(NexusSettingsSection.DeveloperDiagnostics);
        OpenSettings();
    }

    private void OpenBrowser(string? initialUrl)
    {
        if (!App.Services.PolicyService.CanOpenBrowser())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Browser");
        App.Services.AppLaunchTracker.TrackLauncherAction("open_browser", initialUrl);
        try
        {
            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-browser", out var existing) &&
                existing is { IsVisible: true })
            {
                if (!string.IsNullOrWhiteSpace(initialUrl))
                {
                    App.Services.BrowserViewModel.OpenUrl(initialUrl);
                }

                App.Services.WorkspaceWindowManager.Activate("nexus-browser");
                return;
            }

            _browserWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusBrowserWindow
                {
                    DataContext = App.Services.BrowserViewModel,
                },
                "nexus-browser",
                "Nexus Browser",
                "browser");
            App.Services.BrowserViewModel.CloseRequested += OnBrowserClose;
            _browserWindow.Closed += (_, _) =>
            {
                App.Services.BrowserViewModel.CloseRequested -= OnBrowserClose;
                _browserWindow = null;
            };
            _browserWindow.Show();

            if (!string.IsNullOrWhiteSpace(initialUrl))
            {
                App.Services.BrowserViewModel.OpenUrl(initialUrl);
            }
        }
        catch (Exception ex)
        {
            App.Services.DiagnosticsService.LogError("browser_open_failed", ex.Message, ex);
            MessageBox.Show(
                $"Nexus Browser kunne ikke åbnes.\n\n{ex.Message}\n\nDiagnostik: Kopier fejlinfo via Indstillinger → Developer → Diagnostik.",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OpenFiles(string? initialPath)
    {
        if (!App.Services.PolicyService.CanOpenFiles())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Files");
        App.Services.AppLaunchTracker.TrackLauncherAction("open_files", initialPath);
        try
        {
            App.Services.FilesViewModel.OpenLocation(initialPath);

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-files", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-files");
                return;
            }

            _filesWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusFilesWindow
                {
                    DataContext = App.Services.FilesViewModel,
                },
                "nexus-files",
                "Nexus Files",
                "files");
            App.Services.FilesViewModel.CloseRequested += OnFilesClose;
            _filesWindow.Closed += (_, _) =>
            {
                App.Services.FilesViewModel.CloseRequested -= OnFilesClose;
                _filesWindow = null;
            };
            _filesWindow.Show();
        }
        catch (Exception ex)
        {
            App.Services.DiagnosticsService.LogError("files_open_failed", ex.Message, ex);
            MessageBox.Show(
                $"Nexus Files kunne ikke åbnes.\n\n{ex.Message}\n\nDiagnostik: Kopier fejlinfo via Indstillinger → Developer → Diagnostik.",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OpenCalculator()
    {
        if (!App.Services.PolicyService.CanOpenCalculator())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Calculator");
        try
        {
            App.Services.CalculatorViewModel.Reset();

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-calculator", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-calculator");
                return;
            }

            _calculatorWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusCalculatorWindow
                {
                    DataContext = App.Services.CalculatorViewModel,
                },
                "nexus-calculator",
                "Nexus Calculator",
                "calculator");
            App.Services.CalculatorViewModel.CloseRequested += OnCalculatorClose;
            _calculatorWindow.Closed += (_, _) =>
            {
                App.Services.CalculatorViewModel.CloseRequested -= OnCalculatorClose;
                _calculatorWindow = null;
            };
            _calculatorWindow.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"Nexus Calculator kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OpenPhotos(string? sectionHint)
    {
        if (!App.Services.PolicyService.CanOpenPhotos())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Photos");
        try
        {
            App.Services.PhotosViewModel.OpenSection(sectionHint);

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-photos", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-photos");
                return;
            }

            _photosWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusPhotosWindow
                {
                    DataContext = App.Services.PhotosViewModel,
                },
                "nexus-photos",
                "Nexus Photos",
                "photos");
            App.Services.PhotosViewModel.CloseRequested += OnPhotosClose;
            _photosWindow.Closed += (_, _) =>
            {
                App.Services.PhotosViewModel.CloseRequested -= OnPhotosClose;
                _photosWindow = null;
            };
            _photosWindow.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"Nexus Photos kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OnPhotosClose(object? sender, EventArgs e) => _photosWindow?.Close();

    public void OpenMedia(string? sectionHint) => OpenMediaInternal(sectionHint);

    private void OpenMediaInternal(string? sectionHint)
    {
        if (!App.Services.PolicyService.CanOpenMedia())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Store");
        try
        {
            App.Services.MediaViewModel.OpenSection(sectionHint);

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-media", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-media");
                return;
            }

            _mediaWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusMediaWindow
                {
                    DataContext = App.Services.MediaViewModel,
                },
                "nexus-media",
                "Nexus Media",
                "media");
            App.Services.MediaViewModel.CloseRequested += OnMediaClose;
            _mediaWindow.Closed += (_, _) =>
            {
                App.Services.MediaViewModel.CloseRequested -= OnMediaClose;
                _mediaWindow = null;
            };
            _mediaWindow.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"Nexus Media kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OnMediaClose(object? sender, EventArgs e) => _mediaWindow?.Close();

    private void OpenDeviceManager(string? sectionHint)
    {
        if (!App.Services.PolicyService.CanOpenDeviceManager())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Media");
        try
        {
            App.Services.DeviceManagerViewModel.OpenSection(sectionHint);

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-devices", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-devices");
                return;
            }

            _deviceManagerWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusDeviceManagerWindow
                {
                    DataContext = App.Services.DeviceManagerViewModel,
                },
                "nexus-devices",
                "Nexus Devices",
                "devices");
            App.Services.DeviceManagerViewModel.CloseRequested += OnDeviceManagerClose;
            _deviceManagerWindow.Closed += (_, _) =>
            {
                App.Services.DeviceManagerViewModel.StopMonitoring();
                App.Services.DeviceManagerViewModel.CloseRequested -= OnDeviceManagerClose;
                _deviceManagerWindow = null;
            };
            App.Services.DeviceManagerViewModel.StartMonitoring();
            _deviceManagerWindow.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"Nexus Device Manager kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void OpenStore()
    {
        if (!App.Services.PolicyService.CanAccessStore())
        {
            return;
        }

        CloseLauncher();
        App.Services.DesktopViewModel.ActivateDock("Devices");
        try
        {
            App.Services.StoreViewModel.ReloadFromRepository();

            if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-store", out var existing) &&
                existing is { IsVisible: true })
            {
                App.Services.WorkspaceWindowManager.Activate("nexus-store");
                return;
            }

            _storeWindow = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
                new NexusStoreWindow
                {
                    DataContext = App.Services.StoreViewModel,
                },
                "nexus-store",
                "Ninja Store",
                "store");
            WireStoreEvents();
            App.Services.StoreViewModel.CloseRequested += OnStoreClose;
            _storeWindow.Closed += (_, _) =>
            {
                UnwireStoreEvents();
                App.Services.StoreViewModel.CloseRequested -= OnStoreClose;
                _storeWindow = null;
            };
            _storeWindow.Show();
        }
        catch (Exception ex)
        {
            MessageBox.Show(
                $"Ninja Store kunne ikke åbnes.\n\n{ex.Message}",
                "Ninja Nexus",
                MessageBoxButton.OK,
                MessageBoxImage.Warning);
        }
    }

    private void WireStoreEvents()
    {
        var vm = App.Services.StoreViewModel;
        vm.OpenFilesRequested += OnStoreOpenFiles;
        vm.OpenBrowserRequested += OnStoreOpenBrowser;
        vm.OpenCalculatorRequested += OnStoreOpenCalculator;
        vm.OpenSettingsRequested += OnStoreOpenSettings;
        vm.OpenConsoleRequested += OnStoreOpenConsole;
        vm.LaunchBlocked += OnStoreLaunchBlocked;
    }

    private void UnwireStoreEvents()
    {
        var vm = App.Services.StoreViewModel;
        vm.OpenFilesRequested -= OnStoreOpenFiles;
        vm.OpenBrowserRequested -= OnStoreOpenBrowser;
        vm.OpenCalculatorRequested -= OnStoreOpenCalculator;
        vm.OpenSettingsRequested -= OnStoreOpenSettings;
        vm.OpenConsoleRequested -= OnStoreOpenConsole;
        vm.LaunchBlocked -= OnStoreLaunchBlocked;
    }

    private void OnStoreOpenFiles(object? sender, string? path) => OpenFiles(path);

    private void OnStoreOpenBrowser(object? sender, string? url) => OpenBrowser(url);

    private void OnStoreOpenCalculator(object? sender, EventArgs e) => OpenCalculator();

    private void OnStoreOpenSettings(object? sender, string? section)
    {
        if (!string.IsNullOrWhiteSpace(section))
        {
            App.Services.SettingsViewModel.OpenSection(section);
        }

        OpenSettings();
    }

    private void OnStoreOpenConsole(object? sender, EventArgs e) => OpenNexusConsole();

    private void OnStoreLaunchBlocked(object? sender, string message)
    {
        MessageBox.Show(message, "Ninja Store", MessageBoxButton.OK, MessageBoxImage.Information);
    }

    private void OnStoreClose(object? sender, EventArgs e)
    {
        _storeWindow?.Close();
    }

    private void OpenUpdateInfo()
    {
        App.Services.UpdateInfoViewModel.LoadFromCache();
        if (App.Services.WorkspaceWindowManager.TryGetWindow("nexus-updates", out var existing) &&
            existing is { IsVisible: true })
        {
            App.Services.WorkspaceWindowManager.Activate("nexus-updates");
            return;
        }

        var window = App.Services.WorkspaceWindowManager.RegisterWorkspaceWindow(
            new UpdateInfoWindow
            {
                DataContext = App.Services.UpdateInfoViewModel,
            },
            "nexus-updates",
            "Nexus Updates",
            "updates");
        App.Services.UpdateInfoViewModel.CloseRequested += OnUpdateInfoClose;
        window.Closed += (_, _) =>
        {
            App.Services.UpdateInfoViewModel.CloseRequested -= OnUpdateInfoClose;
        };
        window.Show();
    }

    private void OnUpdateInfoClose(object? sender, EventArgs e)
    {
        foreach (Window window in Application.Current.Windows)
        {
            if (window is UpdateInfoWindow updateWindow)
            {
                updateWindow.Close();
            }
        }
    }

    private void OnSettingsClose(object? sender, EventArgs e)
    {
        foreach (Window window in Application.Current.Windows)
        {
            if (window is NexusSettingsWindow settingsWindow)
            {
                settingsWindow.Close();
            }
        }
    }

    private void OnFilesClose(object? sender, EventArgs e)
    {
        _filesWindow?.Close();
    }

    private void OnBrowserClose(object? sender, EventArgs e)
    {
        _browserWindow?.Close();
    }

    private void OnCalculatorClose(object? sender, EventArgs e)
    {
        _calculatorWindow?.Close();
    }

    private void OnDeviceManagerClose(object? sender, EventArgs e)
    {
        _deviceManagerWindow?.Close();
    }

    private void MainWindow_OnKeyDown(object sender, KeyEventArgs e)
    {
        if (IsDeveloperConsoleChord(e))
        {
            if (App.Services.PolicyService.CanAccessConsole())
            {
                OpenNexusConsole();
            }

            e.Handled = true;
            return;
        }

        if (IsWindowsUnlockChord(e))
        {
            OpenWindowsUnlockDialog();
            e.Handled = true;
            return;
        }

        if (e.Key == Key.Escape)
        {
            if (_isLauncherOpen)
            {
                CloseLauncher();
                e.Handled = true;
                return;
            }

            if (_isNotificationCenterOpen)
            {
                CloseNotificationCenter();
                e.Handled = true;
            }

            return;
        }

        var isLauncherShortcut =
            (e.Key == Key.K && Keyboard.Modifiers.HasFlag(ModifierKeys.Alt)) ||
            (e.Key == Key.Space && Keyboard.Modifiers.HasFlag(ModifierKeys.Control)) ||
            (e.Key == Key.LWin || e.Key == Key.RWin);

        if (isLauncherShortcut && MainContent.Content is NexusDesktopView)
        {
            if (_isLauncherOpen)
            {
                CloseLauncher();
            }
            else
            {
                OpenLauncher();
            }

            e.Handled = true;
        }
    }

    private static bool IsDeveloperConsoleChord(KeyEventArgs e)
    {
        if (e.Key != Key.N)
        {
            return false;
        }

        var mods = Keyboard.Modifiers;
        return mods.HasFlag(ModifierKeys.Control) &&
               mods.HasFlag(ModifierKeys.Shift) &&
               mods.HasFlag(ModifierKeys.Alt);
    }

    private static bool IsWindowsUnlockChord(KeyEventArgs e)
    {
        if (e.Key != Key.U)
        {
            return false;
        }

        var mods = Keyboard.Modifiers;
        return mods.HasFlag(ModifierKeys.Control) &&
               mods.HasFlag(ModifierKeys.Shift) &&
               mods.HasFlag(ModifierKeys.Alt);
    }

    public void OpenWithApp(NexusDefaultAppId appId, string filePath)
    {
        switch (appId)
        {
            case NexusDefaultAppId.Photos:
                OpenPhotos(null);
                App.Services.PhotosViewModel.OpenFilePath(filePath);
                break;
            case NexusDefaultAppId.Media:
                OpenMediaInternal(null);
                App.Services.MediaViewModel.OpenFilePath(filePath);
                break;
            case NexusDefaultAppId.FilesPreview:
                OpenFiles(Path.GetDirectoryName(filePath));
                App.Services.FilesViewModel.SelectFile(filePath);
                break;
            case NexusDefaultAppId.Browser:
                OpenBrowser(new Uri(filePath).AbsoluteUri);
                break;
        }
    }
}
