using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using NexusShell.Models;
using NexusShell.Services;

namespace NexusShell.ViewModels;

public sealed class NexusMediaViewModel : INotifyPropertyChanged
{
    private readonly NexusMediaLibraryService _library;
    private readonly NexusMediaPlayerService _player;
    private readonly NexusQueueService _queue;
    private readonly NexusPlaylistService _playlists;
    private readonly NexusMediaMetadataService _metadata;
    private readonly NexusMediaFavoritesService _favorites;
    private readonly NexusMediaRecentService _recent;
    private readonly NexusMiniPlayerState _miniPlayer;

    private NexusMediaSection _currentSection = NexusMediaSection.Home;
    private string _searchText = string.Empty;
    private string _statusMessage = string.Empty;
    private NexusMediaItem? _selectedItem;
    private NexusMediaMetadata _selectedMetadata;
    private NexusMediaPlaylist? _selectedPlaylist;
    private NexusMediaFolderSummary? _selectedFolder;
    private bool _isVideoPlayerVisible;
    private bool _isScanning;
    private double _seekFraction;
    private IReadOnlyList<NexusMediaItem> _allItems = [];

    public NexusMediaViewModel(
        NexusMediaLibraryService library,
        NexusMediaPlayerService player,
        NexusQueueService queue,
        NexusPlaylistService playlists,
        NexusMediaMetadataService metadata,
        NexusMediaFavoritesService favorites,
        NexusMediaRecentService recent)
    {
        _library = library;
        _player = player;
        _queue = queue;
        _playlists = playlists;
        _metadata = metadata;
        _favorites = favorites;
        _recent = recent;
        _selectedMetadata = _metadata.BuildMetadata(null);
        _miniPlayer = new NexusMiniPlayerState(this);

        NavItems =
        [
            new() { Section = NexusMediaSection.Home, Label = "Hjem", IconPath = NexusLucideIcons.Home },
            new() { Section = NexusMediaSection.Videos, Label = "Videoer", IconPath = NexusLucideIcons.Film },
            new() { Section = NexusMediaSection.Music, Label = "Musik", IconPath = NexusLucideIcons.Music },
            new() { Section = NexusMediaSection.Playlists, Label = "Afspilningslister", IconPath = NexusLucideIcons.ListMusic },
            new() { Section = NexusMediaSection.Favorites, Label = "Favoritter", IconPath = NexusLucideIcons.Star },
            new() { Section = NexusMediaSection.Recent, Label = "Seneste", IconPath = NexusLucideIcons.Clock },
            new() { Section = NexusMediaSection.Folders, Label = "Mapper", IconPath = NexusLucideIcons.FolderTree },
        ];

        VideoItems = new ObservableCollection<NexusMediaGridItem>();
        MusicItems = new ObservableCollection<NexusMediaListItem>();
        HomeSections = new ObservableCollection<NexusMediaHomeSection>();
        QueueItems = new ObservableCollection<NexusMediaQueueItem>();
        PlaylistSummaries = new ObservableCollection<NexusMediaPlaylistSummary>();
        FolderSummaries = new ObservableCollection<NexusMediaFolderSummary>();

        NavigateCommand = new RelayCommand(p => Navigate(p as NexusMediaSection? ?? NexusMediaSection.Home));
        RefreshCommand = new RelayCommand(_ => RefreshLibrary(force: true));
        PlayItemCommand = new RelayCommand(p => PlayItem(p));
        SelectItemCommand = new RelayCommand(p => SelectItem(p));
        ToggleFavoriteCommand = new RelayCommand(_ => ToggleFavorite());
        AddToQueueCommand = new RelayCommand(_ => AddSelectedToQueue());
        RemoveFromQueueCommand = new RelayCommand(p => RemoveFromQueue(p as NexusMediaQueueItem));
        MoveQueueUpCommand = new RelayCommand(p => MoveQueue(p as NexusMediaQueueItem, -1));
        MoveQueueDownCommand = new RelayCommand(p => MoveQueue(p as NexusMediaQueueItem, 1));
        PlayPauseCommand = new RelayCommand(_ => TogglePlayPause());
        StopCommand = new RelayCommand(_ => StopPlayback());
        PreviousCommand = new RelayCommand(_ => PlayPrevious());
        NextCommand = new RelayCommand(_ => PlayNext());
        SeekCommand = new RelayCommand(p => SeekToFraction(p));
        SetVolumeCommand = new RelayCommand(p => SetVolume(p));
        ToggleShuffleCommand = new RelayCommand(_ => ToggleShuffle());
        CycleRepeatCommand = new RelayCommand(_ => CycleRepeat());
        ToggleFullscreenCommand = new RelayCommand(_ => _player.RequestFullscreenToggle());
        CloseVideoPlayerCommand = new RelayCommand(_ => CloseVideoPlayer());
        CreatePlaylistCommand = new RelayCommand(_ => CreatePlaylist());
        PlayPlaylistCommand = new RelayCommand(p => PlayPlaylist(p as NexusMediaPlaylistSummary));
        OpenFolderCommand = new RelayCommand(p => OpenFolder(p as NexusMediaFolderSummary));
        CloseCommand = new RelayCommand(_ => CloseRequested?.Invoke(this, EventArgs.Empty));

        _player.StateChanged += (_, _) => SyncPlayerState();
        _player.MediaOpened += (_, _) => OnMediaOpened();
        _player.MediaEnded += (_, _) => OnMediaEnded();
        _player.PlaybackError += (_, msg) => StatusMessage = msg;
        _player.RequestFullscreen += (_, _) => FullscreenRequested?.Invoke(this, EventArgs.Empty);
        _queue.QueueChanged += (_, _) => RefreshQueue();
        _favorites.FavoritesChanged += (_, _) => RefreshLibrary(force: false);
        _playlists.PlaylistsChanged += (_, _) => RefreshPlaylists();
    }

