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

namespace Sonex.Client.Pages.Administrator.System;

public sealed partial class Services : Page
{
    private const int ServicesLimit = 1000;
    private CancellationTokenSource? _loadServicesCts;
    private bool _isUnloaded;

    public Services()
    {
        try
        {
            InitializeComponent();

            DetailsTabView.ItemType = typeof(ServiceRecord);
            DataGrid.ItemsType = typeof(ServiceRecord);
            RootFilter.SetColumns(BuildServiceFilterColumns(), BuildDefaultFilters());
            RootFilter.FilterChanged += RootFilter_FilterChanged;
            Unloaded += Services_Unloaded;
        }
        catch (Exception ex)
        {
            Logger.Error(
                ex,
                source: nameof(Services),
                operation: "Services.ctor");
        }
    }

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

    private async void RootFilter_FilterChanged(object? sender, EventArgs e)
    {
        if (_isUnloaded)
        {
            return;
        }

        await LoadServicesAsync();
    }

    private async void RefreshButton_Click(object sender, RoutedEventArgs e)
    {
        await LoadServicesAsync();
    }

    private async Task LoadServicesAsync()
    {
        _isUnloaded = false;
        _loadServicesCts?.Cancel();
        _loadServicesCts?.Dispose();
        _loadServicesCts = new CancellationTokenSource();
        var ct = _loadServicesCts.Token;

        SetRefreshButtonsEnabled(false);
        DataGrid.LoadingRing = true;
        DataGrid.ItemsType = typeof(ServiceRecord);

        try
        {
            var filter = RootFilter.BuildSql();
            var result = await ServiceRecord.GetAll(
                ServicesLimit,
                filter.WhereSql,
                filter.Parameters,
                ct);

            if (ct.IsCancellationRequested || _isUnloaded)
            {
                return;
            }

            await this.ShowMessageAsync(result);
            Debug.WriteLine(result.ErrorData ?? $"Loaded services: {result.Items.Count}");
            DataGrid.ItemsSource = result.Items;
            DetailsView.Clear();
        }
        finally
        {
            if (!ct.IsCancellationRequested && !_isUnloaded)
            {
                DataGrid.LoadingRing = false;
                SetRefreshButtonsEnabled(true);
            }
        }
    }

    private void DataGrid_OnChangeActiveRow(object sender, DataGridView.DataGridStateChangedEventArgs e)
    {
        if (e.Row is ServiceRecord row)
        {
            DetailsView.Load(row);
        }
        else
        {
            DetailsView.Clear();
        }
    }

    private void Services_Unloaded(object sender, RoutedEventArgs e)
    {
        _isUnloaded = true;
        _loadServicesCts?.Cancel();
        _loadServicesCts?.Dispose();
        _loadServicesCts = null;

        DataGrid.LoadingRing = false;
        DataGrid.ItemsSource = null;
        DataGrid.ItemsType = null;
        DetailsView.Clear();
    }

    private void SetRefreshButtonsEnabled(bool isEnabled)
    {
        DataGrid.RefreshButtonEnabled = isEnabled;
        RefreshDetailsButton.IsEnabled = isEnabled;
    }

    private static IReadOnlyList<SqlFilterColumn> BuildServiceFilterColumns()
    {
        return
        [
            new("Caption", "caption", typeof(string)),
            new("Description", "description", typeof(string)),
            new("Name", "name", typeof(string)),
            new("Status", "status", typeof(string)),
            new("Started", "started", typeof(bool)),
            new("Start mode", "start_mode", typeof(string)),
            new("Can pause", "accept_pause", typeof(bool)),
            new("Can stop", "accept_stop", typeof(bool)),
            new("Display name", "display_name", typeof(string)),
            new("Error control", "error_control", typeof(string)),
            new("Exit code", "exit_code", typeof(int)),
            new("Path", "path_name", typeof(string)),
            new("Service exit code", "service_specific_exit_code", typeof(int)),
            new("Start account", "start_name", typeof(string)),
            new("State", "state", typeof(string)),
            new("Delayed auto start", "delayed_auto_start", typeof(bool)),
            new("Process ID", "process_id", typeof(int))
        ];
    }

    private static IReadOnlyList<SqlFilterDefaultRule> BuildDefaultFilters()
    {
        return
        [
            new("name", SqlFilterComparison.Contains),
            new("display_name", SqlFilterComparison.Contains),
            new("status", SqlFilterComparison.Contains)
        ];
    }
}
