using System.Collections.ObjectModel;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.Logging;
using SharepointToolbox.Core.Messages;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Services;
using SharepointToolbox.Views.Dialogs;

namespace SharepointToolbox.ViewModels;

public partial class MainWindowViewModel : ObservableRecipient
{
    private readonly ProfileService _profileService;
    private readonly SessionManager _sessionManager;
    private readonly ILogger<MainWindowViewModel> _logger;

    // Set by the view layer (MainWindow.xaml.cs) to open the dialog using DI
    public Func<Window>? OpenProfileManagementDialog { get; set; }

    /// <summary>
    /// Factory set by MainWindow.xaml.cs to open the SitePickerDialog for global site selection.
    /// Returns the opened Window; ViewModel calls ShowDialog() on it.
    /// </summary>
    public Func<Window>? OpenGlobalSitePickerDialog { get; set; }

    [ObservableProperty]
    private TenantProfile? _selectedProfile;

    [ObservableProperty]
    private string _connectionStatus = "Not connected";

    [ObservableProperty]
    private string _progressStatus = string.Empty;

    [ObservableProperty]
    private int _progressPercentage;

    public ObservableCollection<TenantProfile> TenantProfiles { get; } = new();

    public ObservableCollection<SiteInfo> GlobalSelectedSites { get; } = new();

    /// <summary>
    /// Label for toolbar display: "3 site(s) selected" or "No sites selected" (localized).
    /// </summary>
    public string GlobalSitesSelectedLabel =>
        GlobalSelectedSites.Count > 0
            ? string.Format(Localization.TranslationSource.Instance["toolbar.globalSites.count"], GlobalSelectedSites.Count)
            : Localization.TranslationSource.Instance["toolbar.globalSites.none"];

    public IAsyncRelayCommand ClearSessionCommand { get; }
    public RelayCommand ManageProfilesCommand { get; }
    public RelayCommand OpenGlobalSitePickerCommand { get; }

    public MainWindowViewModel(
        ProfileService profileService,
        SessionManager sessionManager,
        ILogger<MainWindowViewModel> logger)
    {
        _profileService = profileService;
        _sessionManager = sessionManager;
        _logger = logger;

        ClearSessionCommand = new AsyncRelayCommand(ClearSessionAsync, () => SelectedProfile != null);
        ManageProfilesCommand = new RelayCommand(OpenProfileManagement);
        OpenGlobalSitePickerCommand = new RelayCommand(ExecuteOpenGlobalSitePicker, () => SelectedProfile != null);
        GlobalSelectedSites.CollectionChanged += (_, _) =>
        {
            OnPropertyChanged(nameof(GlobalSitesSelectedLabel));
            BroadcastGlobalSites();
        };

        IsActive = true;
    }

    protected override void OnActivated()
    {
        base.OnActivated();
        Messenger.Register<ProgressUpdatedMessage>(this, (r, m) =>
        {
            var vm = (MainWindowViewModel)r;
            vm.ProgressStatus = m.Value.Message;
            vm.ProgressPercentage = m.Value.Total > 0
                ? (int)(100.0 * m.Value.Current / m.Value.Total)
                : 0;
        });
    }

    partial void OnSelectedProfileChanged(TenantProfile? value)
    {
        if (value != null)
        {
            WeakReferenceMessenger.Default.Send(new TenantSwitchedMessage(value));
        }
        ClearSessionCommand.NotifyCanExecuteChanged();
        // Clear global site selection on tenant switch (sites belong to a tenant)
        GlobalSelectedSites.Clear();
        OpenGlobalSitePickerCommand.NotifyCanExecuteChanged();
    }

    public async Task LoadProfilesAsync()
    {
        try
        {
            var profiles = await _profileService.GetProfilesAsync();
            TenantProfiles.Clear();
            foreach (var profile in profiles)
                TenantProfiles.Add(profile);

            if (TenantProfiles.Count > 0)
                SelectedProfile = TenantProfiles[0];
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to load tenant profiles.");
        }
    }

    private async Task ClearSessionAsync()
    {
        if (SelectedProfile == null) return;
        try
        {
            await _sessionManager.ClearSessionAsync(SelectedProfile.TenantUrl);
            GlobalSelectedSites.Clear();
            ConnectionStatus = "Not connected";
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Failed to clear session for {TenantUrl}.", SelectedProfile.TenantUrl);
        }
    }

    private void OpenProfileManagement()
    {
        if (OpenProfileManagementDialog == null) return;
        var dialog = OpenProfileManagementDialog();
        dialog.Owner = Application.Current.MainWindow;
        dialog.ShowDialog();

        // Reload profiles after dialog closes (modal — ShowDialog blocks until closed)
        _ = LoadProfilesAsync();
    }

    private void ExecuteOpenGlobalSitePicker()
    {
        if (OpenGlobalSitePickerDialog == null) return;
        var dialog = OpenGlobalSitePickerDialog.Invoke();
        if (dialog?.ShowDialog() == true && dialog is SitePickerDialog picker)
        {
            GlobalSelectedSites.Clear();
            foreach (var site in picker.SelectedUrls)
                GlobalSelectedSites.Add(site);
        }
    }

    private void BroadcastGlobalSites()
    {
        WeakReferenceMessenger.Default.Send(
            new GlobalSitesChangedMessage(GlobalSelectedSites.ToList().AsReadOnly()));
    }
}