    public event PropertyChangedEventHandler? PropertyChanged;
    public event EventHandler? CloseRequested;
    public event EventHandler? FullscreenRequested;

    public string Title => "Nexus Media";
    public string VersionLabel => "1.0";

    public ObservableCollection<NexusMediaNavItem> NavItems { get; }
    public ObservableCollection<NexusMediaGridItem> VideoItems { get; }
    public ObservableCollection<NexusMediaListItem> MusicItems { get; }
    public ObservableCollection<NexusMediaHomeSection> HomeSections { get; }
    public ObservableCollection<NexusMediaQueueItem> QueueItems { get; }
    public ObservableCollection<NexusMediaPlaylistSummary> PlaylistSummaries { get; }
    public ObservableCollection<NexusMediaFolderSummary> FolderSummaries { get; }

    public NexusMiniPlayerState MiniPlayer => _miniPlayer;

    public NexusMediaSection CurrentSection
    {
        get => _currentSection;
        private set
        {
            if (_currentSection == value)
            {
                return;
            }

            _currentSection = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(SectionTitle));
            OnPropertyChanged(nameof(IsHomeSection));
            OnPropertyChanged(nameof(IsVideosSection));
            OnPropertyChanged(nameof(IsMusicSection));
            OnPropertyChanged(nameof(IsPlaylistsSection));
            OnPropertyChanged(nameof(IsFoldersSection));
            OnPropertyChanged(nameof(IsFavoritesOrRecentSection));
            OnPropertyChanged(nameof(ShowVideoGrid));
            OnPropertyChanged(nameof(ShowMusicList));
            OnPropertyChanged(nameof(ShowHome));
            OnPropertyChanged(nameof(ShowFolderList));
        }
    }

    public string SectionTitle => CurrentSection switch
    {
        NexusMediaSection.Home => "Hjem",
        NexusMediaSection.Videos => "Videoer",
        NexusMediaSection.Music => "Musik",
        NexusMediaSection.Playlists => "Afspilningslister",
        NexusMediaSection.Favorites => "Favoritter",
        NexusMediaSection.Recent => "Seneste afspillet",
        NexusMediaSection.Folders => "Mapper",
        _ => "Bibliotek",
    };

    public bool IsHomeSection => CurrentSection == NexusMediaSection.Home;
    public bool IsVideosSection => CurrentSection == NexusMediaSection.Videos;
    public bool IsMusicSection => CurrentSection == NexusMediaSection.Music;
    public bool IsPlaylistsSection => CurrentSection == NexusMediaSection.Playlists;
    public bool IsFoldersSection => CurrentSection == NexusMediaSection.Folders;
    public bool IsFavoritesOrRecentSection =>
        CurrentSection is NexusMediaSection.Favorites or NexusMediaSection.Recent;
    public bool ShowHome => IsHomeSection;
    public bool ShowVideoGrid => IsVideosSection || IsFavoritesOrRecentSection;
    public bool ShowMusicList => IsMusicSection;
    public bool ShowFolderList => IsFoldersSection;

    public string SearchText
    {
        get => _searchText;
        set
        {
            _searchText = value;
            OnPropertyChanged();
            ApplySectionFilter();
        }
    }

    public string StatusMessage
    {
        get => _statusMessage;
        private set
        {
            _statusMessage = value;
            OnPropertyChanged();
            OnPropertyChanged(nameof(HasStatusMessage));
        }
    }

    public bool HasStatusMessage => !string.IsNullOrWhiteSpace(StatusMessage);

    public bool IsScanning
    {
        get => _isScanning;
        private set
        {
            _isScanning = value;
            OnPropertyChanged();
        }
    }

    public NexusMediaMetadata SelectedMetadata
    {
        get => _selectedMetadata;
        private set
        {
            _selectedMetadata = value;
            OnPropertyChanged();
        }
    }

    public bool IsVideoPlayerVisible
    {
        get => _isVideoPlayerVisible;
        private set
        {
            _isVideoPlayerVisible = value;
            OnPropertyChanged();
        }
    }

    public bool IsAudioBarVisible => _player.CurrentPath is not null &&
                                     _player.CurrentKind == NexusMediaKind.Audio &&
                                     !IsVideoPlayerVisible;

    public bool IsPlaying => _player.IsPlaying;
    public bool ShowPauseIcon => IsPlaying;
    public bool ShowPlayIcon => !IsPlaying;
    public double Volume => _player.Volume * 100;
    public double SeekFraction
    {
        get => _seekFraction;
        set
        {
            _seekFraction = Math.Clamp(value, 0, 1);
            OnPropertyChanged();
        }
    }

    public string NowPlayingTitle => _queue.CurrentItem?.Title ?? "Intet afspilles";
    public string NowPlayingSubtitle => _queue.CurrentItem?.Kind == NexusMediaKind.Audio
        ? $"{_queue.CurrentItem.Artist} · {_queue.CurrentItem.Album}"
        : _queue.CurrentItem?.ResolutionLabel ?? "Vælg medie";
    public string PositionLabel => NexusMediaFormatting.FormatPosition(_player.Position, _player.Duration);
    public string RepeatModeLabel => _player.RepeatMode switch
    {
        NexusRepeatMode.All => "Gentag alle",
        NexusRepeatMode.One => "Gentag én",
        _ => "Gentag fra",
    };
    public bool ShuffleEnabled => _player.ShuffleEnabled;
    public bool IsFavoriteSelected => _selectedItem?.IsFavorite == true;

    public ICommand NavigateCommand { get; }
    public ICommand RefreshCommand { get; }
    public ICommand PlayItemCommand { get; }
    public ICommand SelectItemCommand { get; }
    public ICommand ToggleFavoriteCommand { get; }
    public ICommand AddToQueueCommand { get; }
    public ICommand RemoveFromQueueCommand { get; }
    public ICommand MoveQueueUpCommand { get; }
    public ICommand MoveQueueDownCommand { get; }
    public ICommand PlayPauseCommand { get; }
    public ICommand StopCommand { get; }
    public ICommand PreviousCommand { get; }
    public ICommand NextCommand { get; }
    public ICommand SeekCommand { get; }
    public ICommand SetVolumeCommand { get; }
    public ICommand ToggleShuffleCommand { get; }
    public ICommand CycleRepeatCommand { get; }
    public ICommand ToggleFullscreenCommand { get; }
    public ICommand CloseVideoPlayerCommand { get; }
    public ICommand CreatePlaylistCommand { get; }
    public ICommand PlayPlaylistCommand { get; }
    public ICommand OpenFolderCommand { get; }
    public ICommand CloseCommand { get; }

    public void Initialize()
    {
        RefreshLibrary(force: true);
        RefreshPlaylists();
    }

    public void OpenSection(string? hint)
    {
        _selectedFolder = null;
        CurrentSection = hint?.ToLowerInvariant() switch
        {
            "videos" or "video" or "videoer" => NexusMediaSection.Videos,
            "music" or "musik" => NexusMediaSection.Music,
            "playlists" or "afspilningslister" => NexusMediaSection.Playlists,
            "favorites" or "favoritter" => NexusMediaSection.Favorites,
            "recent" or "seneste" => NexusMediaSection.Recent,
            "folders" or "mapper" => NexusMediaSection.Folders,
            _ => NexusMediaSection.Home,
        };
        ApplySectionFilter();
    }

    public void OpenFilePath(string filePath)
    {
        if (!_library.TryBuildItemFromPath(filePath, out var item) || item is null)
        {
            StatusMessage = _library.GetUnsupportedFormatMessage(filePath);
            return;
        }

        _queue.SetQueue([item], 0);
        StartPlayback(item);
    }

    public void AttachVideoSurface(System.Windows.Controls.MediaElement element) =>
        _player.AttachVideoElement(element);

    public void DetachVideoSurface() => _player.DetachVideoElement();

    private void Navigate(NexusMediaSection section)
    {
        CurrentSection = section;
        ApplySectionFilter();
    }

    private void RefreshLibrary(bool force)
    {
        IsScanning = true;
        try
        {
            _allItems = _library.ScanLibrary(force);
            _favorites.ApplyFavorites(_allItems);
            ApplySectionFilter();
            StatusMessage = $"{_allItems.Count} medier i biblioteket";
        }
        finally
        {
            IsScanning = false;
        }
    }

    private void ApplySectionFilter()
    {
        IEnumerable<NexusMediaItem> items = CurrentSection switch
        {
            NexusMediaSection.Home => _allItems,
            NexusMediaSection.Videos => _library.GetItemsForSection(NexusMediaSection.Videos, _allItems),
            NexusMediaSection.Music => _library.GetItemsForSection(NexusMediaSection.Music, _allItems),
            NexusMediaSection.Favorites => _library.GetItemsForSection(NexusMediaSection.Favorites, _allItems),
            NexusMediaSection.Recent => ResolveRecentItems(),
            NexusMediaSection.Folders => _selectedFolder is null
                ? _allItems
                : _library.GetItemsInFolder(_selectedFolder.FolderPath, _allItems),
            _ => _allItems,
        };

        if (!string.IsNullOrWhiteSpace(SearchText))
        {
            items = _library.SearchLocal(SearchText, items.ToList());
        }

        var list = items.ToList();
        if (CurrentSection == NexusMediaSection.Home)
        {
            BuildHome(list);
        }

        if (CurrentSection is NexusMediaSection.Videos or NexusMediaSection.Favorites or NexusMediaSection.Recent
            or NexusMediaSection.Folders)
        {
            RebuildVideoGrid(list.Where(i => i.Kind == NexusMediaKind.Video));
        }

        if (CurrentSection == NexusMediaSection.Music)
        {
            RebuildMusicList(list.Where(i => i.Kind == NexusMediaKind.Audio));
        }

        if (CurrentSection == NexusMediaSection.Folders && _selectedFolder is null)
        {
            FolderSummaries.Clear();
            foreach (var folder in _library.GetFolderSummaries(_allItems))
            {
                FolderSummaries.Add(folder);
            }
        }
    }

    private IReadOnlyList<NexusMediaItem> ResolveRecentItems()
    {
        var paths = _recent.GetRecentPaths();
        return paths
            .Select(path => _library.FindByPath(path, _allItems))
            .Where(static i => i is not null)
            .Cast<NexusMediaItem>()
            .ToList();
    }

    private void BuildHome(IReadOnlyList<NexusMediaItem> all)
    {
        HomeSections.Clear();

        var recentPlayed = ResolveRecentItems().Take(8).Select(i => new NexusMediaGridItem(i)).ToList();
        if (recentPlayed.Count > 0)
        {
            HomeSections.Add(new NexusMediaHomeSection
            {
                Title = "Seneste afspillet",
                IconPath = NexusLucideIcons.Clock,
                Items = recentPlayed,
            });
        }

        var favorites = all.Where(static i => i.IsFavorite).Take(8).Select(i => new NexusMediaGridItem(i)).ToList();
        if (favorites.Count > 0)
        {
            HomeSections.Add(new NexusMediaHomeSection
            {
                Title = "Favoritter",
                IconPath = NexusLucideIcons.Star,
                Items = favorites,
            });
        }

        var newest = _library.GetNewItems(8, all).Select(i => new NexusMediaGridItem(i)).ToList();
        if (newest.Count > 0)
        {
            HomeSections.Add(new NexusMediaHomeSection
            {
                Title = "Nye medier",
                IconPath = NexusLucideIcons.Film,
                Items = newest,
            });
        }
    }

    private void RebuildVideoGrid(IEnumerable<NexusMediaItem> videos)
    {
        VideoItems.Clear();
        foreach (var item in videos)
        {
            VideoItems.Add(new NexusMediaGridItem(item));
        }
    }

    private void RebuildMusicList(IEnumerable<NexusMediaItem> tracks)
    {
        MusicItems.Clear();
        foreach (var item in tracks)
        {
            MusicItems.Add(new NexusMediaListItem(item));
        }
    }

    private void RefreshPlaylists()
    {
        PlaylistSummaries.Clear();
        foreach (var playlist in _playlists.GetPlaylists())
        {
            PlaylistSummaries.Add(new NexusMediaPlaylistSummary { Playlist = playlist });
        }
    }

    private void RefreshQueue()
    {
        QueueItems.Clear();
        foreach (var item in _queue.GetQueueItems())
        {
            QueueItems.Add(item);
        }

        OnPropertyChanged(nameof(NowPlayingTitle));
        OnPropertyChanged(nameof(NowPlayingSubtitle));
        _miniPlayer.NotifyChanged();
    }

    private void SelectItem(object? parameter)
    {
        _selectedItem = parameter switch
        {
            NexusMediaGridItem grid => grid.Item,
            NexusMediaListItem list => list.Item,
            NexusMediaItem direct => direct,
            _ => _selectedItem,
        };

        SelectedMetadata = _metadata.BuildMetadata(_selectedItem);
        OnPropertyChanged(nameof(IsFavoriteSelected));
    }

    private void PlayItem(object? parameter)
    {
        var item = parameter switch
        {
            NexusMediaGridItem grid => grid.Item,
            NexusMediaListItem list => list.Item,
            NexusMediaItem direct => direct,
            _ => _selectedItem,
        };

        if (item is null)
        {
            return;
        }

        if (!_library.IsSupportedExtension(item.FullPath))
        {
            StatusMessage = _library.GetUnsupportedFormatMessage(item.FullPath);
            return;
        }

        SelectItem(item);
        var queueSource = item.Kind == NexusMediaKind.Video
            ? _library.GetItemsForSection(NexusMediaSection.Videos, _allItems)
            : _library.GetItemsForSection(NexusMediaSection.Music, _allItems);
        var startIndex = Math.Max(0, queueSource.ToList().FindIndex(i =>
            string.Equals(i.FullPath, item.FullPath, StringComparison.OrdinalIgnoreCase)));
        _queue.SetQueue(queueSource, startIndex);
        StartPlayback(item);
    }

    private void StartPlayback(NexusMediaItem item)
    {
        _player.Open(item.FullPath, item.Kind);
        IsVideoPlayerVisible = item.Kind == NexusMediaKind.Video;
        _recent.RecordPlayback(item.FullPath);
        OnPropertyChanged(nameof(IsAudioBarVisible));
        SyncPlayerState();
    }

    private void ToggleFavorite()
    {
        if (_selectedItem is null)
        {
            return;
        }

        _favorites.ToggleFavorite(_selectedItem);
        OnPropertyChanged(nameof(IsFavoriteSelected));
        if (CurrentSection == NexusMediaSection.Favorites)
        {
            ApplySectionFilter();
        }
    }

    private void AddSelectedToQueue()
    {
        if (_selectedItem is null)
        {
            return;
        }

        _queue.Add(_selectedItem);
    }

    private void RemoveFromQueue(NexusMediaQueueItem? item)
    {
        if (item is null)
        {
            return;
        }

        _queue.RemoveAt(item.Index);
    }

    private void MoveQueue(NexusMediaQueueItem? item, int delta)
    {
        if (item is null)
        {
            return;
        }

        var target = item.Index + delta;
        if (target < 0 || target >= _queue.Count)
        {
            return;
        }

        _queue.Move(item.Index, target);
    }

    private void TogglePlayPause()
    {
        if (string.IsNullOrWhiteSpace(_player.CurrentPath))
        {
            if (_selectedItem is not null)
            {
                PlayItem(_selectedItem);
            }

            return;
        }

        if (_player.IsPlaying)
        {
            _player.Pause();
        }
        else
        {
            _player.Play();
        }

        SyncPlayerState();
    }

    private void StopPlayback()
    {
        _player.Stop();
        IsVideoPlayerVisible = false;
        OnPropertyChanged(nameof(IsAudioBarVisible));
        SyncPlayerState();
    }

    private void PlayPrevious()
    {
        var item = _queue.MovePrevious();
        if (item is not null)
        {
            StartPlayback(item);
        }
    }

    private void PlayNext()
    {
        var item = _queue.MoveNext(_player.ShuffleEnabled);
        if (item is not null)
        {
            StartPlayback(item);
        }
    }

    private void SeekToFraction(object? parameter)
    {
        var fraction = parameter switch
        {
            double d => d,
            string s when double.TryParse(s, out var parsed) => parsed,
            _ => SeekFraction,
        };
        _player.SeekFraction(fraction);
        SyncPlayerState();
    }

    private void SetVolume(object? parameter)
    {
        if (parameter is not string s || !double.TryParse(s, out var value))
        {
            return;
        }

        _player.SetVolume(value / 100.0);
        SyncPlayerState();
    }

    private void ToggleShuffle()
    {
        _player.ToggleShuffle();
        SyncPlayerState();
    }

    private void CycleRepeat()
    {
        _player.CycleRepeatMode();
        SyncPlayerState();
    }

    private void CloseVideoPlayer()
    {
        _player.Pause();
        IsVideoPlayerVisible = false;
        OnPropertyChanged(nameof(IsAudioBarVisible));
    }

    private void CreatePlaylist()
    {
        var playlist = _playlists.CreatePlaylist($"Afspilningsliste {PlaylistSummaries.Count + 1}");
        if (_selectedItem is not null)
        {
            _playlists.AddToPlaylist(playlist.Id, _selectedItem.FullPath);
        }

        RefreshPlaylists();
        StatusMessage = $"Oprettet: {playlist.Name}";
    }

    private void PlayPlaylist(NexusMediaPlaylistSummary? summary)
    {
        if (summary is null)
        {
            return;
        }

        var items = _playlists.ResolvePlaylistItems(summary.Playlist, _allItems);
        if (items.Count == 0)
        {
            StatusMessage = "Afspilningslisten er tom.";
            return;
        }

        _queue.SetQueue(items, 0);
        StartPlayback(items[0]);
    }

    private void OpenFolder(NexusMediaFolderSummary? folder)
    {
        if (folder is null)
        {
            return;
        }

        _selectedFolder = folder;
        ApplySectionFilter();
    }

    private void OnMediaOpened()
    {
        var current = _queue.CurrentItem;
        if (current is null)
        {
            return;
        }

        var (w, h) = _player.GetVideoDimensions();
        SelectedMetadata = _metadata.MergeRuntime(current, _player.Duration, w, h);
        SyncPlayerState();
    }

    private void OnMediaEnded()
    {
        if (_player.RepeatMode == NexusRepeatMode.One && _queue.CurrentItem is not null)
        {
            StartPlayback(_queue.CurrentItem);
            return;
        }

        if (_player.RepeatMode == NexusRepeatMode.All || _queue.Count > 1)
        {
            PlayNext();
            return;
        }

        _player.Pause();
        SyncPlayerState();
    }

    private void SyncPlayerState()
    {
        if (_player.Duration > TimeSpan.Zero)
        {
            SeekFraction = _player.Position.TotalSeconds / _player.Duration.TotalSeconds;
        }

        OnPropertyChanged(nameof(IsPlaying));
        OnPropertyChanged(nameof(ShowPauseIcon));
        OnPropertyChanged(nameof(ShowPlayIcon));
        OnPropertyChanged(nameof(Volume));
        OnPropertyChanged(nameof(PositionLabel));
        OnPropertyChanged(nameof(RepeatModeLabel));
        OnPropertyChanged(nameof(ShuffleEnabled));
        OnPropertyChanged(nameof(IsAudioBarVisible));
        OnPropertyChanged(nameof(NowPlayingTitle));
        OnPropertyChanged(nameof(NowPlayingSubtitle));
        _miniPlayer.NotifyChanged();
    }

    private void OnPropertyChanged([CallerMemberName] string? name = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

/// <summary>Hooks for a future dock mini player — not wired in POC 1.0.</summary>
public sealed class NexusMiniPlayerState
{
    private readonly NexusMediaViewModel _owner;

    public NexusMiniPlayerState(NexusMediaViewModel owner) => _owner = owner;

    public string Title => _owner.NowPlayingTitle;
    public string Subtitle => _owner.NowPlayingSubtitle;
    public bool IsPlaying => _owner.IsPlaying;
    public bool HasMedia => _owner.QueueItems.Count > 0;
    public ICommand PlayPauseCommand => _owner.PlayPauseCommand;
    public ICommand NextCommand => _owner.NextCommand;

    internal void NotifyChanged()
    {
        // Reserved for future INotifyPropertyChanged on dock tile.
    }
}
