// 2025/6/23 by Zhe Fang

using BetterLyrics.WinUI3.Enums;
using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using BetterLyrics.WinUI3.Models.Settings;
using BetterLyrics.WinUI3.Services.LiveStatesService;
using BetterLyrics.WinUI3.Services.MediaSessionsService;
using BetterLyrics.WinUI3.Services.SettingsService;
using BetterLyrics.WinUI3.ViewModels;
using BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel;
using BetterLyrics.WinUI3.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.Mvvm.Messaging.Messages;
using CommunityToolkit.WinUI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System.Collections.Generic;
using Vanara.PInvoke;
using Windows.Foundation;
using Windows.System;
using Windows.UI;
using WinRT.Interop;
using WinUIEx;

namespace BetterLyrics.WinUI3
{
    public partial class LyricsWindowViewModel
        : BaseWindowViewModel,
            IRecipient<PropertyChangedMessage<List<string>>>,
            IRecipient<PropertyChangedMessage<ElementTheme>>
    {
        private readonly IMediaSessionsService _mediaSessionsService;
        private readonly ISettingsService _settingsService;
        private readonly ILiveStatesService _liveStatesService;

        private ForegroundWindowWatcher? _fgWindowWatcher = null;

        public LyricsWindowViewModel(ISettingsService settingsService, IMediaSessionsService mediaSessionsService, ILiveStatesService liveStatesService)
        {
            _settingsService = settingsService;
            _mediaSessionsService = mediaSessionsService;
            _liveStatesService = liveStatesService;

            AppSettings = _settingsService.AppSettings;
            LiveStates = _liveStatesService.LiveStates;

            IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
            OnIsImmersiveModeChanged(_settingsService.AppSettings.GeneralSettings.IsImmersiveMode);

            _mediaSessionsService.IsPlayingChanged += PlaybackService_IsPlayingChanged;
        }

        private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
        {
            WindowHelper.SetLyricsWindowVisibilityByPlayingStatus();
        }

        [ObservableProperty] public partial AppSettings AppSettings { get; set; }

        [ObservableProperty] public partial LiveStates LiveStates { get; set; }

        /// <summary>
        /// 歌词窗口所在的背景主题色
        /// </summary>
        [ObservableProperty][NotifyPropertyChangedRecipients] public partial Color BackdropAccentColor { get; set; }

        [ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsImmersiveMode { get; set; }

        [ObservableProperty] public partial double TopCommandGridOpacity { get; set; }

        [ObservableProperty] public partial ElementTheme ThemeType { get; set; } = ElementTheme.Default;

        [ObservableProperty] public partial double TitleBarFontSize { get; set; } = 11;

        [ObservableProperty] public partial Visibility CloseButtonVisibility { get; set; } = Visibility.Visible;

        partial void OnIsImmersiveModeChanged(bool value)
        {
            if (value)
            {
                TopCommandGridOpacity = 0f;
            }
            else
            {
                TopCommandGridOpacity = 1f;
            }
        }

        public void InitShortcuts()
        {
            UpdateLyricsWindowBorderlessShortcut();
            UpdateLyricsWindowClickThroughShortcut();
            UpdateLyricsWindowShowHideShortcut();
            UpdateLyricsWindowSwitchShortcut();
        }

        private void UpdateLyricsWindowShowHideShortcut()
        {
            GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowShowOrHide,
                _settingsService.AppSettings.GeneralSettings.ShowOrHideLyricsWindowShortcut,
                () =>
                {
                    var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
                    if (window == null) return;

                    if (window.Visible)
                    {
                        window.Hide();
                    }
                    else
                    {
                        WindowHelper.OpenOrShowWindow<LyricsWindow>();
                    }
                }
            );
        }

        private void UpdateLyricsWindowBorderlessShortcut()
        {
            GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.Borderless,
                _settingsService.AppSettings.GeneralSettings.BorderlessShortcut,
                () =>
                {
                    LiveStates.LyricsWindowStatus.IsBorderless = !LiveStates.LyricsWindowStatus.IsBorderless;
                }
            );
        }

