using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Localization;
using SharepointToolbox.Services;
using SharepointToolbox.ViewModels.Dialogs;

namespace SharepointToolbox.Views.Dialogs;

/// <summary>
/// Dialog for selecting multiple SharePoint sites.
/// Delegates loading and filter/sort logic to <see cref="SitePickerDialogLogic"/>
/// so the code-behind only handles WPF plumbing.
/// </summary>
public partial class SitePickerDialog : Window
{
    private readonly SitePickerDialogLogic _logic;
    private List<SitePickerItem> _allItems = new();
    private string _sortColumn = "Url";
    private ListSortDirection _sortDirection = ListSortDirection.Ascending;

    /// <summary>
    /// Returns the list of sites the user checked before clicking OK.
    /// </summary>
    public IReadOnlyList<SiteInfo> SelectedUrls =>
        _allItems.Where(i => i.IsSelected).Select(i => new SiteInfo(i.Url, i.Title)
        {
            StorageUsedMb = i.StorageUsedMb,
            StorageQuotaMb = i.StorageQuotaMb,
            Template = i.Template
        }).ToList();

    public SitePickerDialog(ISiteListService siteListService, TenantProfile profile)
    {
        InitializeComponent();
        _logic = new SitePickerDialogLogic(siteListService, profile);
    }

    private async void Window_Loaded(object sender, RoutedEventArgs e) => await LoadSitesAsync();

    private async Task LoadSitesAsync()
    {
        StatusText.Text = TranslationSource.Instance["sitepicker.status.loading"];
        LoadButton.IsEnabled = false;
        try
        {
            var items = await _logic.LoadAsync(
                new Progress<OperationProgress>(),
                System.Threading.CancellationToken.None);
            _allItems = items.ToList();
            ApplyFilter();
            StatusText.Text = string.Format(
                CultureInfo.CurrentUICulture,
                TranslationSource.Instance["sitepicker.status.loaded"],
                _allItems.Count);
        }
        catch (InvalidOperationException ex)
        {
            StatusText.Text = ex.Message;
        }
        catch (Exception ex)
        {
            StatusText.Text = string.Format(
                CultureInfo.CurrentUICulture,
                TranslationSource.Instance["sitepicker.status.error"],
                ex.Message);
        }
        finally
        {
            LoadButton.IsEnabled = true;
        }
    }

    private void ApplyFilter()
    {
        var text = FilterBox.Text.Trim();
        var minMb = SitePickerDialogLogic.ParseLongOrDefault(MinSizeBox.Text, 0);
        var maxMb = SitePickerDialogLogic.ParseLongOrDefault(MaxSizeBox.Text, long.MaxValue);
        var kindFilter = (TypeFilter.SelectedItem as ComboBoxItem)?.Tag as string ?? "All";

        var filtered = SitePickerDialogLogic.ApplyFilter(_allItems, text, minMb, maxMb, kindFilter);
        var sorted = SitePickerDialogLogic.ApplySort(filtered, _sortColumn, _sortDirection);
        var list = sorted.ToList();

        SiteList.ItemsSource = list;
        if (_allItems.Count > 0)
            StatusText.Text = string.Format(
                CultureInfo.CurrentUICulture,
                TranslationSource.Instance["sitepicker.status.shown"],
                list.Count, _allItems.Count);
    }

    private void SiteList_ColumnHeaderClick(object sender, RoutedEventArgs e)
    {
        if (e.OriginalSource is not GridViewColumnHeader header) return;
        if (header.Role == GridViewColumnHeaderRole.Padding) return;
        if (header.Tag is not string column || string.IsNullOrEmpty(column)) return;

        if (_sortColumn == column)
        {
            _sortDirection = _sortDirection == ListSortDirection.Ascending
                ? ListSortDirection.Descending
                : ListSortDirection.Ascending;
        }
        else
        {
            _sortColumn = column;
            _sortDirection = ListSortDirection.Ascending;
        }
        ApplyFilter();
    }

    private void FilterBox_TextChanged(object sender, TextChangedEventArgs e) => ApplyFilter();
    private void SizeBox_TextChanged(object sender, TextChangedEventArgs e) => ApplyFilter();
    private void TypeFilter_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (!IsLoaded) return;
        ApplyFilter();
    }

    private void SelectAll_Click(object sender, RoutedEventArgs e)
    {
        if (SiteList.ItemsSource is IEnumerable<SitePickerItem> visible)
        {
            foreach (var item in visible) item.IsSelected = true;
        }
        ApplyFilter();
    }

    private void DeselectAll_Click(object sender, RoutedEventArgs e)
    {
        if (SiteList.ItemsSource is IEnumerable<SitePickerItem> visible)
        {
            foreach (var item in visible) item.IsSelected = false;
        }
        ApplyFilter();
    }

    private async void LoadButton_Click(object sender, RoutedEventArgs e) => await LoadSitesAsync();

    private void OK_Click(object sender, RoutedEventArgs e)
    {
        DialogResult = true;
        Close();
    }
}

/// <summary>
/// Mutable wrapper for a site entry shown in the SitePickerDialog list.
/// Supports two-way CheckBox binding via INotifyPropertyChanged.
/// </summary>
public class SitePickerItem : INotifyPropertyChanged
{
    private bool _isSelected;

    public string Url { get; init; } = string.Empty;
    public string Title { get; init; } = string.Empty;
    public long StorageUsedMb { get; init; }
    public long StorageQuotaMb { get; init; }
    public string Template { get; init; } = string.Empty;

    public SiteKind Kind => SiteKindHelper.FromTemplate(Template);
    public string KindDisplay => SiteKindHelper.DisplayName(Kind);
    public string SizeDisplay => FormatSize(StorageUsedMb);

    public bool IsSelected
    {
        get => _isSelected;
        set
        {
            if (_isSelected == value) return;
            _isSelected = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSelected)));
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    public SitePickerItem(string url, string title, long storageUsedMb = 0, long storageQuotaMb = 0, string template = "")
    {
        Url = url;
        Title = title;
        StorageUsedMb = storageUsedMb;
        StorageQuotaMb = storageQuotaMb;
        Template = template;
    }

    private static string FormatSize(long mb)
    {
        if (mb <= 0) return "—";
        if (mb >= 1024) return $"{mb / 1024.0:F1} GB";
        return $"{mb} MB";
    }
}
