using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using CamBooth.App.Core.AppSettings;
using CamBooth.App.Core.Logging;
using CamBooth.App.Features.Camera;
using CamBooth.App.Features.DebugConsole;
using CamBooth.App.Features.LiveView;
using CamBooth.App.Features.PhotoPrismUpload;
using CamBooth.App.Features.PictureGallery;

namespace CamBooth.App;

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private readonly Logger _logger;
    private readonly AppSettingsService _appSettings;
    private readonly PictureGalleryService _pictureGalleryService;
    private readonly CameraService _cameraService;
    private readonly PhotoPrismUploadService _photoPrismUploadService;
    private readonly MainWindowViewModel _viewModel;

    private LiveViewPage? _liveViewPage;
    private bool _isCameraStarted;
    private bool _isPicturePanelVisible;
    private bool _isDebugConsoleVisible;
    private bool _isShutdownSliderOpen;

    private const string ShutdownGlyphClosed = "\uE7E8";
    private const string ShutdownGlyphOpen = "\uE711";
    private const double ShutdownSliderOffset = 160;


    public MainWindow(
        Logger logger,
        AppSettingsService appSettings,
        PictureGalleryService pictureGalleryService,
        CameraService cameraService,
        PhotoPrismUploadService photoPrismUploadService,
        MainWindowViewModel viewModel)
    {
        _logger = logger;
        _appSettings = appSettings;
        _pictureGalleryService = pictureGalleryService;
        _cameraService = cameraService;
        _photoPrismUploadService = photoPrismUploadService;
        _viewModel = viewModel;

        InitializeComponent();

        // Wire ViewModel events to UI
        _viewModel.LoadingProgressChanged += (status, count) =>
        {
            LoadingStatusText.Text = status;
            LoadingCountText.Text = count;
        };
        _viewModel.InitializationCompleted += () =>
        {
            LoadingOverlay.Visibility = Visibility.Collapsed;
            WelcomeOverlay.Visibility = Visibility.Visible;
        };
        _viewModel.GalleryPromptRequested += () => GalleryPrompt.Visibility = Visibility.Visible;
        _viewModel.GalleryPromptDismissed += () => GalleryPrompt.Visibility = Visibility.Collapsed;

        // Wire service events
        _pictureGalleryService.NewPhotoCountChanged += OnNewPhotoCountChanged;
        TimerControlRectangleAnimation.OnTimerEllapsed += OnTimerElapsed;

        // Initial UI state
        _isDebugConsoleVisible = _appSettings.IsDebugConsoleVisible;
        SetVisibilityDebugConsole(_isDebugConsoleVisible);
        SetVisibilityPicturePanel(false);
        DebugCloseButton.Visibility = Visibility.Collapsed;
        HideDebugButton.Visibility = _appSettings.IsDebugConsoleVisible ? Visibility.Visible : Visibility.Collapsed;

        Closing += OnClosing;

        _ = _viewModel.InitializeAsync();
        _logger.Info($"config file loaded: '{appSettings.ConfigFileName}'");
        _logger.Info("MainWindow initialized");
    }


    #region Event handlers

    private void OnTimerElapsed()
    {
        SwitchButtonAndTimerPanel();
        try
        {
            // Focus is guaranteed complete before the timer fires (bounded timeout).
            _viewModel.TakePhotoAfterTimer();
            TriggerShutterFlash();
        }
        catch (Exception ex)
        {
            _logger.Error(ex.Message);
            System.Windows.MessageBox.Show("Sorry, da ging was schief! Bitte nochmal probieren.");
        }
    }

    private void OnNewPhotoCountChanged(object? sender, int count)
    {
        NewPhotosBadge.Visibility = count > 0 ? Visibility.Visible : Visibility.Collapsed;
        if (count > 0)
            NewPhotoCountText.Text = count.ToString();
    }

    private void OnClosing(object? sender, CancelEventArgs e)
    {
        try
        {
            _cameraService.CloseSession();
        }
        catch (Exception ex)
        {
            _logger.Error($"Fehler beim Schließen der Kamera-Session: {ex.Message}");
        }

        _liveViewPage?.Dispose();
    }

    // XAML-bound handlers
    private void StartExperience(object sender, RoutedEventArgs e)
    {
        StartLiveViewIfNeeded();
        WelcomeOverlay.Visibility = Visibility.Collapsed;
        ButtonPanel.Visibility = Visibility.Visible;
        ActionButtonsContainer.Visibility = Visibility.Visible;
        //ShutdownDock.Visibility = Visibility.Visible;
    }

    private void StartTakePhotoProcess(object sender, RoutedEventArgs e)
    {
        if (_viewModel.IsPhotoProcessRunning) return;

        ClosePicturePanel();
        _viewModel.StartPhotoProcess();
        SwitchButtonAndTimerPanel();
        TimerControlRectangleAnimation.StartTimer(_appSettings.PhotoCountdownSeconds);

        // Autofocus runs silently in the background during the countdown.
        // The effective timeout is capped so focus always completes before the timer fires.
        _ = _viewModel.BeginFocusAsync(
            _appSettings.FocusDelaySeconds,
            _appSettings.FocusTimeoutMs,
            _appSettings.PhotoCountdownSeconds);
    }

    private void SetVisibilityPicturePanel(object sender, MouseButtonEventArgs e) =>
        SetVisibilityPicturePanel(!_isPicturePanelVisible);

    private void SetVisibilityDebugConsole(object sender, RoutedEventArgs e)
    {
        _isDebugConsoleVisible = !_isDebugConsoleVisible;
        SetVisibilityDebugConsole(_isDebugConsoleVisible);
    }

    // private void ToggleShutdownSlider(object sender, RoutedEventArgs e)
    // {
    //     _isShutdownSliderOpen = !_isShutdownSliderOpen;
    //     ShutdownToggleButton.Content = _isShutdownSliderOpen ? ShutdownGlyphOpen : ShutdownGlyphClosed;
    //     var animation = new DoubleAnimation
    //     {
    //         To = _isShutdownSliderOpen ? 0 : ShutdownSliderOffset,
    //         Duration = TimeSpan.FromMilliseconds(250),
    //         EasingFunction = new QuadraticEase()
    //     };
    //     ShutdownSliderTransform.BeginAnimation(TranslateTransform.XProperty, animation);
    // }

    // private async void ShutdownWindows(object sender, RoutedEventArgs e)
    // {
    //     bool confirmed = await ShutdownConfirmOverlay.ShowAsync();
    //     if (!confirmed) return;
    //
    //     try
    //     {
    //         _cameraService.CloseSession();
    //     }
    //     catch
    //     {
    //     }
    //
    //     var (args, errorMsg) = _appSettings.IsShutdownEnabled
    //         ? ("/s /t 0", "Windows konnte nicht heruntergefahren werden.")
    //         : ("/l", "Abmeldung fehlgeschlagen.");
    //
    //     try
    //     {
    //         Process.Start(new ProcessStartInfo
    //         {
    //             FileName = "shutdown",
    //             Arguments = args,
    //             CreateNoWindow = true,
    //             UseShellExecute = false
    //         });
    //     }
    //     catch (Exception ex)
    //     {
    //         _logger.Error(ex.Message);
    //         System.Windows.MessageBox.Show(errorMsg);
    //     }
    // }

    private void ShowQRCode(object sender, MouseButtonEventArgs e)
    {
        try
        {
            var qrCodeImage = _photoPrismUploadService.GenerateAlbumQRCode();
            if (qrCodeImage == null)
            {
                System.Windows.MessageBox.Show(
                    "QR-Code konnte nicht generiert werden. Bitte überprüfe die PhotoPrism-Konfiguration.",
                    "Fehler", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
                return;
            }

            var content = new StackPanel { HorizontalAlignment = HorizontalAlignment.Center };
            content.Children.Add(new System.Windows.Controls.Image
            {
                Source = qrCodeImage,
                Width = 400,
                Height = 400,
                Margin = new Thickness(0, 0, 0, 20)
            });
            content.Children.Add(new System.Windows.Controls.TextBlock
            {
                Text = "Nimm dein Handy und halte die Kamera auf den Code.\n" +
                       "Tippe dann auf den Link, der erscheint - schon siehst du alle Fotos.",
                Foreground = Brushes.White,
                FontSize = 18,
                LineHeight = 26,
                TextAlignment = TextAlignment.Center,
                TextWrapping = TextWrapping.Wrap,
                MaxWidth = 420
            });

            QRCodeOverlay.DialogContent = content;
            QRCodeOverlay.Show();
        }
        catch (Exception ex)
        {
            _logger.Error($"Fehler beim Anzeigen des QR-Codes: {ex.Message}");
            System.Windows.MessageBox.Show(
                $"Fehler beim Anzeigen des QR-Codes: {ex.Message}",
                "Fehler", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        }
    }

    private async void OpenGalleryFromPrompt(object sender, RoutedEventArgs e)
    {
        _viewModel.DismissGalleryPrompt();
        SetVisibilityPicturePanel(true);
        await Task.Delay(300);
        await ShowLatestPhotoDialogAsync();
    }

    private void CloseApp(object sender, RoutedEventArgs e) => Close();

    #endregion


    #region UI helpers

    private void StartLiveViewIfNeeded()
    {
        if (_isCameraStarted) return;
        try
        {
            _liveViewPage = new LiveViewPage(_logger, _cameraService);
            MainFrame.Navigate(_liveViewPage);
            _isCameraStarted = true;
        }
        catch (Exception ex)
        {
            _logger.Error($"Failed to start live view: {ex.Message}\n{ex.StackTrace}");
            System.Windows.MessageBox.Show(
                $"Failed to initialize camera. Please ensure the camera is properly connected.\n\nError: {ex.Message}",
                "Camera Connection Error", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Error);
        }
    }

    public void ClosePicturePanel()
    {
        if (PicturePanel.Content is PictureGalleryPage page)
            page.CloseOpenDialog();
        if (PicturePanel.Content is null) return;
        SetVisibilityPicturePanel(false);
    }

    private void SetVisibilityPicturePanel(bool visible)
    {
        if (visible)
        {
            _viewModel.DismissGalleryPrompt();
            PicturePanel.Navigate(new PictureGalleryPage(_appSettings, _logger, _pictureGalleryService,
                _photoPrismUploadService));
            _pictureGalleryService.ResetNewPhotoCount();
            ButtonPanel.Visibility = Visibility.Hidden;
            ActionButtonsContainer.Visibility = Visibility.Hidden;
            //ShutdownDock.Visibility = Visibility.Hidden;
        }
        else
        {
            PicturePanel.ClearValue(ContentProperty);
            ButtonPanel.Visibility = Visibility.Visible;
            ActionButtonsContainer.Visibility = Visibility.Visible;
            //ShutdownDock.Visibility = Visibility.Visible;
        }

        _isPicturePanelVisible = visible;
    }

    private void SetVisibilityDebugConsole(bool visible)
    {
        if (!_appSettings.IsDebugConsoleVisible) return;
        if (visible)
            DebugFrame.Navigate(new DebugConsolePage(_logger));
        else
            DebugFrame.ClearValue(ContentProperty);
    }

    private void SwitchButtonAndTimerPanel()
    {
        ButtonPanel.Visibility = ButtonPanel.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
        ActionButtonsContainer.Visibility = ActionButtonsContainer.Visibility == Visibility.Hidden
            ? Visibility.Visible
            : Visibility.Hidden;
        TimerPanel.Visibility = TimerPanel.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
    }

    /// <summary>Briefly flashes the screen white to simulate a camera shutter.</summary>
    private void TriggerShutterFlash()
    {
        FlashOverlay.BeginAnimation(OpacityProperty,
            new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(450))
            {
                EasingFunction = new PowerEase { Power = 2, EasingMode = EasingMode.EaseIn }
            });
    }

    private async Task ShowLatestPhotoDialogAsync()
    {
        try
        {
            await _pictureGalleryService.LoadThumbnailsToCache(1);
            var latestPhotos = _pictureGalleryService.ThumbnailsOrderedByNewestDescending;
            if (latestPhotos.Count == 0)
            {
                _logger.Error("No photos found in gallery");
                return;
            }

            var latestPhoto = latestPhotos[0];
            if (latestPhoto.UriSource == null)
            {
                _logger.Error("Latest photo UriSource is null");
                return;
            }

            var photoPath = Uri.UnescapeDataString(latestPhoto.UriSource.AbsolutePath);
            if (PicturePanel.Content is PictureGalleryPage galleryPage)
                await galleryPage.ShowPhotoDialogAsync(photoPath);
        }
        catch (Exception ex)
        {
            _logger.Error($"Error showing photo dialog: {ex.Message}");
        }
    }

    #endregion
}