        private void UpdateLyricsWindowClickThroughShortcut()
        {
            GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.ClickThrough,
                _settingsService.AppSettings.GeneralSettings.ClickThroughShortcut,
                () =>
                {
                    LiveStates.LyricsWindowStatus.IsClickThrough = !LiveStates.LyricsWindowStatus.IsClickThrough;
                }
            );
        }

        private void UpdateLyricsWindowSwitchShortcut()
        {
            GlobalHotKeyHelper.UpdateHotKey<LyricsWindow>(ShortcutID.LyricsWindowSwitch,
                _settingsService.AppSettings.GeneralSettings.LyricsWindowSwitchShortcut,
                () =>
                {
                    WindowHelper.OpenOrShowWindow<LyricsWindowSwitchWindow>();
                }
            );
        }

        public void InitFgWindowWatcher()
        {
            var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
            if (window == null) return;

            var hwnd = WindowNative.GetWindowHandle(window);
            _fgWindowWatcher = new ForegroundWindowWatcher(
                hwnd,
                fgHwnd =>
                {
                    _dispatcherQueueTimer.Debounce(() =>
                    {
                        if (_liveStatesService.LiveStates.LyricsWindowStatus.IsAlwaysOnTop &&
                            _liveStatesService.LiveStates.LyricsWindowStatus.IsAlwaysOnTopPolling &&
                            window.AppWindow.Presenter is OverlappedPresenter presenter)
                        {
                            presenter.IsAlwaysOnTop = true;
                        }
                        UpdateBackdropAccentColor(hwnd);
                    }, Constants.Time.DebounceTimeout);
                }
            );
            _fgWindowWatcher.Start();
            UpdateBackdropAccentColor(hwnd);
        }

        public void UpdateBackdropAccentColor(nint hwnd)
        {
            BackdropAccentColor = ColorHelper.GetAccentColor(
                hwnd,
                _liveStatesService.LiveStates.LyricsWindowStatus.MonitorDeviceName,
                _liveStatesService.LiveStates.LyricsWindowStatus.EnvironmentSampleMode).ToColor();
        }

        public void ExitOrClose()
        {
            if (_settingsService.AppSettings.GeneralSettings.ExitOnLyricsWindowClosed)
            {
                WindowHelper.ExitApp();
            }
            else
            {
                var window = WindowHelper.GetWindowByWindowType<LyricsWindow>();
                window?.Hide();
            }
        }

        public void RefreshLyricsWindowStatus()
        {
            _liveStatesService.RefreshLyricsWindowStatus();
        }

        [RelayCommand]
        private void OnImmersiveToggleButtonEnabledChanged()
        {
            _settingsService.AppSettings.GeneralSettings.IsImmersiveMode = IsImmersiveMode;
        }

        public void Receive(PropertyChangedMessage<List<string>> message)
        {
            if (message.Sender is GeneralSettings)
            {
                if (message.PropertyName == nameof(GeneralSettings.ClickThroughShortcut))
                {
                    UpdateLyricsWindowClickThroughShortcut();
                }
            }
            else if (message.Sender is GeneralSettings)
            {
                if (message.PropertyName == nameof(GeneralSettings.BorderlessShortcut))
                {
                    UpdateLyricsWindowBorderlessShortcut();
                }
            }
            else if (message.Sender is GeneralSettings)
            {
                if (message.PropertyName == nameof(GeneralSettings.ShowOrHideLyricsWindowShortcut))
                {
                    UpdateLyricsWindowShowHideShortcut();
                }
            }
            else if (message.Sender is GeneralSettings)
            {
                if (message.PropertyName == nameof(GeneralSettings.LyricsWindowSwitchShortcut))
                {
                    UpdateLyricsWindowSwitchShortcut();
                }
            }
        }

        public void Receive(PropertyChangedMessage<ElementTheme> message)
        {
            if (message.Sender is LyricsRendererViewModel)
            {
                if (message.PropertyName == nameof(LyricsRendererViewModel.ThemeTypeSent))
                {
                    ThemeType = message.NewValue;
                }
            }
        }
    }
}
