using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Sonex.Client.Controls.DataGridView;
using Sonex.Client.Dialogs;
using Sonex.Data.Records;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Logger = Sonex.Client.Helpers.Logger;

namespace Sonex.Client.Pages.Administrator.Accounts;

public sealed partial class Sessions : Page
{
    private bool _isLoading;

    public Sessions()
    {
        try
        {
            InitializeComponent();

            SendMessageButton.Click += SendMessageButton_Click;
            LogoutSelectedButton.Click += LogoutSelectedButton_Click;
            CloseSelectedButton.Click += CloseSelectedButton_Click;
            DataGrid.ItemsType = typeof(ActiveSessionRecord);
            DataGrid.Loaded += DataGrid_Loaded;
            DataGrid.RefreshRequested += DataGrid_RefreshRequested;
            DataGrid.OnChangeSelection += DataGrid_OnChangeSelection;
            UpdateActionButtons();
        }
        catch (Exception ex)
        {
            Logger.Error(
                ex,
                source: nameof(Sessions),
                operation: "Sessions.ctor");
        }
    }

    private async void DataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        await LoadSessionsAsync();
    }

    private void DataGrid_OnChangeSelection(object? sender, DataGridView.DataGridStateChangedEventArgs e)
    {
        UpdateActionButtons(e.SelectedRowsCount > 0);
    }

    private async void DataGrid_RefreshRequested(object? sender, EventArgs e)
    {
        await LoadSessionsAsync();
    }

    private async void SendMessageButton_Click(object sender, RoutedEventArgs e)
    {
        var selectedSessions = GetSelectedSessions();
        if (selectedSessions.Count == 0)
            return;

        var dialog = SendSessionsMessageDialog.CreateForSessions(selectedSessions);
        dialog.XamlRoot = Content.XamlRoot;

        await dialog.ShowAsync();
    }

    private async void LogoutSelectedButton_Click(object sender, RoutedEventArgs e)
    {
        await SendToSelectedInstancesAsync(
            "Logout",
            "Do you want to log out the selected instances?",
            "Logout",
            static session => session.SendLogout());
    }

    private async void CloseSelectedButton_Click(object sender, RoutedEventArgs e)
    {
        await SendToSelectedInstancesAsync(
            "Close app",
            "Do you want to close the application in the selected instances?",
            "Close app",
            static session => session.SendClose());
    }

    private async Task LoadSessionsAsync()
    {
        if (_isLoading)
            return;

        _isLoading = true;

        try
        {
            DataGrid.RefreshButtonEnabled = false;
            DataGrid.LoadingRing = true;
            DataGrid.ItemsType = typeof(ActiveSessionRecord);

            var result = await ActiveSessionRecord.GetAll();
            await this.ShowMessageAsync(result);
            Debug.WriteLine(result.Items.Count);
            DataGrid.ItemsSource = result.Items;
            UpdateActionButtons();
        }
        finally
        {
            DataGrid.LoadingRing = false;
            DataGrid.RefreshButtonEnabled = true;
            _isLoading = false;
        }
    }

    private void UpdateActionButtons(bool? hasSelectionOverride = null)
    {
        var hasSelection = hasSelectionOverride ?? GetSelectedSessions().Count > 0;

        SendMessageButton.IsEnabled = hasSelection;
        LogoutSelectedButton.IsEnabled = hasSelection;
        CloseSelectedButton.IsEnabled = hasSelection;
    }

    private List<ActiveSessionRecord> GetSelectedSessions()
    {
        return DataGrid.GetSelectedItems<ActiveSessionRecord>();
    }

    private List<ActiveSessionRecord> GetSelectedInstances()
    {
        var selectedInstances = new List<ActiveSessionRecord>();
        var usedInstanceIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        foreach (var session in GetSelectedSessions())
        {
            var instanceId = session.GetRequiredInstanceId();
            if (string.IsNullOrWhiteSpace(instanceId))
                continue;

            if (!usedInstanceIds.Add(instanceId))
                continue;

            selectedInstances.Add(session);
        }

        return selectedInstances;
    }

    private async Task SendToSelectedInstancesAsync(
        string dialogTitle,
        string question,
        string buttonText,
        Func<ActiveSessionRecord, Task> action)
    {
        var sessions = GetSelectedInstances();
        if (sessions.Count == 0)
        {
            await this.ShowMessageAsync(
                "No valid instances",
                "None of the selected sessions has an instance identifier.");
            return;
        }

        var confirm = new ContentDialog
        {
            XamlRoot = Content.XamlRoot,
            Title = dialogTitle,
            Content = $"{question} Number of instances: {sessions.Count}.",
            PrimaryButtonText = buttonText,
            CloseButtonText = "Cancel",
            DefaultButton = ContentDialogButton.Close
        };

        var result = await confirm.ShowAsync();
        if (result != ContentDialogResult.Primary)
            return;

        try
        {
            foreach (var session in sessions)
                await action(session);
        }
        catch (Exception ex)
        {
            string errorId = Logger.Error(
                ex,
                source: nameof(Sessions),
                operation: nameof(SendToSelectedInstancesAsync));
            await this.ShowMessageAsync("Error", Logger.BuildUserMessage(errorId));
        }
    }
}
